L’Angular Material MatMenu è un pannello mobile contenente un elenco di opzioni. È come la parte a discesa dell’elenco Seleziona, ma senza la casella di testo o la parte dell’etichetta che mostra l’elemento selezionato:

Assenti anche il pulsante freccia che apre l’elenco. Per questo motivo, il menu è in genere collegato a un HTMLElement che include matMenuTriggerFor direttiva, un tale pulsante, collegamento o qualsiasi altro elemento HTML interattivo:

<button mat-button [matMenuTriggerFor]="menu">Menu</button>

Il menu mat è ricco di tutti i tipi di proprietà, metodi e hook di eventi utili, che lo rendono un controllo altamente versatile. Il Documenti sul menu dei materiali angolari presentare alcune possibili varianti; ne troverai molti altri su vari siti Web e presenti in tutorial proprio come questo.

Recentemente, ho cercato di trovare un prototipo adatto per un menu che contenesse caselle di controllo. La cosa più vicina che ho trovato è stato ironicamente un controllo personalizzato che faceva parte di una delle applicazioni della mia organizzazione. Non era perfetto; mancava l’accessibilità della tastiera prevista, ma per il resto era perfettamente funzionante. Dopo aver ripristinato la funzionalità della tastiera persa, avevo proprio quello che volevo: un MatMenu che conteneva caselle di controllo. In questo tutorial, tratterò tutto ciò che devi sapere per crearne uno tuo.

Leggi: Come ottimizzare le applicazioni angolari.

Funzionalità di base MatmMenu in JavaScript

Il nostro menu conterrà un elenco di automobili premium. Verrà attivato tramite un pulsante che recita “Seleziona un veicolo”. Il testo del pulsante cambia quindi in “Chiudi menu” quando il menu è aperto, come mostrato nell’immagine seguente:

MatMenu in JavaScript Tutorial

Immagazziniamo i veicoli al pubblico premiumAutomobilesList variabile membro della classe come un array di oggetti. Una seconda variabile – Veicoli selezionati – memorizzerà i nomi dei veicoli selezionati:

public premiumAutomobilesList = [
  { title: 'Audi', activated: false, value: 'audi' },
  { title: 'Infiniti', activated: false, value: 'infiniti' },
  { title: 'BMW', activated: false, value: 'bmw' },
  { title: 'Mercedes', activated: false, value: 'mercedes' },
  { title: 'Lexus', activated: false, value: 'lexus' },
  { title: 'Alfa Romeo', activated: false, value: 'alfa romeo' },
  { title: 'Porsche', activated: false, value: 'porsche' },
];
private selectedVehicles: string[] = [];
public formattedSelectedVehicles: string = '';

Negli oggetti del veicolo di cui sopra, il titolo corrisponde all’etichetta della casella di controllo, attivato descrive lo stato della casella di controllo, ad es vero per controllato e falso per deselezionato, e il valore è ciò che viene restituito da una casella di controllo quando selezionata.

Aggiungiamo tre elementi al modello:

  1. il pulsante matMenuTrigger che apre e chiude il menu:
    <button #matMenuTrigger mat-raised-button color="primary" 
      [matMenuTriggerFor]="menu" 
      (menuOpened)="onMenuOpened()"
      (menuClosed)="onMenuClosed()">{{triggerButtonText}}</button>
    
  2. il pannello del menu:
    <mat-menu #menu="matMenu">
      <mat-checkbox #menuItems
        *ngFor="let item of premiumAutomobilesList; let i = index;"
        [(ngModel)]="item.activated"
        (click)="$event.stopPropagation()"
        (change)="onVehicleSelect()"
        (keydown)="onMenuKeyDown($event, i)"
        >{{ item.title }}</mat-checkbox
      >
    </mat-menu>
    
  3. un elemento paragrafo (

    ) che mostra i veicoli selezionati:

    <p>{{ formattedSelectedVehicles }}</p>
    

In termini di stile, la cosa più importante è che le caselle di controllo siano ordinate verticalmente come una colonna:

.mat-menu-panel {
  background: lightgray;
  margin-top: .3rem;
  
  .mat-menu-content {
    display: flex;
    flex-direction: column;
    padding: 0.5rem 1rem;
  }
}

Tracciamento delle selezioni utente in MatMenus

Puoi vedere nel markup HTML per il menu mat che il modificare l’evento è associato al metodo della classe onVehicleSelect(). Associa i veicoli selezionati a una serie di nomi di veicoli, gli stessi utilizzati per le etichette delle caselle di controllo:

public onVehicleSelect() {
  this.selectedVehicles = this.premiumAutomobilesList
    .filter(menuitem => menuitem.activated)
    .map(menuitem => menuitem.title);
}

Come accennato in precedenza, il attivato La proprietà agisce come il nostro modello, quindi gli elementi attivati ​​sono quelli che sono selezionati.

Interazione della tastiera in MatMenus

Forse uno dei motivi per cui non vediamo molti MatMenu che utilizzano caselle di controllo è che interrompono la navigazione da tastiera integrata. Secondo i documenti, queste sono le chiavi supportate e i loro effetti:

  1. DOWN_ARROW: mette a fuoco la voce di menu successiva
  2. UP_ARROW: mette a fuoco la voce di menu precedente
  3. RIGHT_ARROW: Apre il sottomenu della voce di menu
  4. LEFT_ARROW: Chiude il menu corrente, se è un sottomenu
  5. INVIO/SPAZIO: attiva la voce di menu focalizzata
  6. ESCAPE: Chiude il menu

È abbastanza facile da ripristinare associando l’evento keydown a un gestore. Ecco di cosa avremo bisogno:

@ViewChild('matMenuTrigger', { read: MatMenuTrigger })
private matMenuTriggerRef: MatMenuTrigger;
@ViewChildren('menuItems')
private menuItemsRef: QueryList<MatCheckbox>;
  
public onMenuKeyDown(event: KeyboardEvent, index: number) {
  switch (event.key) {
    case 'ArrowUp':
      if (index > 0) {
        this.setCheckboxFocus(index - 1);
      } else {
        this.menuItemsRef.last.focus();
      }
      break;
    case 'ArrowDown':
      if (index !== this.menuItemsRef.length - 1) {
        this.setCheckboxFocus(index + 1);
      } else {
        this.setFocusOnFirstItem();
      }
      break;
    case 'Enter':
      event.preventDefault();
      this.premiumAutomobilesList[index].activated
        = !this.premiumAutomobilesList[index].activated;
      this.onVehicleSelect();
      setTimeout(() => this.matMenuTriggerRef.closeMenu(), 200);
      break; 
  }
}

L’unica differenza tra il comportamento predefinito e il nostro è che, nella nostra app, il tasto Invio chiude il menu oltre a selezionare la voce attualmente focalizzata. Un leggero ritardo dà all’utente il tempo sufficiente per vedere che l’elemento è stato attivato.

MatMenu menuAperto e menuChiuso Eventi

Il fermalibro menuAperto e menuChiuso i gestori di eventi si occupano di impostare il focus e la stringa di output formattata dei veicoli selezionati:

@ViewChild('matMenuTrigger', { read: MatButton })
private matButtonRef: MatButton;
  
public onMenuOpened() {
  this.setFocusOnFirstItem();
  this.triggerButtonText="Close menu";
  this.formattedSelectedVehicles="";
}

public onMenuClosed() {   
  this.matButtonRef.focus();
  this.triggerButtonText="Select a vehicle";

  this.formattedSelectedVehicles =
    (this.selectedVehicles.length === 0
      ? 'No vehicles selected'
      : 'You selected ' + this.selectedVehicles.join(', ')) + '.';
}

Abbiamo bisogno di un secondo riferimento al pulsante matMenuTrigger perché il primo lo legge come un tipo MatMenuTrigger. Questo è così che possiamo invocare il suo metodo closeMenu() in risposta all’evento keydown Enter. Questa volta, dobbiamo accedere al metodo focus() di MatButton, che non è disponibile per MatMenuTrigger.

La dimostrazione

Troverai il menu dei veicoli premium su stackblitz.com.

MatMenu JavaScript Tutorial

Creare un MatMenu con caselle di controllo non è molto più difficile della tua varietà da giardino di base, a patto che tu sia disposto a fare un po’ di sforzo in più per gestire la navigazione da tastiera. In effetti, a meno che tu non stia implementando un menu a discesa multilivello, è davvero un processo abbastanza semplice.

Leggi: Cause comuni degli errori JavaScript e come evitarli

Source link

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.