Simple popup filter improvements
This commit is contained in:
parent
aec5da15df
commit
4c0437d7fc
3
src/assets/icons/filter-list.svg
Normal file
3
src/assets/icons/filter-list.svg
Normal 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 |
4
src/lib/filtering/models/simple-filter-option.ts
Normal file
4
src/lib/filtering/models/simple-filter-option.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export interface SimpleFilterOption<T> {
|
||||
value: T;
|
||||
label: string;
|
||||
}
|
||||
@ -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>
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -15,6 +15,7 @@ export const ICONS = new Set([
|
||||
'edit',
|
||||
'expand',
|
||||
'failure',
|
||||
'filter-list',
|
||||
'help-outline',
|
||||
'lanes',
|
||||
'list',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user