Sommario
< Home
Stampa

Componenti

Partendo dal modello di funzionamento della pagina web (evento, azione, reazione) e la programmazione con le funzioni (funzioni) possiamo progettare applicazioni web che si basano sul concetto di componente.

Un componente è una porzione della pagina web indipendente dalle altre che viene gestita interamente da un solo oggetto Javascript, appunto il componente.

Il componente è un elemento autoconclusivo della applicazione Web, collegato ad un elemento della pagina, che gestisce autonomamente, tramite un oggetto, l’interazione con l’utente e la gestione delle logiche applicative ad esso collegate. Ad esempio un componente potrebbe essere una tabella, una form, un elemento contenente informazioni dinamiche, un elenco. Inoltre i componenti possono essere anche contenitori di altri componenti, come ad esempio tabelle complesse, dove ogni riga è essa stessa un componente. Il risultato a cui andremo ad arrivare è strutturare la pagina come nella seguente figura:

Le architetture a componenti sono alla base delle applicazioni Javascript moderne, e sono utilizzati da tutti i framework Javascript più diffusi, come React, Vue ed Angular.

In questa lezione vedremo come è possibile utilizzare i componenti anche con Javascript nativo, senza usare librerie esterne. Per funzionare useremo le Closure.

Un componente tabella

Un componente deve gestire l’intero ciclo di vita applicativo della porzione di pagina di cui si occupa, quindi sia la fase di render iniziale, sia la gestione di evento, azione e reazione. In questo esempio scriviamo una semplice tabella sotto forma di componente. Questa tabella avrà le seguenti proprietà private: parentElement (che contiene il riferimento all’elemento del DOM in cui essere inserita) e data (che contiene i dati della tabella, espressi come array bidimensionale, dove la prima riga contiene le intestazioni).

const createTable = (parentElement) => {
  let data;
  return {
    build: (dataInput) => {
      data = dataInput;
    },
    render: () => {
      let htmlTable = "<table>";
      htmlTable += data.map((row) => 
        "<tr>" + row.map((col) => 
          "<td>" + col + "</td>"
        ).join("")
      ).join("") + "</tr>";
      htmlTable += "</table";
      parentElement.innerHTML = htmlTable;
    }
  }
}

const table1 = createTable(document.querySelector("#table1"));
table1.build([["Cognome", "Voto"], ["Pogba", "6"], ["Vlahovic", 8], ["Thuram", 6.5]]);
table1.render();

const table2 = createTable(document.querySelector("#table2"));
table2.build([["Squadra", "punti"], ["Torino", 11], ["Napoli", 10], ["Udines", 10]]);
table2.render();

Come si può osservare abbiamo creato due oggetti tabella, associati a due contenitori distinti del DOM. E’ anche possibile rapidamente cambiare i dati usando il metodo build() ed eseguendo una nuova render().

Un componente form

In questo caso creiamo una semplice form che espone 3 metodi pubblici (setLabels, onsubmit e render) che gestiscono le label della form, la render e la onsubmit che associa la callback da eseguire una volta che l’utente ha cliccato. Qui il codice:

const createForm = (parentElement) => {
  let data;
  let callback = null;

  return {  
    setLabels: (labels) => { data = labels; },  
    onsubmit: (callbackInput) => { callback = callbackInput},
    render: () => { 
      parentElement.innerHTML = 
        data.map((name, index) => {
            return `<div>${name}\n<input id="${name}" type="text" /></div>`;
          }).join('\n')
          + "<button type='button' id='submit'>Submit</button>";  
      document.querySelector("#submit").onclick = () => {
// modo 1: lista di valori
        const result = data.map((name) => {
          return document.querySelector("#" + name).value;
        });
// modo 2 alternativo dizionario
        const result = {};
        data.forEach((name) => {
          result[name] = document.querySelector("#" + name).value;
        });
        callback(result);
      }          
    },
  };
};

const form = createForm(document.querySelector('#app'));
form.setLabels(["Nome", "Cognome", "Età"]);
form.onsubmit(console.log);
form.render();

Ricapitolando:

  • il metodo setLabels definisce le label associate agli input della form;
  • il metodo onSubmit serve per indicare all’oggetto form quale sarà la funzione callback da richiamare una volta che è stata effettuata la submit (cioè quando l’utente preme il pulsante submit)
  • il metodo render fa due cose:
    • crea la form dinamicamente in base alle labels definite sopra e la inserisce nel contenitore parentElement;
    • dopo il rendering, viene gestito il click al pulsante, che attiva una funzione che prima raccoglie i dati inseriti dall’utente nelle input e li mette in una lista, e poi richiama la funzione di callback memorizzata dal metodo onSubmit