Matthias
Matthias

Reputation: 3556

How to access selection options in material mat-selection-list

I am trying to access the selected options of a material mat-selection-list component (version 7). I have found documentation for selectedOptions here.

I have fiddeld together some lines of html/ts that seem to give me access to the desired data. However I do not think it is the right way. However I could not find advice using "famous search engine".

I have folloing HTML (pizza.component.html)

<h1>Pizzas</h1>
<mat-selection-list #pizzaList (selectionChange)="onPizzasChange($event)">
    <mat-list-option *ngFor="let pizza of pizzas">
        {{pizza}}
    </mat-list-option>
</mat-selection-list>

And corresponding typescript file (pizza.component.ts)

import { MatButtonModule } from '@angular/material/button';
import { Component, OnInit } from '@angular/core';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { Pizza } from '../pizza';

@Component({
    selector: 'app-pizza-view',
    templateUrl: './pizza-view.component.html',
    styleUrls: ['./pizza-view.component.css']
})

export class PizzaViewComponent implements OnInit {

    pizzas: any;

    constructor( ) { }

    ngOnInit() {
        pizzas = [ 'Margherita', 'Funghi', 'Quattro Stagioni', 'Calzone' ];
    }

    onPizzasChange(event) {
        console.log("selectedOptions:", event.option.selectionList.selectedOptions._selection;
    };

}

Question would be: How do I do it correctly?

PS: I am using @angular/core 7.0.0 and material 7.0.1

Upvotes: 13

Views: 29178

Answers (2)

frido
frido

Reputation: 14089

Start by adding a value for strings or ngValue for objects to your options.

<mat-list-option *ngFor="let pizza of pizzas" [value]="pizza"> or [ngValue]="pizza"

Option 1: Using selectionChange

Pass the array of the selected MatListOptions to your function.

<mat-selection-list #pizzaList (selectionChange)="onGroupsChange(pizzaList.selectedOptions.selected)">
    <mat-list-option *ngFor="let pizza of pizzas" [value]="pizza">
        {{pizza}}
    </mat-list-option>
</mat-selection-list>

You will get an array that contains the selected options in the order they were selected.

import { MatListOption } from '@angular/material/list'

onGroupsChange(options: MatListOption[]) {
  // map these MatListOptions to their values
  console.log(options.map(o => o.value));
}

Option 2: Using ngModel

As @Eliseo commented you could use ngModel for 2-way data binding if you only want access to the selected data but don't need to be notified about changes.

<mat-selection-list #pizzaList [(ngModel)]="selectedPizzas">
    <mat-list-option *ngFor="let pizza of pizzas" [value]="pizza">
        {{pizza}}
    </mat-list-option>
</mat-selection-list>
selectedPizzas: string[]; // this array will contain the selected pizzas

To additionally get notified about changes you could add ngModelChange:

<mat-selection-list #pizzaList [(ngModel)]="selectedPizzas" (ngModelChange)="onGroupsChange($event)">

You will get an array that contains the selected options' values in the order they appear in the input array pizzas (not in the order they were selected as with selectionChange).

onGroupsChange(selectedPizzas: string[]) {
  console.log(selectedPizzas);
}

Upvotes: 34

LppEdd
LppEdd

Reputation: 21104

Well, IMHO, the right way seems to be using the selectedOptions property of the MatSelectionList.

selectedOptions: SelectionModel<MatListOption>

In your example you're accessing a private property.
You can check out the sources of SelectionModel to see what you're able to use.

The right method seems to be

/** Selected values. */
get selected(): T[] {
  if (!this._selected) {
    this._selected = Array.from(this._selection.values());
  }

  return this._selected;
}

The event is typed as MatSelectionListChange, so:

onPizzasChange(event: MatSelectionListChange) {
    console.log("selectedOptions:", event.source.selectedOptions.selected();
};

PS: unlike the other answer, I prefer keeping the template as clean as possible.

All the properties accesses might be done inside the component. Which is also easier to read and understand.

Upvotes: 8

Related Questions