Diferencia entre revisiones de «CRUD en Javascript i Firebase»

De Jose Castillo Aliaga
Ir a la navegación Ir a la búsqueda
Línea 131: Línea 131:
La tasca del model passa per definir les classes, la manera d'aconseguir les dades del servidor i les dades que ja tenim. Tindrà funcions per a fer el CRUD contra el servidor i getters i setters per a obtindre o crear objectes de les classes. Amés, pot implementar el patró '''[https://es.wikipedia.org/wiki/Observer_(patr%C3%B3n_de_dise%C3%B1o) Observer]''' per mantindre als altres informats dels canvis.
La tasca del model passa per definir les classes, la manera d'aconseguir les dades del servidor i les dades que ja tenim. Tindrà funcions per a fer el CRUD contra el servidor i getters i setters per a obtindre o crear objectes de les classes. Amés, pot implementar el patró '''[https://es.wikipedia.org/wiki/Observer_(patr%C3%B3n_de_dise%C3%B1o) Observer]''' per mantindre als altres informats dels canvis.


A l'hora de fer el '''model''' ens podem plantejar si és interessant mantindre'l sols per a la definició de les dades i dividir-ho en model - servici per gestionar l'accés al servidor en una classe separada. D'aquesta manera, el controlador demanarà coses al servici el qual mantindrà instàncies del model. Es pot fer tot junt, però d'aquesta manera s'entén millor el rol de cadascun. En el nostre cas, el model quedarà de forma testimonial, ja que el servici serà el que arreplegue les dades del servidor. Això és paregut amb el que passa en Angular, el model es pot equiparar a les Interfícies i els servicis ho fan tot. Com que en Javascript no hi ha tipat de dades ni interfícies, el model queda sols per a coses internes concretes de les dades que no passen en el servidor ni en la vista. Per exemple, el càlcul aleatori d'un identificador o similars.
A l'hora de fer el '''model''' ens podem plantejar si és interessant mantindre'l sols per a la definició de les dades i dividir-ho en model - servici per gestionar l'accés al servidor en una classe separada. D'aquesta manera, el controlador demanarà coses al servici el qual mantindrà instàncies del model. Es pot fer tot junt, però d'aquesta manera s'entén millor el rol de cadascun. En el nostre cas, el model quedarà de forma testimonial, ja que el servici serà el que arreplegue les dades del servidor. Això és paregut amb el que passa en Angular, el model es pot equiparar a les Interfícies i els servicis ho fan tot. Com que en Javascript no hi ha tipat de dades ni interfícies, el model queda sols per a coses internes concretes de les dades que no passen en el servidor ni en la vista. Per exemple, el càlcul aleatori d'un identificador o similars.


=== Vista ===
=== Vista ===

Revisión del 08:43 20 may 2021

Aquest article és un tutorial i no pretén aprofundir en la teoria de Javascript o de Firebase. Sols explicarem les coses que necessitem per a l'objectiu.

Les possibilitats quan ens plantegem cóm fer una web amb frontend fet en Javascript i un backend. En aquest article sols anem a tractar una: Frontend fet en Javascript pur a partir de ES6 front a un API REST generat per una base de dades Realtime del servici Firebase. Els avantatges de fer-ho així són:

  • Quasi total compatibilitat en qualsevol navegador amb un cost de computació mínim, ja que no necessitem llibreries externes ni frameworks.
  • Simplicitat si el projecte és menut.
  • Velocitat i alta disponibilitat de les dades gràcies a un servici extern molt fiable.
  • Simplicitat al tractar amb una base de dades en JSON.
  • Avantatges dels protocols REST.
  • No tindre que programar un backend tradicional (PHP o JAVA, MySQL...)

Els desavantatges són:

  • No comptar amb els beneficis d'un framework com Angular, Vue o React que simplifiquen la programació de grans projectes.
  • Possibilitat de fer-ho mal o insegur al no utilitzar llibreries per comunicar amb el servidor.
  • Dependència d'un servici extern.
  • No poder programar el backend i comptar sols amb una simple base de dades que s'ha de gestionar en el frontend.

Tan sols anem a fer una gestió de productes i llistes de productes amb la possibilitat de Crear Llegir Actualitzar i Esborrar (CRUD).

Configuració de Firebase

La documentació de Firebase és molt completa i de gran qualitat, per tant no cal entrar en detalls. Sols cal crear una base de dades Realtime a la que, de moment, li ficarem com a regles de control d'accés que tots puguen llegir i escriure sense autenticar:

{
  "rules": {
    ".read": "now < 1621116000000",  // 2021-5-16
    ".write": "now < 1621116000000",  // 2021-5-16
  }
}

En l'exemple anterior tenen un límit de data que es pot ampliar si volem.

En quant a les dades de la base de dades, anem a començar en un JSON molt simple de productes i llistes de productes:

{"listas":{"Lista1":{"nombre":"lista1","productos":[1,2,3,4]},"Lista2":{"nombre":"lista2","productos":[1,2,3,5]}},"productos":{"1":{"id":1,"marca":"Nikon","precio":649.95,"referencia":"D3400"},"2":{"id":2,"marca":"Nikon","precio":6499.95,"referencia":"D5"},"3":{"id":3,"marca":"Nikon","precio":1999.95,"referencia":"D500"},"4":{"id":4,"marca":"Nikon","precio":1049.95,"referencia":"D7200"},"5":{"id":5,"marca":"Nikon","precio":1999.95,"referencia":"D500"},"6":{"id":6,"marca":"Canon","precio":3999.95,"referencia":"EOS 5D"},"7":{"id":7,"marca":"Canon","precio":1800.95,"referencia":"EOS 7D"},"8":{"id":8,"marca":"Canon","precio":2645.95,"referencia":"EOS 80D"},"9":{"id":9,"marca":"Canon","precio":989.95,"referencia":"EOS Rebel T6"},"10":{"id":10,"marca":"Canon","precio":753.95,"referencia":"EOS-1D"},"11":{"id":11,"marca":"Canon","precio":457.95,"referencia":"EOS 1D X"}}}

És important que els elements del JSON tinguen clau:valor, és a dir, no utilitzem [] a no ser que siguen ja valors molt concrets.

En aquest cas, tenim unes llistes de productes que apunten als identificadors dels productes. Com es veu, la clau de cada producte és igual al valor de l'atribut id del producte, això és redundant i es pot llevar. En versions posteriors el llevarem.

Amb aquestes dades, si volem accedir a:

  • La llista de tots els productes anirem a la URL: http://<url de firebase>/productos.json
  • Un producte en concret: http://<url de firebase>/productos/2.json
  • La llista de productes de lista1: http://<url de firebase>/listas/Lista1/productos.json

Ho podem provar amb curl:

curl https://<url>/listas/Lista1/productos.json

O amb algun programa més còmode per fer moltes proves com és Postman


Pàgina web HTML inicial

El que anem a fer és confiar totalment la càrrega de les dades a Javascript amb les tècniques de AJAX. Per tant, l'HTML inicial serà molt simple. No obstant, utilitzarem Bootstrap per fer el disseny més agradable sense esforç. Necessitem un div contenidor on anar generant les llistes i els productes que inicialment el deixarem buit. També farem un menú per seleccionar el que necessitem.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/css/bootstrap.min.css" rel="stylesheet"
        integrity="sha384-eOJMYsd53ii+scO/bJGFsiCZc+5NDVN2yr8+0RDqr0Ql0h+rP48ckxlpbzKgwra6" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/js/bootstrap.bundle.min.js"
        integrity="sha384-JEW9xMcG8R+pH31jmWH6WWP0WintQrMb4s7ZOdauHnUtxwoG2vI5DkLtS3qm9Ekf"
        crossorigin="anonymous"></script>
   <script src="script.js"></script>

</head>

<body>
    <header>
        <nav class="navbar navbar-expand-lg navbar-light bg-light">
            <div class="container-fluid">
                <a class="navbar-brand" href="#">Navbar</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse"
                    data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent"
                    aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="collapse navbar-collapse" id="navbarSupportedContent">
                    <ul class="navbar-nav me-auto mb-2 mb-lg-0">
                        <li class="nav-item">
                            <a class="nav-link active" aria-current="page" href="#">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link" href="#">Todos los productos</a>
                        </li>
                        <li class="nav-item dropdown">
                            <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button"
                                data-bs-toggle="dropdown" aria-expanded="false">
                                Listas
                            </a>
                            <ul class="dropdown-menu" aria-labelledby="navbarDropdown">
                                <li><a class="dropdown-item" href="#">Action</a></li>
                                <li><a class="dropdown-item" href="#">Another action</a></li>
                                <li>
                                    <hr class="dropdown-divider">
                                </li>
                                <li><a class="dropdown-item" href="#">Something else here</a></li>
                            </ul>
                        </li>
                    </ul>

                </div>
            </div>
        </nav>
    </header>
    <main>
        <section>
            <div id="container">

            </div>
        </section>

    </main>
</body>
</html>

Es tracta d'una web molt simple amb un menú superior en el que podem mostrar tots els productes, les llistes i un menú desplegable on ficarem un enllaç a cada llista.

Estructura del Javascript

Encara que siga una aplicació simple anem a intentar respectar els principis de MVC. D'aquesta manera, anem a fer un model per a productes i llistes encarregat de la comunicació amb el servidor, un controlador encarregat de comunicar el model en la vista i una vista encarregada de transformar les dades en elements del DOM i de proporcionar interacció amb l'usuari.

Per a fer-ho encara més fàcil de mantindre, podem fer una classe genèrica de model, vista i controlador per compartir coses comuns entre les diferents classes com l'accés al servidor o els mètodes de dibuixar o refrescar.

Model

La tasca del model passa per definir les classes, la manera d'aconseguir les dades del servidor i les dades que ja tenim. Tindrà funcions per a fer el CRUD contra el servidor i getters i setters per a obtindre o crear objectes de les classes. Amés, pot implementar el patró Observer per mantindre als altres informats dels canvis.

A l'hora de fer el model ens podem plantejar si és interessant mantindre'l sols per a la definició de les dades i dividir-ho en model - servici per gestionar l'accés al servidor en una classe separada. D'aquesta manera, el controlador demanarà coses al servici el qual mantindrà instàncies del model. Es pot fer tot junt, però d'aquesta manera s'entén millor el rol de cadascun. En el nostre cas, el model quedarà de forma testimonial, ja que el servici serà el que arreplegue les dades del servidor. Això és paregut amb el que passa en Angular, el model es pot equiparar a les Interfícies i els servicis ho fan tot. Com que en Javascript no hi ha tipat de dades ni interfícies, el model queda sols per a coses internes concretes de les dades que no passen en el servidor ni en la vista. Per exemple, el càlcul aleatori d'un identificador o similars.

Vista

La vista sols s'encarrega de mostrar les dades i d'informar de les interaccions de l'usuari. Les interaccions que suposen un canvi en les dades o una petició al servidor no seran ateses per la vista. No obstant la vista sí pot atendre alguns esdeveniments relacionats amb la interfície.

La vista tindrà algun mecanisme de notificacions cap al controlador. En el nostre cas, en principi el que farem és associar funcions del controlador a esdeveniments. D'aquesta manera la vista detecta l'esdeveniment i executa el callback que el controlador li ha manat.

Per una altra banda, la vista ha de ser notificada dels canvis de les dades en el model-servici o el controlador. Això serà amb funcions públiques que seran invocades pel controlador.

Controlador

La construcció del controlador cridarà als constructors de la vista i del model-servici. El controlador té com a funció bàsica connectar la vista en el model i, si cal, fer la lògica del negoci en mig. En el nostre exemple, el controlador serà molt lleuger però imprescindible. El constructor del controlador relacionarà els esdeveniments del model i la vista entre ells. Per fer-ho més senzill d'entendre, es crearan unes funcions intermedies que seran enviades com a callback al model o a la vista.



https://www.natapuntes.es/patron-mvc-en-vanilla-javascript/

https://github.com/Fictizia/Curso-JS-Avanzado-para-desarrolladores-Front-end_ed3/blob/master/teoria/clase18.md

https://github.com/Fictizia/Curso-JS-Avanzado-para-desarrolladores-Front-end_ed3