diff --git a/libs/ui/src/lib/activities-filter/activities-filter.component.html b/libs/ui/src/lib/activities-filter/activities-filter.component.html index fd22ed351..d87ce16ce 100644 --- a/libs/ui/src/lib/activities-filter/activities-filter.component.html +++ b/libs/ui/src/lib/activities-filter/activities-filter.component.html @@ -10,7 +10,7 @@ [removable]="true" (removed)="onRemoveFilter(filter)" > - {{ filter.label | gfSymbol }} + {{ filter.label ?? '' | gfSymbol }} @@ -23,7 +23,7 @@ [matAutocomplete]="autocomplete" [matChipInputFor]="chipList" [matChipInputSeparatorKeyCodes]="separatorKeysCodes" - [placeholder]="placeholder" + [placeholder]="placeholder()" (matChipInputTokenEnd)="onAddFilter($event)" /> @@ -35,7 +35,7 @@ @for (filter of filterGroup.filters; track filter) { - {{ filter.label | gfSymbol }} + {{ filter.label ?? '' | gfSymbol }} } @@ -46,7 +46,7 @@ disabled mat-icon-button matSuffix - [ngClass]="{ 'd-none': !isLoading }" + [ngClass]="{ 'd-none': !isLoading() }" > diff --git a/libs/ui/src/lib/activities-filter/activities-filter.component.ts b/libs/ui/src/lib/activities-filter/activities-filter.component.ts index 34f883c67..25fad683d 100644 --- a/libs/ui/src/lib/activities-filter/activities-filter.component.ts +++ b/libs/ui/src/lib/activities-filter/activities-filter.component.ts @@ -8,14 +8,14 @@ import { ChangeDetectionStrategy, Component, ElementRef, - EventEmitter, Input, OnChanges, - OnDestroy, - Output, SimpleChanges, - ViewChild + ViewChild, + input, + output } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { FormControl, ReactiveFormsModule } from '@angular/forms'; import { MatAutocomplete, @@ -30,8 +30,7 @@ import { IonIcon } from '@ionic/angular/standalone'; import { addIcons } from 'ionicons'; import { closeOutline, searchOutline } from 'ionicons/icons'; import { groupBy } from 'lodash'; -import { BehaviorSubject, Observable, Subject } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; +import { BehaviorSubject } from 'rxjs'; import { translate } from '../i18n'; @@ -53,28 +52,26 @@ import { translate } from '../i18n'; styleUrls: ['./activities-filter.component.scss'], templateUrl: './activities-filter.component.html' }) -export class GfActivitiesFilterComponent implements OnChanges, OnDestroy { +export class GfActivitiesFilterComponent implements OnChanges { @Input() allFilters: Filter[]; - @Input() isLoading: boolean; - @Input() placeholder: string; - @Output() valueChanged = new EventEmitter(); + @ViewChild('autocomplete') protected matAutocomplete: MatAutocomplete; + @ViewChild('searchInput') protected searchInput: ElementRef; - @ViewChild('autocomplete') matAutocomplete: MatAutocomplete; - @ViewChild('searchInput') searchInput: ElementRef; + public readonly isLoading = input.required(); + public readonly placeholder = input.required(); + public readonly valueChanged = output(); - public filterGroups$: Subject = new BehaviorSubject([]); - public filters$: Subject = new BehaviorSubject([]); - public filters: Observable = this.filters$.asObservable(); - public searchControl = new FormControl(undefined); - public selectedFilters: Filter[] = []; - public separatorKeysCodes: number[] = [ENTER, COMMA]; - - private unsubscribeSubject = new Subject(); + protected readonly filterGroups$ = new BehaviorSubject([]); + protected readonly searchControl = new FormControl( + null + ); + protected selectedFilters: Filter[] = []; + protected readonly separatorKeysCodes: number[] = [ENTER, COMMA]; public constructor() { this.searchControl.valueChanges - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed()) .subscribe((filterOrSearchTerm) => { if (filterOrSearchTerm) { const searchTerm = @@ -97,41 +94,39 @@ export class GfActivitiesFilterComponent implements OnChanges, OnDestroy { } } - public onAddFilter({ input, value }: MatChipInputEvent) { + public onAddFilter({ chipInput, value }: MatChipInputEvent) { if (value?.trim()) { this.updateFilters(); } // Reset the input value - if (input) { - input.value = ''; + if (chipInput.inputElement) { + chipInput.inputElement.value = ''; } - this.searchControl.setValue(undefined); + this.searchControl.setValue(null); } public onRemoveFilter(aFilter: Filter) { - this.selectedFilters = this.selectedFilters.filter((filter) => { - return filter.id !== aFilter.id; + this.selectedFilters = this.selectedFilters.filter(({ id }) => { + return id !== aFilter.id; }); this.updateFilters(); } public onSelectFilter(event: MatAutocompleteSelectedEvent) { - this.selectedFilters.push( - this.allFilters.find((filter) => { - return filter.id === event.option.value; - }) - ); + const filter = this.allFilters.find(({ id }) => { + return id === event.option.value; + }); + + if (filter) { + this.selectedFilters.push(filter); + } + this.updateFilters(); this.searchInput.nativeElement.value = ''; - this.searchControl.setValue(undefined); - } - - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); + this.searchControl.setValue(null); } private getGroupedFilters(searchTerm?: string) { @@ -139,23 +134,23 @@ export class GfActivitiesFilterComponent implements OnChanges, OnDestroy { this.allFilters .filter((filter) => { // Filter selected filters - return !this.selectedFilters.some((selectedFilter) => { - return selectedFilter.id === filter.id; + return !this.selectedFilters.some(({ id }) => { + return id === filter.id; }); }) .filter((filter) => { if (searchTerm) { // Filter by search term return filter.label - .toLowerCase() + ?.toLowerCase() .includes(searchTerm.toLowerCase()); } return filter; }) - .sort((a, b) => a.label?.localeCompare(b.label)), - (filter) => { - return filter.type; + .sort((a, b) => (a.label ?? '').localeCompare(b.label ?? '')), + ({ type }) => { + return type; } );