import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'; import { AbstractControl, FormControl, ValidationErrors } from '@angular/forms'; import { OptionSelect } from '../../interface/option-select.interface'; import { Filter } from '../../interface/filter.interface'; import { MatOptionSelectionChange } from '@angular/material/core'; import { combineLatestWith, map, Observable, of, startWith } from 'rxjs'; import { ChevronDown as iconChevronDown, X as iconClose } from 'lucide-angular'; import { Utils } from '../../common/utils'; @Component({ selector: 'kit-toolbar-filter-select', templateUrl: './toolbar-filter-select.component.html' }) export class ToolbarFilterSelectComponent implements OnInit, OnChanges{ @Input() filterForm: FormControl = new FormControl({}); public filteredOptions$: Observable | undefined; public iconChevronDown = iconChevronDown public iconClose = iconClose private _filter!:Filter; public constructor(){} @Input() public set filter(filter:Filter){ this._filter = filter; } public get filter(){ return this._filter; } public ngOnInit(): void { this.setFilterObservable() } public ngOnChanges(changes: SimpleChanges): void { if(changes['options']) { this.setFilterObservable() } } public onChange(event: MatOptionSelectionChange) { //this.changeEvent.emit(event.source.value); } public compareFn(option1: string, option2: OptionSelect | string): boolean { let validation = false if(option1 && option2){ if(typeof (option2) === 'string'){ validation = option1 === option2 }else{ validation = option1 === option2.value } } return validation } public isControlRequired(): boolean { if (this.filterForm && this.filterForm.validator) { const validator = this.filterForm.validator({} as any); return !!(validator && validator['required']); } return false; } public displayFn(option: OptionSelect): string { return option && option.label ? option.label : ''; } public clearSelection(){ this.filterForm.setValue(null); //this.changeEvent.emit(); } public validateError () { return this.filter?.errors ? Utils.validateError(this.filterForm, this.filter?.errors) : ''; } private validateOption(control: AbstractControl): ValidationErrors|null { const value = control.value; // Valida si el valor es un objeto o un primitivo y si está en las opciones if(this.filter.values && value) { const isValid = this.filter.values?.some(option => typeof value === 'object' ? option.value === value.value : option.value === value ); return isValid ? null : { invalidOption: true }; } return null } private setFilterObservable(){ this.filteredOptions$ = this.filterForm.valueChanges.pipe( startWith(this.filterForm.value || ''), combineLatestWith(of(this.filter.values || [])), map(([inputValue, optionslist]) => { if(inputValue){ let filterValue: string; if (typeof inputValue === 'object' && inputValue) { filterValue = inputValue.value ? inputValue.value.toLowerCase() : ''; } else if (typeof inputValue === 'string') { filterValue = inputValue.toLowerCase(); } else { filterValue = ''; } if (!filterValue) { return optionslist; } return optionslist.filter((option: any) => option.value.toLowerCase().includes(filterValue) || // Filtra por value option.label.toLowerCase().includes(filterValue) // O por label ); } else { return optionslist; } }) ); if (this.filter.values && this.filter.values.length > 0 ) { const existingValidators = this.filterForm.validator ? [this.filterForm.validator] : []; this.filterForm.setValidators([this.validateOption.bind(this), ...existingValidators]) } } }