Mat Selection List无法存储全部选中值 嵌套JSON多选问题求助
Hey there, let's sort out why your selection list is only keeping one group's selected values at a time. The core issue here is that you're binding all your nested selection lists to the same single variable (like a single ngModel or form control). Every time you select options from a new group, it replaces the entire array instead of adding to it.
Solution 1: Maintain a Global Selected Array with Selection Change Events
This approach lets you manually handle adding/removing selected values across all groups:
In your parent component TS:
import { MatSelectionListChange } from '@angular/material/list'; // Your nested service categories data serviceCategories = [ { name: 'Category 1', services: [{ id: 1, name: 'Service 1' }, { id: 2, name: 'Service 2' }] }, { name: 'Category 2', services: [{ id: 3, name: 'Service 3' }, { id: 4, name: 'Service 4' }] } ]; // Global array to store all selected service IDs selectedServices: number[] = []; onServiceSelectionChange(event: MatSelectionListChange, groupServices: any[]) { // Get all IDs from the current group const groupServiceIds = groupServices.map(service => service.id); // Remove any previously selected IDs from this group this.selectedServices = this.selectedServices.filter(id => !groupServiceIds.includes(id)); // Add the newly selected IDs from this group const newlySelectedIds = event.source.selectedOptions.selected.map(option => option.value); this.selectedServices.push(...newlySelectedIds); // Optional: Ensure no duplicates (though selection change should handle this) this.selectedServices = [...new Set(this.selectedServices)]; }In your parent component template:
<mat-selection-list *ngFor="let category of serviceCategories" (selectionChange)="onServiceSelectionChange($event, category.services)" > <div mat-subheader>{{ category.name }}</div> <mat-list-option *ngFor="let service of category.services" [value]="service.id" > {{ service.name }} </mat-list-option> </mat-selection-list> <!-- Display all selected values --> <p>Selected Service IDs: {{ selectedServices }}</p>
Solution 2: Bind Each Group to Its Own Selection Array (Simpler)
If you prefer using ngModel, assign a unique selection array to each category group, then combine them when you need the full list:
Update your category data in TS:
serviceCategories = [ { name: 'Category 1', services: [{ id: 1, name: 'Service 1' }, { id: 2, name: 'Service 2' }], selectedIds: [] // Unique array for this group }, { name: 'Category 2', services: [{ id: 3, name: 'Service 3' }, { id: 4, name: 'Service 4' }], selectedIds: [] // Unique array for this group } ]; // Get all selected IDs across all groups get allSelectedServices() { return this.serviceCategories.flatMap(category => category.selectedIds); }Update your template:
<mat-selection-list *ngFor="let category of serviceCategories" [(ngModel)]="category.selectedIds" [multiple]="true" > <div mat-subheader>{{ category.name }}</div> <mat-list-option *ngFor="let service of category.services" [value]="service.id" > {{ service.name }} </mat-list-option> </mat-selection-list> <!-- Display combined selected values --> <p>Selected Service IDs: {{ allSelectedServices }}</p>
Either of these approaches will let you collect all selected values across groups—when you select all options, you'll get the expected [1,2,3,4] array instead of just one group's values.
内容的提问来源于stack exchange,提问作者Amrutha

