typescript - Comment implémenter tout sélectionner dans le menu déroulant Angular Material Angular 5
J'utilise mat-select pour afficher un menu déroulant, j'ai besoin de la fonctionnalité de tout sélectionner dans le menu déroulant Angular.
Ci-dessous est mon html
<mat-select formControlName="myControl" multiple (ngModelChange)="resetSelect($event, 'myControl')">
<mat-option>Select All</mat-option>
<mat-option [value]="1">Option 1</mat-option>
<mat-option [value]="2">Option 2</mat-option>
<mat-option [value]="3">Option 3</mat-option>
</mat-select>
Voici mon code ts
/**
* click handler that resets a multiple select
* @param {Array} $event current value of the field
* @param {string} field name of the formControl in the formGroup
*/
protected resetSelect($event: string[], field: string) {
// when resetting the value, this method gets called again, so stop recursion if we have no values
if ($event.length === 0) {
return;
}
// first option (with no value) has been clicked
if ($event[0] === undefined) {
// reset the formControl value
this.myFormGroup.get(field).setValue([]);
}
}
D'une manière ou d'une autre, cela ne fonctionne pas correctement, veuillez m'aider ou me faire savoir s'il y a une meilleure façon de faire cela.
Réponse #1
Utilisez l'événement de clic, essayez ceci
<mat-form-field>
<mat-select placeholder="Toppings" [formControl]="toppings" multiple>
<mat-option [value]="1" (click)="selectAll(ev)"
#ev
>SelectAll</mat-option>
<mat-option *ngFor="let topping of toppingList" [value]="topping">{{topping}}</mat-option>
</mat-select>
</mat-form-field>
}
Typescript :
selectAll(ev) {
if(ev._selected) {
this.toppings.setValue(['Extra cheese', 'Mushroom', 'Onion', 'Pepperoni', 'Sausage', 'Tomato']);
ev._selected=true;
}
if(ev._selected==false) {
this.toppings.setValue([]);
}
}
Exemple : https://stackblitz.com/edit/angular-czmxfp
Réponse #2
J'ai étendu le MatSelect d'Angular Material pour inclure les fonctionnalités suivantes :
- Recherche
- Regroupement
- Tout sélectionner
- Sélectionnez toutes les options d'un groupe
Un exemple fonctionnel peut être trouvé ici sur StackBlitz et le référentiel complet peut être trouvé ici sur GitHub
Voici le fragment de code de l’implémentation de « Tout sélectionner »
HTML
<button *ngIf="isGroup && values.length" mat-icon-button (click)="toggleGroup()">
<mat-icon>
{{ isCollapsed ? 'chevron_right' : 'expand_more' }}
</mat-icon>
</button>
<ng-container *ngIf="values.length" [ngSwitch]="isMultiple">
<mat-checkbox *ngSwitchCase="true" disableRipple matRipple class="mat-option" color="primary"
[ngClass]="{ 'mat-selected': isIndeterminate() || isChecked() }" [indeterminate]="isIndeterminate()"
[checked]="isChecked()" (click)="$event.stopPropagation()" (change)="toggleSelection($event)">
{{text}}
</mat-checkbox>
<span *ngSwitchDefault>
{{text}}
</span>
</ng-container>
TS
import { Component, Input, ViewEncapsulation, OnChanges, SimpleChanges, ChangeDetectionStrategy, ChangeDetectorRef, OnInit, OnDestroy } from '@angular/core';
import { FormControl } from '@angular/forms';
import { MatCheckboxChange } from '@angular/material';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
// tslint:disable-next-line:component-selector
selector: 'mat-select-check',
templateUrl: './mat-select-check.component.html',
styleUrls: ['./mat-select-check.component.css'],
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class MatSelectCheckComponent implements OnChanges, OnInit, OnDestroy {
@Input() selectControl: FormControl;
@Input() values = [];
@Input() text = 'Select All';
@Input() isGroup = false;
@Input() groupData: any;
@Input() dataKey = 'Key';
@Input() isMultiple?: boolean;
private _onDestroy = new Subject<void>();
isCollapsed = false;
constructor(private changeDetectorRef: ChangeDetectorRef) { }
ngOnChanges(changes: SimpleChanges) {
if (changes && changes.values && changes.values.currentValue && changes.values.currentValue.length) {
this.values = changes.values.currentValue.map(z => z[this.dataKey]);
}
setTimeout(() => {
this.changeDetectorRef.detectChanges();
});
}
ngOnInit() {
if (this.selectControl) {
this.selectControl.valueChanges
.pipe(takeUntil(this._onDestroy))
.subscribe(value => setTimeout(() => {
this.changeDetectorRef.detectChanges();
}));
}
}
ngOnDestroy() {
this._onDestroy.next();
this._onDestroy.complete();
}
isChecked(): boolean {
const hasValues = this.selectControl.value && this.values.length && this.selectControl.value.length;
if (hasValues) {
const length = this.selectControl.value.filter(x => this.values.includes(x)).length;
return length > 0 && length === this.values.length;
}
return false;
}
isIndeterminate(): boolean {
const hasValues = this.selectControl.value && this.values.length && this.selectControl.value.length;
if (hasValues) {
const length = this.selectControl.value.filter(x => this.values.includes(x)).length;
return length > 0 && length < this.values.length;
}
return false;
}
toggleSelection(change: MatCheckboxChange): void {
if (change.checked) {
const newValue = this.selectControl.value ? [...this.selectControl.value, ...this.values] : [...this.values];
this.selectControl.setValue(Array.from(new Set(newValue)));
} else {
this.selectControl.setValue(this.selectControl.value.filter(x => !this.values.includes(x)));
}
}
toggleGroup() {
this.isCollapsed = !this.isCollapsed;
this.groupData[this.groupData.findIndex(x => x.key === this.text)].isVisible = !this.isCollapsed;
}
}
