Simple popup filter improvements

This commit is contained in:
Adina Țeudan 2024-06-17 15:29:26 +03:00
parent aec5da15df
commit 4c0437d7fc
5 changed files with 69 additions and 37 deletions

View File

@ -0,0 +1,3 @@
<svg width="18" height="12" viewBox="0 0 18 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7 12V10H11V12H7ZM3 7V5H15V7H3ZM0 2V0H18V2H0Z" fill="currentColor" />
</svg>

After

Width:  |  Height:  |  Size: 186 B

View File

@ -0,0 +1,4 @@
export interface SimpleFilterOption<T> {
value: T;
label: string;
}

View File

@ -1,25 +1,33 @@
<ng-container *ngIf="icon">
<iqser-icon-button
[attr.aria-expanded]="expanded()"
[class.disabled]="disabled()"
[disabled]="disabled()"
[icon]="icon()"
[label]="label()"
[matMenuTriggerFor]="filterMenu"
[showDot]="hasActiveFilters()"
></iqser-icon-button>
</ng-container>
<iqser-icon-button
*ngIf="type() === 'text' && icon()"
[attr.aria-expanded]="expanded()"
[class.disabled]="disabled()"
[disabled]="disabled()"
[icon]="icon()"
[label]="label()"
[matMenuTriggerFor]="filterMenu"
[showDot]="hasActiveFilters()"
></iqser-icon-button>
<ng-container *ngIf="!icon">
<iqser-chevron-button
[attr.aria-expanded]="expanded()"
[class.disabled]="disabled"
[disabled]="disabled()"
[label]="label()"
[matMenuTriggerFor]="filterMenu"
[showDot]="hasActiveFilters()"
></iqser-chevron-button>
</ng-container>
<iqser-chevron-button
[attr.aria-expanded]="expanded()"
[class.disabled]="disabled()"
[disabled]="disabled()"
[label]="label()"
[matMenuTriggerFor]="filterMenu"
[showDot]="hasActiveFilters()"
*ngIf="type() === 'text' && !icon()"
></iqser-chevron-button>
<iqser-circle-button
[attr.aria-expanded]="expanded()"
[class.disabled]="disabled()"
[disabled]="disabled()"
[matMenuTriggerFor]="filterMenu"
[showDot]="hasActiveFilters()"
[icon]="icon() || 'iqser:filter-list'"
*ngIf="type() === 'icon'"
></iqser-circle-button>
<mat-menu #filterMenu="matMenu" (closed)="expanded.set(false)" xPosition="before">
<div iqserStopPropagation>

View File

@ -1,12 +1,12 @@
import { Component, computed, input, output, signal, untracked } from '@angular/core';
import { Component, computed, effect, input, output, signal, untracked } from '@angular/core';
import { MatMenuModule } from '@angular/material/menu';
import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { MatCheckbox } from '@angular/material/checkbox';
import { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';
import { ChevronButtonComponent, IconButtonComponent } from '../../buttons';
import { ChevronButtonComponent, CircleButtonComponent, IconButtonComponent } from '../../buttons';
import { StopPropagationDirective } from '../../directives';
import { InputWithActionComponent } from '../../inputs';
import { SimpleFilterOption } from '../models/simple-filter-option';
@Component({
selector: 'iqser-simple-popup-filter',
@ -24,18 +24,20 @@ import { InputWithActionComponent } from '../../inputs';
MatCheckbox,
IconButtonComponent,
ChevronButtonComponent,
CircleButtonComponent,
],
})
export class SimplePopupFilterComponent<T extends { label: string }> {
options = input.required<T[]>();
icon = input<string>();
label = input<string>();
filterPlaceholder = input.required<string>();
disabled = input<boolean>(false);
selectionChanged = output<T[]>();
export class SimplePopupFilterComponent<T> {
readonly options = input.required<SimpleFilterOption<T>[]>();
readonly icon = input<string>();
readonly label = input<string>();
readonly filterPlaceholder = input.required<string>();
readonly disabled = input<boolean>(false);
readonly type = input<'text' | 'icon'>('text');
readonly selectionChanged = output<SimpleFilterOption<T>[]>();
readonly expanded = signal(false);
readonly selectedOptions = signal<T[]>([]);
readonly selectedOptions = signal<SimpleFilterOption<T>[]>([]);
readonly hasActiveFilters = computed(() => this.selectedOptions().length > 0);
readonly searchValue = signal('');
readonly displayedOptions = computed(() =>
@ -43,10 +45,24 @@ export class SimplePopupFilterComponent<T extends { label: string }> {
);
constructor() {
toObservable(this.selectedOptions)
.pipe(takeUntilDestroyed())
// eslint-disable-next-line rxjs/no-ignored-subscription
.subscribe(() => this.selectionChanged.emit(this.selectedOptions()));
effect(() => {
this.selectionChanged.emit(this.selectedOptions());
});
/** If the options change and the selected options are not in the new options, remove them. */
effect(
() => {
const allOptions = this.options();
const selectedOptions = untracked(this.selectedOptions);
if (selectedOptions.some(selectedOption => !allOptions.find(o => o.value === selectedOption))) {
this.selectedOptions.set(
selectedOptions.filter(selectedOption => allOptions.find(o => o.value === selectedOption.value)),
);
}
},
{ allowSignalWrites: true },
);
}
protected _selectAll(): void {
@ -57,7 +73,7 @@ export class SimplePopupFilterComponent<T extends { label: string }> {
this.selectedOptions.set([]);
}
protected _filterCheckboxClicked(option: T): void {
protected _filterCheckboxClicked(option: SimpleFilterOption<T>): void {
if (this.selectedOptions().includes(option)) {
this.selectedOptions.set(this.selectedOptions().filter(selectedOption => selectedOption !== option));
} else {

View File

@ -15,6 +15,7 @@ export const ICONS = new Set([
'edit',
'expand',
'failure',
'filter-list',
'help-outline',
'lanes',
'list',