import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'; import { AbmList } from '../../interface/abm-list.interface'; import { AbstractControl, FormControl, ValidationErrors } from '@angular/forms'; import { MatOptionSelectionChange } from '@angular/material/core'; import { combineLatestWith, map, Observable, of, startWith } from 'rxjs'; import { IOption } from '../../interface/option.interface'; import { ChevronDown, X } from 'lucide-angular'; @Component({ selector: 'kit-abm-list-select', templateUrl: './abm-list-select.component.html' }) export class AbmListSelectComponent implements OnInit, OnChanges{ @Input() formControl!: FormControl; private _abmListInput!: AbmList; public constructor(){} @Input() public set abmListInput(abmListInput:AbmList){ this._abmListInput = abmListInput; } public filteredOptions$: Observable | undefined; public get abmListInput(){ return this._abmListInput; } readonly xI = X; readonly chevronDownI = ChevronDown; ngOnInit(): void { this.setFilterObservable() } ngOnChanges(changes: SimpleChanges): void { if(changes['abmListInput']) { this.setFilterObservable() } } private setFilterObservable(){ this.filteredOptions$ = this.formControl.valueChanges.pipe( startWith(this.formControl.value || ''), combineLatestWith(of(this._abmListInput.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._abmListInput.values && this._abmListInput.values.length > 0 ) { const existingValidators = this.formControl.validator ? [this.formControl.validator] : []; this.formControl.setValidators([this.validateOption.bind(this), ...existingValidators]) } } 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._abmListInput.values && value) { const isValid = this._abmListInput.values?.some(option => typeof value === 'object' ? option.value === value.value : option.value === value ); return isValid ? null : { invalidOption: true }; } return null } isControlRequired(): boolean { if (this.formControl && this.formControl.validator) { const validator = this.formControl.validator({} as any); return !!(validator && validator['required']); } return false; } displayFn(option: IOption): string { return option && option.label ? option.label : ''; } clearSelection(){ this.formControl.setValue(null); this.formControl.markAsDirty(); this.formControl.updateValueAndValidity(); } onChange(event: MatOptionSelectionChange) { this.formControl.setValue(event.source.value); } }