diff --git a/src/app/shared/filter/checkbox-filter/checkbox-filter.css b/src/app/shared/filter/checkbox-filter/checkbox-filter.css new file mode 100644 index 0000000..e69de29 diff --git a/src/app/shared/filter/checkbox-filter/checkbox-filter.html b/src/app/shared/filter/checkbox-filter/checkbox-filter.html new file mode 100644 index 0000000..b6d06dc --- /dev/null +++ b/src/app/shared/filter/checkbox-filter/checkbox-filter.html @@ -0,0 +1,14 @@ + + + + + Tout sélectionner + + + {{data[propertyValueName]}} + {{data}} + + + \ No newline at end of file diff --git a/src/app/shared/filter/checkbox-filter/checkbox-filter.ts b/src/app/shared/filter/checkbox-filter/checkbox-filter.ts new file mode 100644 index 0000000..e6ff222 --- /dev/null +++ b/src/app/shared/filter/checkbox-filter/checkbox-filter.ts @@ -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 implements OnInit, OnChanges { + + /** + * Liste des éléments sélectionnés + */ + elementsSelected: Array = []; + + /** + * 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; + + /** + * 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(); + + /** + * Elément sélectionné + */ + @Output() isSelectedEvent = new EventEmitter>(); + + + 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() { + } + } + \ No newline at end of file diff --git a/src/app/shared/filter/filter.module.ts b/src/app/shared/filter/filter.module.ts new file mode 100644 index 0000000..9d30ceb --- /dev/null +++ b/src/app/shared/filter/filter.module.ts @@ -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 {} diff --git a/src/app/shared/filter/select-filter/select-filter.css b/src/app/shared/filter/select-filter/select-filter.css new file mode 100644 index 0000000..8eea0ab --- /dev/null +++ b/src/app/shared/filter/select-filter/select-filter.css @@ -0,0 +1,4 @@ +mat-select .mat-checkbox-layout, +mat-select .mat-checkbox-label { + width:100% !important; +} \ No newline at end of file diff --git a/src/app/shared/filter/select-filter/select-filter.html b/src/app/shared/filter/select-filter/select-filter.html new file mode 100644 index 0000000..d3bb6c6 --- /dev/null +++ b/src/app/shared/filter/select-filter/select-filter.html @@ -0,0 +1,11 @@ + + {{label}} + + Tout sélectionner + + {{data[propertyValueName]}} + {{data}} + + + + diff --git a/src/app/shared/filter/select-filter/select-filter.ts b/src/app/shared/filter/select-filter/select-filter.ts new file mode 100644 index 0000000..6b1d985 --- /dev/null +++ b/src/app/shared/filter/select-filter/select-filter.ts @@ -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 implements OnInit, OnChanges { + + /** + * Liste des éléments sélectionnés + */ + elementsSelected: Array = []; + + /** + * 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; + + /** + * 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(); + + /** + * Elément sélectionné + */ + @Output() isSelectedEvent = new EventEmitter>(); + + + 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() { + } + } + \ No newline at end of file diff --git a/src/app/shared/filter/selected-element.ts b/src/app/shared/filter/selected-element.ts new file mode 100644 index 0000000..fd68bbe --- /dev/null +++ b/src/app/shared/filter/selected-element.ts @@ -0,0 +1,11 @@ +export interface SelectedElement { + /** + * Détermine si l'élément est sélectionné ou non + */ + isSelected: boolean; + + /** + * Element sélectionné + */ + selectedElement: T; +} \ No newline at end of file