parent
56b19f8a0b
commit
851ee9e637
@ -0,0 +1,14 @@ |
|||||||
|
<button (click)="$event.stopPropagation();" mat-icon-button [matMenuTriggerFor]="menu" aria-label="filter-button avec menu"> |
||||||
|
<mat-icon>filter_alt</mat-icon> |
||||||
|
</button> |
||||||
|
<mat-menu #menu="matMenu"> |
||||||
|
<mat-list role="list" (click)="$event.stopPropagation();"> |
||||||
|
<mat-list-item role="listitem"> |
||||||
|
<mat-checkbox (change)="selectedAllChecked($event.checked)" [checked]="checkedAll"> Tout sélectionner</mat-checkbox> |
||||||
|
</mat-list-item> |
||||||
|
<mat-list-item *ngFor="let data of dataSource" role="listitem"> |
||||||
|
<mat-checkbox *ngIf="isPropertyValueName" (change)="selectedChecked($event.checked,data)" [checked]="exists(data)"> {{data[propertyValueName]}}</mat-checkbox> |
||||||
|
<mat-checkbox *ngIf="!isPropertyValueName" (change)="selectedChecked($event.checked,data)" [checked]="exists(data)"> {{data}}</mat-checkbox> |
||||||
|
</mat-list-item> |
||||||
|
</mat-list> |
||||||
|
</mat-menu> |
@ -0,0 +1,120 @@ |
|||||||
|
import { Component, Input, Output, EventEmitter, OnInit, OnChanges } from "@angular/core"; |
||||||
|
|
||||||
|
import { SelectedElement } from "@shared/filter/selected-element"; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Component({ |
||||||
|
selector: "checkbox-filter", |
||||||
|
templateUrl: "./checkbox-filter.html", |
||||||
|
styleUrls: ["./checkbox-filter.css"] |
||||||
|
}) |
||||||
|
export class CheckboxFilterComponent<T> implements OnInit, OnChanges { |
||||||
|
|
||||||
|
/** |
||||||
|
* Liste des éléments sélectionnés |
||||||
|
*/ |
||||||
|
elementsSelected: Array<T> = []; |
||||||
|
|
||||||
|
/** |
||||||
|
* Booléen permettant de determiner si la propriété "propertyValueName" contient une valeur ou non |
||||||
|
*/ |
||||||
|
isPropertyValueName: boolean; |
||||||
|
|
||||||
|
/** |
||||||
|
* Coche toutes les cases à cocher |
||||||
|
*/ |
||||||
|
@Input() checkedAll: boolean; |
||||||
|
|
||||||
|
/** |
||||||
|
* Source de données |
||||||
|
*/ |
||||||
|
@Input() dataSource : Array<T>; |
||||||
|
|
||||||
|
/** |
||||||
|
* Nom de la propriété contenant la valeur à afficher |
||||||
|
*/ |
||||||
|
@Input() propertyValueName: string;
|
||||||
|
|
||||||
|
/** |
||||||
|
* Booléen permettant de savoir si toutes les cases sont cochées ou non |
||||||
|
*/ |
||||||
|
@Output() isSelectedAllEvent = new EventEmitter<boolean>(); |
||||||
|
|
||||||
|
/** |
||||||
|
* Elément sélectionné |
||||||
|
*/ |
||||||
|
@Output() isSelectedEvent = new EventEmitter<SelectedElement<T>>(); |
||||||
|
|
||||||
|
|
||||||
|
constructor() {} |
||||||
|
|
||||||
|
ngOnInit() { |
||||||
|
this.isPropertyValueName = !this.propertyValueName ? false : true; |
||||||
|
} |
||||||
|
|
||||||
|
ngOnChanges() { |
||||||
|
if (this.dataSource.length > 0) { |
||||||
|
this.checkElementhasProperty(); |
||||||
|
this.selectedAllChecked(this.checkedAll); |
||||||
|
}
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Vérifie que tous les éléments de source de données possède la propriété "propertyValueName" lorsque cette dernière
|
||||||
|
* contient une valeur. |
||||||
|
*/ |
||||||
|
checkElementhasProperty() { |
||||||
|
if(this.propertyValueName && !this.dataSource.every(e => e.hasOwnProperty(this.propertyValueName))) |
||||||
|
throw new Error("Il existe au moins un élément dans la source de données qui ne possède pas la propriété '"+this.propertyValueName+"'.");
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Détermine si l'élément est présent dans la liste des éléments sélectionnés |
||||||
|
* @param element
|
||||||
|
*/ |
||||||
|
exists(element) { |
||||||
|
return this.elementsSelected.indexOf(element) > -1; |
||||||
|
}; |
||||||
|
|
||||||
|
/** |
||||||
|
* Met à jour la liste des éléments sélectionnés et met à jour l'EventEmitter "isSelectedAllEvent" |
||||||
|
* @param event case "Tout Sélectionner" cochée ou décochée |
||||||
|
*/ |
||||||
|
selectedAllChecked(event) { |
||||||
|
this.isSelectedAllEvent.emit(event);
|
||||||
|
this.checkedAll = event; |
||||||
|
this.elementsSelected = []; |
||||||
|
|
||||||
|
if(event) |
||||||
|
this.dataSource.map(data => this.elementsSelected.push(data)); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Met à jour la liste des éléments sélectionnés et met à jour l'EventEmitter "isSelectedEvent" |
||||||
|
* @param event case cochée ou décochée par l'utilisateur |
||||||
|
* @param data Valeur de la case cochée ou décochée |
||||||
|
*/ |
||||||
|
selectedChecked = (event: any, data: T) => { |
||||||
|
this.isSelectedEvent.emit({isSelected: event, selectedElement: data}); |
||||||
|
|
||||||
|
// si la checkbox a été cochée
|
||||||
|
if(event) |
||||||
|
this.elementsSelected.push(data); |
||||||
|
else |
||||||
|
this.elementsSelected = this.elementsSelected.filter(element => element != data); |
||||||
|
|
||||||
|
// coche la case "Tout sélectionner" si tous les éléments sont cochés
|
||||||
|
this.elementsSelected.length == this.dataSource.length ? this.checkedAll = true: this.checkedAll = false; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Une fois la page fermée, il est nécessaire de se désabonner des Oberservable afin d'éviter les fuites mémoires. |
||||||
|
*/ |
||||||
|
ngOnDestroy() { |
||||||
|
} |
||||||
|
} |
||||||
|
|
@ -0,0 +1,28 @@ |
|||||||
|
import { NgModule } from "@angular/core"; |
||||||
|
import { CommonModule } from '@angular/common'; |
||||||
|
import { FormsModule, ReactiveFormsModule} from '@angular/forms'; |
||||||
|
import { RouterModule } from '@angular/router'; |
||||||
|
|
||||||
|
import { MaterialModule } from "../angular-material/angular-material.module"; |
||||||
|
import { CheckboxFilterComponent } from "@shared/filter/checkbox-filter/checkbox-filter"; |
||||||
|
import { SelectFilterComponent } from "@shared/filter/select-filter/select-filter"; |
||||||
|
|
||||||
|
|
||||||
|
@NgModule({ |
||||||
|
declarations: [
|
||||||
|
CheckboxFilterComponent, |
||||||
|
SelectFilterComponent |
||||||
|
], |
||||||
|
imports: [ |
||||||
|
MaterialModule, |
||||||
|
CommonModule, |
||||||
|
FormsModule, |
||||||
|
ReactiveFormsModule, |
||||||
|
RouterModule |
||||||
|
], |
||||||
|
exports: [ |
||||||
|
CheckboxFilterComponent, |
||||||
|
SelectFilterComponent |
||||||
|
] |
||||||
|
}) |
||||||
|
export class FilterModule {} |
@ -0,0 +1,4 @@ |
|||||||
|
mat-select .mat-checkbox-layout, |
||||||
|
mat-select .mat-checkbox-label { |
||||||
|
width:100% !important; |
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
<mat-form-field appearance="fill"> |
||||||
|
<mat-label>{{label}}</mat-label> |
||||||
|
<mat-select [(value)]="elementsSelected" multiple> |
||||||
|
<mat-checkbox class="mat-option" (change)="selectedAllChecked($event.checked)" [checked]="checkedAll"> Tout sélectionner</mat-checkbox> |
||||||
|
<ng-container *ngFor="let data of dataSource"> |
||||||
|
<mat-option #matOption *ngIf="isPropertyValueName" (click)="selectedChecked(matOption.selected, data)" [value]="data">{{data[propertyValueName]}}</mat-option> |
||||||
|
<mat-option #matOption *ngIf="!isPropertyValueName" (click)="selectedChecked(matOption.selected, data)" [value]="data">{{data}}</mat-option> |
||||||
|
</ng-container> |
||||||
|
</mat-select> |
||||||
|
</mat-form-field> |
||||||
|
|
@ -0,0 +1,116 @@ |
|||||||
|
import { Component, Input, Output, EventEmitter, OnInit, OnChanges } from "@angular/core"; |
||||||
|
import { SelectedElement } from "@shared/filter/selected-element"; |
||||||
|
|
||||||
|
@Component({ |
||||||
|
selector: "select-filter", |
||||||
|
templateUrl: "./select-filter.html", |
||||||
|
styleUrls: ["./select-filter.css"] |
||||||
|
}) |
||||||
|
export class SelectFilterComponent<T> implements OnInit, OnChanges { |
||||||
|
|
||||||
|
/** |
||||||
|
* Liste des éléments sélectionnés |
||||||
|
*/ |
||||||
|
elementsSelected: Array<T> = []; |
||||||
|
|
||||||
|
/** |
||||||
|
* Booléen permettant de determiner si la propriété "propertyValueName" contient une valeur ou non |
||||||
|
*/ |
||||||
|
isPropertyValueName: boolean; |
||||||
|
|
||||||
|
/** |
||||||
|
* Libellé qui est affiché dans la liste déroulante lorsqu'aucune valeur n'est sélectionnée |
||||||
|
*/ |
||||||
|
@Input() label: string; |
||||||
|
|
||||||
|
/** |
||||||
|
* Cocher toutes les cases à cocher |
||||||
|
*/ |
||||||
|
@Input() checkedAll: boolean; |
||||||
|
|
||||||
|
/** |
||||||
|
* Source de données |
||||||
|
*/ |
||||||
|
@Input() dataSource : Array<T>; |
||||||
|
|
||||||
|
/** |
||||||
|
* Nom de la propriété contenant la valeur à afficher |
||||||
|
*/ |
||||||
|
@Input() propertyValueName: string;
|
||||||
|
|
||||||
|
/** |
||||||
|
* Booléen permettant de savoir si toutes les cases sont cochées ou non |
||||||
|
*/ |
||||||
|
@Output() isSelectedAllEvent = new EventEmitter<boolean>(); |
||||||
|
|
||||||
|
/** |
||||||
|
* Elément sélectionné |
||||||
|
*/ |
||||||
|
@Output() isSelectedEvent = new EventEmitter<SelectedElement<T>>(); |
||||||
|
|
||||||
|
|
||||||
|
constructor() {} |
||||||
|
|
||||||
|
ngOnInit() { |
||||||
|
this.isPropertyValueName = !this.propertyValueName ? false : true; |
||||||
|
} |
||||||
|
|
||||||
|
ngOnChanges() { |
||||||
|
if (this.dataSource.length > 0) { |
||||||
|
this.checkElementhasProperty();
|
||||||
|
this.selectedAllChecked(this.checkedAll); |
||||||
|
}
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Vérifie que tous les éléments de source de données possède la propriété "propertyValueName" lorsque cette dernière
|
||||||
|
* contient une valeur. |
||||||
|
*/ |
||||||
|
checkElementhasProperty() { |
||||||
|
if(this.propertyValueName && !this.dataSource.every(e => e.hasOwnProperty(this.propertyValueName))) |
||||||
|
throw new Error("Il existe au moins un élément dans la source de données qui ne possède pas la propriété '"+this.propertyValueName+"'.");
|
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Met à jour la liste des éléments sélectionnés et met à jour l'EventEmitter "isSelectedAllEvent" |
||||||
|
* @param event case "Tout Sélectionner" cochée ou décochée |
||||||
|
*/ |
||||||
|
selectedAllChecked(event) { |
||||||
|
this.isSelectedAllEvent.emit(event);
|
||||||
|
this.checkedAll = event; |
||||||
|
this.elementsSelected = []; |
||||||
|
|
||||||
|
if(event) |
||||||
|
this.dataSource.map(data => this.elementsSelected.push(data));
|
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Met à jour la liste des éléments sélectionnés et met à jour l'EventEmitter "isSelectedEvent" |
||||||
|
* @param isChecked case cochée ou décochée par l'utilisateur |
||||||
|
* @param data Valeur de la case cochée ou décochée |
||||||
|
*/ |
||||||
|
selectedChecked = (isChecked: boolean, data: T) => { |
||||||
|
this.isSelectedEvent.emit({isSelected: isChecked, selectedElement: data}); |
||||||
|
|
||||||
|
if(isChecked) { |
||||||
|
var index = this.elementsSelected.findIndex(element => element == data);
|
||||||
|
|
||||||
|
if (index === -1)
|
||||||
|
this.elementsSelected.push(data); |
||||||
|
}
|
||||||
|
else { |
||||||
|
this.elementsSelected = this.elementsSelected.filter(element => element != data); |
||||||
|
} |
||||||
|
|
||||||
|
// coche la case "Tout sélectionner" si tous les éléments sont cochés
|
||||||
|
this.elementsSelected.length == this.dataSource.length ? this.checkedAll = true: this.checkedAll = false; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Une fois la page fermée, il est nécessaire de se désabonner des Oberservable afin d'éviter les fuites mémoires. |
||||||
|
*/ |
||||||
|
ngOnDestroy() { |
||||||
|
} |
||||||
|
} |
||||||
|
|
@ -0,0 +1,11 @@ |
|||||||
|
export interface SelectedElement<T> {
|
||||||
|
/** |
||||||
|
* Détermine si l'élément est sélectionné ou non |
||||||
|
*/ |
||||||
|
isSelected: boolean; |
||||||
|
|
||||||
|
/** |
||||||
|
* Element sélectionné |
||||||
|
*/ |
||||||
|
selectedElement: T; |
||||||
|
} |
Loading…
Reference in new issue