Angolare: evidenziazione dei termini di ricerca nei nodi MatTree
Tempo di lettura: 4 minuti

Nel precedente articolo di questa serie, abbiamo utilizzato il getDescendants() di NestedTreeControl metodo per filtrare i nodi selezionati e quelli che corrispondono a una stringa di ricerca. Nel tutorial di sviluppo Web di oggi, faremo risaltare i termini di ricerca corrispondenti espandendo quei nodi ed evidenziando il testo corrispondente.

Potete leggere la prima parte di questa serie visitando: Filtraggio dei nodi NestedTreeControl del materiale angolare.

Espansione dei nodi abbinati in angolare

In genere, è bello vedere i nodi che stai cercando. Il problema è che quei nodi possono o non possono essere già espansi. Convenientemente, il NestedTreeControl offre un paio di metodi utili che possono aiutarci. Per esempio, isExpanded() ci dice se un dato nodo è visibile (cioè espanso) o meno. Potremmo applicarlo in pubblico hideParentNode() metodo in questo modo:

public hideParentNode(node: VehicleNode): boolean {
  const hide = this.treeControl
        .getDescendants(node)
        .filter(node => node.children == null || node.children.length === 0)
        .every(node => this.hideLeafNode(node));

  if (!hide && !this.treeControl.isExpanded(node)) {
    // expand the node
  }
  return hide;
}

Per espandere il nodo padre, il NestedTreeControl mette a disposizione expandDiscendenti(). Accetta un nodo ed espande il suo sottoalbero in modo ricorsivo in modo che anche tutti i suoi discendenti vengano espansi. Lo invocheremmo così:

this.treeControl.expandDescendants(node);

Mentre funziona, impedisce anche all’utente di collassare qualsiasi nodo che contiene testo corrispondente! Il motivo è quello hideParentNode() viene invocato da Angular molte volte mentre valuta e rivaluta le espressioni del modello. Una soluzione di gran lunga migliore consiste nell’associare il campo di testo a un gestore separato tramite il ngModelChange evento:

<label>Filter by:
    <input [(ngModel)]="searchString" (ngModelChange)="filterStringUpdate($event)" />
  </label>

Il ngModelChange $ evento riceve il valore del modello più recente e più grande, che in questo caso è il stringa di ricerca.

Un leggero intoppo all’espansione dei nodi corrispondenti qui è che non otteniamo più un riferimento ai singoli nodi. Pertanto, dobbiamo sostanzialmente eseguire la ricerca su tutti i nodi foglia per determinare quali mostrare. Il lato positivo è che abbiamo già un metodo in grado di controllare i nodi figlio per noi. Questo metodo è ovviamente hideParentNode(). Abbiamo ancora bisogno di alcuni nodi radice su cui eseguire l’iterazione. Quelli sono disponibili dal Controllo dell’albero o Fonte di dati. Useremo quest’ultimo:

public filterStringUpdate(searchString: string) {
    if (searchString) {
      this.dataSource.data.forEach(node => {
        if (!this.hideParentNode(node) 
         && !this.treeControl.isExpanded(node)
        ) {
          this.treeControl.expandDescendants(node);
        }
      });
    }
  }

Ora i rami si espanderanno non appena viene trovato il testo del nodo corrispondente:

Leggi: Filtra i nodi DOM usando un TreeWalker

Evidenziazione dei termini di ricerca abbinati in angolare e CSS

Oltre ad espandere i nodi dell’albero per mostrare le etichette dei nodi corrispondenti, possiamo anche evidenziare i termini di ricerca corrispondenti impostando il loro colore di sfondo. Potrebbe sembrare un compito arduo, ma, in Angular, è relativamente facile.

Probabilmente ci sono diversi modi per farlo, ma una soluzione è creare una pipe che accetti il ​​testo cercato come argomento e restituisca un SPAN elemento basato sul risultato di a espressione regolare o RegEx. Ecco il codice per una tale pipe:

import { Pipe, PipeTransform, SecurityContext } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';

@Pipe({
  name: 'highlight',
})
export class HighlightPipe implements PipeTransform {

  constructor(private sanitizer: DomSanitizer) { }

  transform(text: string, search: string): string {
    if (!search) {
      return text;
    }

    const regex = 
      new RegExp(
        this.sanitizer.sanitize(SecurityContext.HTML, search), 'gi'
      );
    const match = text.match(regex);

    if (!match) {
      return text;
    }

    return text.replace(regex, `<span class="highlight">${match[0]}</span>`);
  }
}

Leggere: Ottimizzazione dei modelli RegEx

Se guardi da vicino il codice sopra, noterai che ci sono tre dichiarazioni di ritorno. Questo perché la pipa non sa mai cosa otterrà:

  1. Potrebbe non esserci affatto una stringa di ricerca. In tal caso, restituiamo il testo completo e inalterato.
  2. Il termine di ricerca potrebbe non corrispondere a nessuna parte del testo. Ancora una volta, restituiamo il testo originale.
  3. Se la RegEx colpisce, avvolgiamo la parte abbinata all’interno SPAN tag e restituirlo.

Un’altra curiosità osservata nel trasformare() il metodo è il disinfettare() metodo. La sanificazione si riferisce alla modifica dell’input non attendibile in modo che sia reso sicuro l’inserimento nel DOM. Il metodo di sanificazione è esposto dal Disinfettante Dom class, motivo per cui viene iniettato tramite il costruttore.

Il tipo di sanificazione eseguita dipende dal contesto, perché un valore innocuo in CSS potrebbe essere potenzialmente pericoloso in un URL. Per tale motivo, il primo argomento del disinfettare() il metodo è un Contesto di sicurezza enum. Dal momento che stiamo generando markup HTML, il contesto corretto è SecurityContext.HTML.

Il Evidenzia Tubo restituisce una stringa, quindi non è sufficiente filtrare il nome.nodo attraverso il tubo. Ciò visualizzerà il SPAN markup come testo! Il modo per aggirare il problema è assegnare il valore convogliato a un elemento nidificato innerHTML proprietà. Non vogliamo modificare le caselle di controllo del tappetino innerHTML perché questo lo sostituirà con l’output del tubo di evidenziazione. Possiamo invece aggiungere a SPAN elemento che conterrà l’evidenziazione nidificata SPAN:

<mat-checkbox 
  class="checklist-leaf-node" 
  (change)="itemToggle($event.checked,node)" 
  [checked]="node.selected"
>
<span [innerHTML]="node.name | highlight: searchString"></span>
</mat-checkbox>

L’unica cosa che resta da fare ora è aggiungere il evidenziare regola di classe al stili.css file:

.highlight {
  background-color: rgba(255, 255, 0, 0.5);
  font-weight: bold;
}

Ciò darà al testo abbinato quel familiare evidenziatore giallo che tutti ricordiamo a scuola:

Come evidenziare i termini di ricerca con i CSS

C’è una demo del codice di oggi su stackblitz.

Conclusione

Nel tutorial sullo sviluppo Web di Angular di oggi, abbiamo imparato come far risaltare i termini di ricerca corrispondenti espandendo quei nodi ed evidenziando il testo del nodo. C’è voluto un po’ di ingegno, ma dove c’è una volontà, c’è sempre un modo!

Per saperne di più JavaScript e tutorial di sviluppo web angolare e guide alla programmazione.

Source link

Di Simone Serra

Web Designer Freelancer Realizzazione Siti Web Serra Simone Realizzo siti web, portali ed e-commerce con focus specifici sull’usabilità, l’impatto grafico, una facile gestione e soprattutto in grado di produrre conversioni visitatore-cliente. Elaboro siti internet, seguendo gli standard Web garantendo la massima compatibilità con tutti i devices. Sviluppo e-commerce personalizzati, multilingua, geolocalizzati per potervi mettere nelle migliori condizioni di vendita. Posiziono il tuo sito su Google per dare maggiore visibilità alla tua attività sui motori di ricerca con SEO di base o avanzato.