Parte 1: Presentazione di MatTree
Tradizionale SELEZIONARE gli elementi hanno a lungo consentito selezioni multiple tramite il multiplo attributo. I mezzi per selezionare più opzioni possono variare a seconda del sistema operativo e del browser.
Per esempio:
- Per Windows, gli utenti dovrebbero tenere premuto il controllo (Ctrl) per selezionare più opzioni.
- Per Mac, tenere premuto il pulsante di comando per selezionare più opzioni.
Questa non era la soluzione più semplice o più accessibile, quindi i creatori di Angular Material mat-select caselle di controllo utilizzate in modalità di selezione multipla. In effetti, abbiamo usato un tale controllo nel Testo angolare con selezione del tappetino: personalizza l’aspetto articolo:
In questa serie, lavoreremo con un controllo che si comporta allo stesso modo, ma è più adatto alla visualizzazione di dati gerarchici: il MatTree. In questa puntata, impareremo a conoscere i diversi tipi di MatAlberi nonché come configurare l’origine dati sottostante. Da lì, incorporeremo le caselle di controllo nel nostro albero. Infine, apriremo l’albero all’interno di a MatMenu come sostituto del MatSelect.
Dati raggruppati e gerarchie in Angular
Il MatSelect può visualizzare i dati gerarchici fino a un punto utilizzando il
L’evidente limitazione del
Come puoi vedere, sembra simile a una selezione multipla MatSelect in quanto il nostro controllo utilizza le caselle di controllo come meccanismo di selezione. Al contrario, i nodi mat-tree di base contengono solo testo privo di qualsiasi mezzo per selezionarli:
Leggi: Crea un MatMenu con le caselle di controllo
Alberi piatti e alberi nidificati in Angular
Esistono due tipi di alberi: albero piatto e albero nidificato. Ciascuno di questi due tipi di alberi impiega diverse strutture DOM:
- albero piattoIn un albero piatto, la gerarchia è appiattita in modo che i nodi non vengano visualizzati in una configurazione padre-figlio, ma piuttosto come fratelli in sequenza. Il “livello” di ogni nodo dell’albero viene letto attraverso il getLevel() metodo del TreeControl; questo livello può essere utilizzato per definire lo stile del nodo in modo che sia rientrato al livello appropriato.
- albero nidificatoIn un albero nidificato, i nodi figli sono posizionati all’interno del loro nodo padre nel DOM. Il nodo padre ha uno sbocco per mantenere tutti i nodi figli.
A questo punto probabilmente ti starai chiedendo perché qualcuno dovrebbe usare un albero nidificato se l’albero piatto fornisce la stessa funzionalità? Personalmente mi piace il fatto che il DOM dell’albero nidificato si avvicini meglio alla sua gerarchia. Inoltre, indipendentemente dal fatto che l’HTML sia statico o reso dinamico, ci sono alcuni vantaggi principali definiti per un albero nidificato:
- È possibile sfruttare il bubbling degli eventi, che può ridurre notevolmente la quantità di codice necessaria per acquisire l’interazione dell’utente con il DOM. L’annidamento semplifica inoltre l’acquisizione di più eventi.
- Hai un maggiore controllo sulla formattazione essendo in grado di applicare lo stile ai nodi padre che verranno ereditati dagli elementi figlio.
- Gli alberi nidificati sono molto utili quando si utilizzano preprocessori CSS come LESS o Sass, poiché riducono notevolmente la quantità di stili necessari per essere scritti.
- Mentre le prestazioni tra il rendering dei due alberi possono essere le stesse, quando devi considerare gli utenti con connessioni lente o un servizio mobile scadente, la regola empirica è che meno elementi DOM sono, meglio è.
Leggi: Gestione dello stato angolare con NgRx
Formato dei dati
Il MatTree si aspetta un array in cui ogni elemento rappresenta un oggetto nodo. Il tipo di oggetto che puoi usare non è vincolato in alcun modo, a patto che tu gli dica quale tipo di oggetto aspettarsi e come recuperare i nodi figlio. Quindi, andrà bene una classe o un’interfaccia. Nella nostra app, utilizzeremo un’interfaccia chiamata Nodo Veicolo. Eccolo di seguito, insieme all’intero array di dati:
interface VehicleNode { name: string; id?: number; selected?: boolean; indeterminate?: boolean; children?: VehicleNode[]; parent?: VehicleNode; } const TREE_DATA: VehicleNode[] = [ { name: "Infiniti", children: [ { name: "G50", children: [ { name: "Pure AWD", id: 1 }, { name: "Luxe", id: 2 } ] }, { name: "QX50", children: [ { name: "Pure AWD", id: 3 }, { name: "Luxe", id: 4 } ] } ] }, { name: "BMW", children: [ { name: "2 Series", children: [ { name: "Coupé", id: 5 }, { name: "Gran Coupé", id: 6 } ] }, { name: "3 Series", children: [ { name: "Sedan", id: 7 }, { name: "PHEV", id: 8 } ] } ] } ];
Inizializzazione dell’albero
Ci sono due oggetti molto importanti che dovrai inizializzare per avere un albero funzionante: questi sono i Nested TreeControl e MatTreeNestedDataSource.
Il TreeControl controlla lo stato di espansione/compressione dei nodi dell’albero, consentendo agli utenti di espandere e comprimere i nodi dell’albero in modo ricorsivo. Per farlo, devi passare una funzione al getChildren() metodo tramite il NestedTreeControl’s costruttore. La tua funzione di funzione può restituire un osservabile di figli per un dato nodo, o semplicemente un array di oggetti figli.
Il MatTreeNestedDataSource gestisce i dati sottostanti dell’albero, ovvero l’array di oggetti. Di nuovo, ha bisogno di sapere con quale tipo di oggetti sta lavorando, quindi dovresti istanziarlo con un generico che indica il tipo di oggetto prima di assegnare il tuo array alla sua proprietà dei dati:
Ecco come appare tutto questo nel nostro caso:
export class TreeNestedOverviewExample { treeControl = new NestedTreeControl<VehicleNode>(node => node.children); dataSource = new MatTreeNestedDataSource< VehicleNode>(); constructor() { this.dataSource.data = TREE_DATA; } //... }
C’è una demo con il nested di base MatTree in poi stackblitz.
Andare avanti con Mat-Tree e Angular
A questo punto, la nostra app mostra solo i nodi nidificati in modalità di sola lettura. Nel prossimo articolo aggiungeremo le caselle di controllo in modo che la nostra app possa tenere traccia delle selezioni degli utenti.