Simple popup filter
This commit is contained in:
parent
748cce4032
commit
aec5da15df
@ -11,3 +11,4 @@ export * from './models/nested-filter.model';
|
||||
|
||||
export * from './popup-filter/popup-filter.component';
|
||||
export * from './quick-filters/quick-filters.component';
|
||||
export * from './simple-popup-filter/simple-popup-filter.component';
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<mat-menu #filterMenu="matMenu" (closed)="expanded.set(false)" xPosition="before">
|
||||
<div iqserStopPropagation>
|
||||
<ng-template matMenuContent>
|
||||
<div class="input-wrapper">
|
||||
<iqser-input-with-action
|
||||
[value]="searchValue()"
|
||||
(valueChange)="searchValue.set($event)"
|
||||
[placeholder]="filterPlaceholder()"
|
||||
[width]="'full'"
|
||||
></iqser-input-with-action>
|
||||
</div>
|
||||
|
||||
<div class="filter-menu-header">
|
||||
<div translate="filter-menu.label" class="all-caps-label"></div>
|
||||
<div class="actions">
|
||||
<div (click)="_selectAll()" class="all-caps-label primary pointer" iqserStopPropagation translate="actions.all"></div>
|
||||
<div (click)="_clear()" class="all-caps-label primary pointer" iqserStopPropagation translate="actions.none"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="filter-content">
|
||||
<div mat-menu-item *ngFor="let option of displayedOptions()" (click)="_filterCheckboxClicked(option)">
|
||||
<mat-checkbox [checked]="selectedOptions().includes(option)" class="filter-menu-checkbox">
|
||||
{{ option.label }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
</div>
|
||||
</mat-menu>
|
||||
@ -0,0 +1,24 @@
|
||||
@use 'common-mixins';
|
||||
|
||||
.filter-menu-options,
|
||||
.filter-menu-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 8px 16px 16px 16px;
|
||||
min-width: var(--filter-card-min-width);
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.input-wrapper {
|
||||
padding: 0 8px 8px 8px;
|
||||
}
|
||||
|
||||
.filter-content {
|
||||
max-height: 300px;
|
||||
overflow: auto;
|
||||
@include common-mixins.scroll-bar;
|
||||
}
|
||||
@ -0,0 +1,67 @@
|
||||
import { Component, computed, 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 { StopPropagationDirective } from '../../directives';
|
||||
import { InputWithActionComponent } from '../../inputs';
|
||||
|
||||
@Component({
|
||||
selector: 'iqser-simple-popup-filter',
|
||||
templateUrl: './simple-popup-filter.component.html',
|
||||
styleUrls: ['./simple-popup-filter.component.scss'],
|
||||
standalone: true,
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatMenuModule,
|
||||
IconButtonComponent,
|
||||
ChevronButtonComponent,
|
||||
StopPropagationDirective,
|
||||
InputWithActionComponent,
|
||||
TranslateModule,
|
||||
MatCheckbox,
|
||||
IconButtonComponent,
|
||||
ChevronButtonComponent,
|
||||
],
|
||||
})
|
||||
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[]>();
|
||||
|
||||
readonly expanded = signal(false);
|
||||
readonly selectedOptions = signal<T[]>([]);
|
||||
readonly hasActiveFilters = computed(() => this.selectedOptions().length > 0);
|
||||
readonly searchValue = signal('');
|
||||
readonly displayedOptions = computed(() =>
|
||||
this.options().filter(option => option.label.toLowerCase().includes(this.searchValue().toLowerCase())),
|
||||
);
|
||||
|
||||
constructor() {
|
||||
toObservable(this.selectedOptions)
|
||||
.pipe(takeUntilDestroyed())
|
||||
// eslint-disable-next-line rxjs/no-ignored-subscription
|
||||
.subscribe(() => this.selectionChanged.emit(this.selectedOptions()));
|
||||
}
|
||||
|
||||
protected _selectAll(): void {
|
||||
this.selectedOptions.set(untracked(this.options));
|
||||
}
|
||||
|
||||
protected _clear(): void {
|
||||
this.selectedOptions.set([]);
|
||||
}
|
||||
|
||||
protected _filterCheckboxClicked(option: T): void {
|
||||
if (this.selectedOptions().includes(option)) {
|
||||
this.selectedOptions.set(this.selectedOptions().filter(selectedOption => selectedOption !== option));
|
||||
} else {
|
||||
this.selectedOptions.set([...this.selectedOptions(), option]);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user