valtech-components 2.0.393 → 2.0.394

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { EventEmitter, Component, Input, Output, Injectable, inject, InjectionToken, Inject, ChangeDetectorRef, HostListener, Pipe, ChangeDetectionStrategy, ViewChild, signal, computed, effect, forwardRef } from '@angular/core';
2
+ import { EventEmitter, Component, Input, Output, Injectable, inject, InjectionToken, Inject, ChangeDetectorRef, HostListener, Pipe, ChangeDetectionStrategy, ViewChild, forwardRef } from '@angular/core';
3
3
  import { IonAvatar, IonCard, IonIcon, IonButton, IonSpinner, IonText, IonModal, IonHeader, IonToolbar, IonContent, IonButtons, IonTitle, IonProgressBar, IonCardContent, IonCardHeader, IonCardTitle, IonCardSubtitle, IonCheckbox, IonTextarea, IonDatetime, IonDatetimeButton, IonInput, IonSelect, IonSelectOption, IonLabel, IonSearchbar, IonRadioGroup, IonRadio, IonMenuButton, IonFooter, IonList, IonListHeader, IonNote, IonItem } from '@ionic/angular/standalone';
4
4
  import * as i1 from '@angular/common';
5
5
  import { CommonModule, NgStyle, Location, AsyncPipe, NgFor, NgClass } from '@angular/common';
@@ -5670,48 +5670,13 @@ class MultiSelectSimpleComponent {
5670
5670
  this.valueProperty = 'id';
5671
5671
  this.placeholder = '';
5672
5672
  this.langService = inject(LangService);
5673
- // Signals for reactive state management
5674
- this.isOpen = signal(false);
5675
- this.searchTerm = signal('');
5676
- this.selectedValues = signal([]);
5677
- // Force options to be reactive
5678
- this.optionsSignal = signal([]);
5679
- // Computed signals
5680
- this.displayValue = computed(() => {
5681
- const selected = this.selectedValues();
5682
- if (selected.length === 0) {
5683
- return '';
5684
- }
5685
- if (selected.length === 1) {
5686
- const option = this.getOptionByValue(selected[0]);
5687
- return option ? option[this.labelProperty] : '';
5688
- }
5689
- return `${selected.length} elementos seleccionados`;
5690
- });
5691
- this.filteredOptions = computed(() => {
5692
- // Use signal instead of props directly
5693
- const options = this.optionsSignal();
5694
- const search = this.searchTerm().toLowerCase();
5695
- // Debug
5696
- console.log('[MultiSelectSimple] filteredOptions computed:', {
5697
- optionsCount: options.length,
5698
- searchTerm: search,
5699
- options: options.slice(0, 3) // Primeras 3 opciones
5700
- });
5701
- if (!search) {
5702
- return options;
5703
- }
5704
- return options.filter(option => {
5705
- const label = option[this.labelProperty]
5706
- ? replaceSpecialChars(String(option[this.labelProperty]).toLowerCase())
5707
- : '';
5708
- const value = option[this.valueProperty]
5709
- ? replaceSpecialChars(String(option[this.valueProperty]).toLowerCase())
5710
- : '';
5711
- const searchTerm = replaceSpecialChars(search);
5712
- return label.includes(searchTerm) || value.includes(searchTerm);
5713
- });
5714
- });
5673
+ this.changeDetector = inject(ChangeDetectorRef);
5674
+ // Classic Angular properties
5675
+ this.isOpen = false;
5676
+ this.searchTerm = '';
5677
+ this.selectedValues = [];
5678
+ this.displayValue = '';
5679
+ this.filteredOptions = [];
5715
5680
  this.searchPlaceholder = '';
5716
5681
  // ControlValueAccessor
5717
5682
  this.onChange = (_value) => { };
@@ -5720,52 +5685,29 @@ class MultiSelectSimpleComponent {
5720
5685
  this.searchPlaceholder = this.langService.getText('_global', 'search', 'Buscar');
5721
5686
  // Close dropdown when clicking outside
5722
5687
  document.addEventListener('click', this.handleClickOutside.bind(this));
5723
- // Debug effect to track when filteredOptions changes
5724
- effect(() => {
5725
- const options = this.filteredOptions();
5726
- console.log('[MultiSelectSimple] EFFECT - filteredOptions changed:', {
5727
- optionsCount: options.length,
5728
- options: options,
5729
- timestamp: new Date().toLocaleTimeString()
5730
- });
5731
- });
5732
5688
  }
5733
5689
  ngOnInit() {
5734
- console.log('[MultiSelectSimple] ngOnInit:', {
5735
- props: !!this.props,
5736
- options: this.props?.options?.length || 0,
5737
- control: !!this.props?.control
5738
- });
5739
- // Update options signal
5740
- if (this.props?.options) {
5741
- this.optionsSignal.set(this.props.options);
5742
- }
5743
5690
  this.applyDefaultValue();
5691
+ this.initializeOptions();
5744
5692
  this.syncSelectedValues();
5693
+ this.updateDisplayValue();
5745
5694
  }
5746
5695
  ngOnDestroy() {
5747
5696
  document.removeEventListener('click', this.handleClickOutside.bind(this));
5748
5697
  }
5749
5698
  ngOnChanges(changes) {
5750
- console.log('[MultiSelectSimple] ngOnChanges:', {
5751
- hasPropsChange: !!changes['props'],
5752
- props: !!this.props,
5753
- options: this.props?.options?.length || 0,
5754
- propsOptions: this.props?.options
5755
- });
5756
5699
  if (changes['props'] && this.props) {
5757
- // Update options signal when props change
5758
- if (this.props.options) {
5759
- console.log('[MultiSelectSimple] Updating optionsSignal with:', this.props.options);
5760
- this.optionsSignal.set(this.props.options);
5761
- }
5700
+ this.initializeOptions();
5762
5701
  this.syncSelectedValues();
5702
+ this.updateDisplayValue();
5703
+ this.changeDetector.detectChanges();
5763
5704
  }
5764
5705
  }
5765
5706
  // ControlValueAccessor implementation
5766
5707
  writeValue(value) {
5767
5708
  const valueArray = this.parseValue(value);
5768
- this.selectedValues.set(valueArray);
5709
+ this.selectedValues = valueArray;
5710
+ this.updateDisplayValue();
5769
5711
  }
5770
5712
  registerOnChange(fn) {
5771
5713
  this.onChange = fn;
@@ -5779,8 +5721,8 @@ class MultiSelectSimpleComponent {
5779
5721
  // Component methods
5780
5722
  toggleDropdown(event) {
5781
5723
  event.stopPropagation();
5782
- this.isOpen.update(value => !value);
5783
- if (this.isOpen()) {
5724
+ this.isOpen = !this.isOpen;
5725
+ if (this.isOpen) {
5784
5726
  this.onTouched();
5785
5727
  // Focus search bar when opening
5786
5728
  setTimeout(() => {
@@ -5792,45 +5734,48 @@ class MultiSelectSimpleComponent {
5792
5734
  }
5793
5735
  }
5794
5736
  onSearch(event) {
5795
- this.searchTerm.set(event.detail.value || '');
5737
+ this.searchTerm = event.detail.value || '';
5738
+ this.filterOptions();
5796
5739
  }
5797
5740
  toggleOption(option) {
5798
- const value = String(option[this.valueProperty]); // Convertir a string
5799
- const currentSelected = this.selectedValues();
5741
+ const value = String(option[this.valueProperty]);
5800
5742
  if (this.isSelected(option)) {
5801
5743
  // Remove from selection
5802
- this.selectedValues.set(currentSelected.filter(v => v !== value));
5744
+ this.selectedValues = this.selectedValues.filter(v => v !== value);
5803
5745
  }
5804
5746
  else {
5805
5747
  // Add to selection
5806
- this.selectedValues.set([...currentSelected, value]);
5748
+ this.selectedValues = [...this.selectedValues, value];
5807
5749
  }
5750
+ this.updateDisplayValue();
5808
5751
  this.emitValue();
5809
5752
  }
5810
5753
  selectAll() {
5811
- const allValues = this.filteredOptions().map(option => String(option[this.valueProperty]));
5812
- const currentSelected = this.selectedValues();
5754
+ const allValues = this.filteredOptions.map(option => String(option[this.valueProperty]));
5813
5755
  // Add only new values to avoid duplicates
5814
- const newValues = allValues.filter(value => !currentSelected.includes(value));
5815
- this.selectedValues.set([...currentSelected, ...newValues]);
5756
+ const newValues = allValues.filter(value => !this.selectedValues.includes(value));
5757
+ this.selectedValues = [...this.selectedValues, ...newValues];
5758
+ this.updateDisplayValue();
5816
5759
  this.emitValue();
5817
5760
  }
5818
5761
  clearAll() {
5819
- this.selectedValues.set([]);
5762
+ this.selectedValues = [];
5763
+ this.updateDisplayValue();
5820
5764
  this.emitValue();
5821
5765
  }
5822
5766
  isSelected(option) {
5823
- return this.selectedValues().includes(String(option[this.valueProperty]));
5767
+ return this.selectedValues.includes(String(option[this.valueProperty]));
5824
5768
  }
5825
5769
  trackByFn(_index, option) {
5826
5770
  return option[this.valueProperty];
5827
5771
  }
5828
5772
  handleClickOutside(event) {
5829
- if (this.isOpen() &&
5773
+ if (this.isOpen &&
5830
5774
  !this.mainInputRef?.nativeElement?.contains(event.target) &&
5831
5775
  !this.dropdownRef?.nativeElement?.contains(event.target)) {
5832
- this.isOpen.set(false);
5833
- this.searchTerm.set('');
5776
+ this.isOpen = false;
5777
+ this.searchTerm = '';
5778
+ this.initializeOptions();
5834
5779
  }
5835
5780
  }
5836
5781
  parseValue(value) {
@@ -5844,7 +5789,7 @@ class MultiSelectSimpleComponent {
5844
5789
  return [String(value)];
5845
5790
  }
5846
5791
  emitValue() {
5847
- const value = this.selectedValues().join(',');
5792
+ const value = this.selectedValues.join(',');
5848
5793
  this.onChange(value);
5849
5794
  if (this.props?.control) {
5850
5795
  this.props.control.setValue(value);
@@ -5853,27 +5798,49 @@ class MultiSelectSimpleComponent {
5853
5798
  }
5854
5799
  }
5855
5800
  getOptionByValue(value) {
5856
- return this.optionsSignal().find(option => String(option[this.valueProperty]) === String(value));
5801
+ return this.filteredOptions.find(option => String(option[this.valueProperty]) === String(value));
5857
5802
  }
5858
5803
  applyDefaultValue() {
5859
5804
  if (this.props) {
5860
5805
  applyDefaultValueToControl(this.props);
5861
5806
  }
5862
5807
  }
5863
- debugOptions() {
5864
- console.log('[MultiSelectSimple] DEBUG CLICK:', {
5865
- props: this.props,
5866
- filteredOptions: this.filteredOptions(),
5867
- searchTerm: this.searchTerm(),
5868
- propsOptions: this.props?.options,
5869
- optionsSignal: this.optionsSignal(),
5870
- computed: this.filteredOptions()
5808
+ initializeOptions() {
5809
+ this.filteredOptions = this.props?.options || [];
5810
+ }
5811
+ filterOptions() {
5812
+ if (!this.searchTerm) {
5813
+ this.initializeOptions();
5814
+ return;
5815
+ }
5816
+ const search = replaceSpecialChars(this.searchTerm.toLowerCase());
5817
+ this.filteredOptions = (this.props?.options || []).filter(option => {
5818
+ const label = option[this.labelProperty]
5819
+ ? replaceSpecialChars(String(option[this.labelProperty]).toLowerCase())
5820
+ : '';
5821
+ const value = option[this.valueProperty]
5822
+ ? replaceSpecialChars(String(option[this.valueProperty]).toLowerCase())
5823
+ : '';
5824
+ return label.includes(search) || value.includes(search);
5871
5825
  });
5872
5826
  }
5827
+ updateDisplayValue() {
5828
+ if (this.selectedValues.length === 0) {
5829
+ this.displayValue = '';
5830
+ return;
5831
+ }
5832
+ if (this.selectedValues.length === 1) {
5833
+ const option = this.getOptionByValue(this.selectedValues[0]);
5834
+ this.displayValue = option ? option[this.labelProperty] : '';
5835
+ }
5836
+ else {
5837
+ this.displayValue = `${this.selectedValues.length} elementos seleccionados`;
5838
+ }
5839
+ }
5873
5840
  syncSelectedValues() {
5874
5841
  if (this.props?.control?.value) {
5875
5842
  const valueArray = this.parseValue(this.props.control.value);
5876
- this.selectedValues.set(valueArray);
5843
+ this.selectedValues = valueArray;
5877
5844
  }
5878
5845
  }
5879
5846
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MultiSelectSimpleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
@@ -5889,18 +5856,18 @@ class MultiSelectSimpleComponent {
5889
5856
  <ion-input
5890
5857
  #mainInput
5891
5858
  type="text"
5892
- [value]="displayValue()"
5859
+ [value]="displayValue"
5893
5860
  [placeholder]="props?.placeholder || placeholder"
5894
5861
  readonly
5895
5862
  class="main-input"
5896
- [class.is-open]="isOpen()"
5863
+ [class.is-open]="isOpen"
5897
5864
  />
5898
5865
 
5899
5866
  <!-- Dropdown icon -->
5900
5867
  <ion-icon
5901
5868
  name="chevron-down-outline"
5902
5869
  class="dropdown-icon"
5903
- [class.rotated]="isOpen()"
5870
+ [class.rotated]="isOpen"
5904
5871
  ></ion-icon>
5905
5872
 
5906
5873
  <!-- Hidden input for form control -->
@@ -5914,7 +5881,7 @@ class MultiSelectSimpleComponent {
5914
5881
  <!-- Dropdown overlay -->
5915
5882
  <div
5916
5883
  class="dropdown-overlay"
5917
- [class.visible]="isOpen()"
5884
+ [class.visible]="isOpen"
5918
5885
  #dropdown
5919
5886
  >
5920
5887
  <!-- Search bar -->
@@ -5923,7 +5890,7 @@ class MultiSelectSimpleComponent {
5923
5890
  #searchbar
5924
5891
  [placeholder]="searchPlaceholder"
5925
5892
  (ionInput)="onSearch($event)"
5926
- [value]="searchTerm()"
5893
+ [value]="searchTerm"
5927
5894
  show-clear-button="focus"
5928
5895
  ></ion-searchbar>
5929
5896
  </div>
@@ -5934,7 +5901,7 @@ class MultiSelectSimpleComponent {
5934
5901
  fill="clear"
5935
5902
  size="small"
5936
5903
  (click)="selectAll()"
5937
- [disabled]="filteredOptions().length === 0"
5904
+ [disabled]="filteredOptions.length === 0"
5938
5905
  >
5939
5906
  Seleccionar todos
5940
5907
  </ion-button>
@@ -5943,22 +5910,17 @@ class MultiSelectSimpleComponent {
5943
5910
  size="small"
5944
5911
  color="medium"
5945
5912
  (click)="clearAll()"
5946
- [disabled]="selectedValues().length === 0"
5913
+ [disabled]="selectedValues.length === 0"
5947
5914
  >
5948
5915
  Limpiar
5949
5916
  </ion-button>
5950
5917
  </div>
5951
5918
 
5952
- <!-- Debug button -->
5953
- <div class="search-container" style="background: red; color: white; padding: 4px;">
5954
- <button (click)="debugOptions()">DEBUG: {{ filteredOptions().length }} opciones</button>
5955
- </div>
5956
-
5957
5919
  <!-- Options list -->
5958
5920
  <div class="options-container">
5959
5921
  <ion-list class="options-list">
5960
5922
  <ion-item
5961
- *ngFor="let option of filteredOptions(); trackBy: trackByFn"
5923
+ *ngFor="let option of filteredOptions; trackBy: trackByFn"
5962
5924
  button
5963
5925
  (click)="toggleOption(option)"
5964
5926
  class="option-item"
@@ -5971,9 +5933,9 @@ class MultiSelectSimpleComponent {
5971
5933
  </ion-item>
5972
5934
 
5973
5935
  <!-- No results message -->
5974
- <ion-item *ngIf="filteredOptions().length === 0" class="no-results">
5936
+ <ion-item *ngIf="filteredOptions.length === 0" class="no-results">
5975
5937
  <ion-label color="medium">
5976
- {{ searchTerm() ? 'No se encontraron resultados' : 'No hay opciones disponibles' }}
5938
+ {{ searchTerm ? 'No se encontraron resultados' : 'No hay opciones disponibles' }}
5977
5939
  </ion-label>
5978
5940
  </ion-item>
5979
5941
  </ion-list>
@@ -5995,18 +5957,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
5995
5957
  <ion-input
5996
5958
  #mainInput
5997
5959
  type="text"
5998
- [value]="displayValue()"
5960
+ [value]="displayValue"
5999
5961
  [placeholder]="props?.placeholder || placeholder"
6000
5962
  readonly
6001
5963
  class="main-input"
6002
- [class.is-open]="isOpen()"
5964
+ [class.is-open]="isOpen"
6003
5965
  />
6004
5966
 
6005
5967
  <!-- Dropdown icon -->
6006
5968
  <ion-icon
6007
5969
  name="chevron-down-outline"
6008
5970
  class="dropdown-icon"
6009
- [class.rotated]="isOpen()"
5971
+ [class.rotated]="isOpen"
6010
5972
  ></ion-icon>
6011
5973
 
6012
5974
  <!-- Hidden input for form control -->
@@ -6020,7 +5982,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
6020
5982
  <!-- Dropdown overlay -->
6021
5983
  <div
6022
5984
  class="dropdown-overlay"
6023
- [class.visible]="isOpen()"
5985
+ [class.visible]="isOpen"
6024
5986
  #dropdown
6025
5987
  >
6026
5988
  <!-- Search bar -->
@@ -6029,7 +5991,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
6029
5991
  #searchbar
6030
5992
  [placeholder]="searchPlaceholder"
6031
5993
  (ionInput)="onSearch($event)"
6032
- [value]="searchTerm()"
5994
+ [value]="searchTerm"
6033
5995
  show-clear-button="focus"
6034
5996
  ></ion-searchbar>
6035
5997
  </div>
@@ -6040,7 +6002,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
6040
6002
  fill="clear"
6041
6003
  size="small"
6042
6004
  (click)="selectAll()"
6043
- [disabled]="filteredOptions().length === 0"
6005
+ [disabled]="filteredOptions.length === 0"
6044
6006
  >
6045
6007
  Seleccionar todos
6046
6008
  </ion-button>
@@ -6049,22 +6011,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
6049
6011
  size="small"
6050
6012
  color="medium"
6051
6013
  (click)="clearAll()"
6052
- [disabled]="selectedValues().length === 0"
6014
+ [disabled]="selectedValues.length === 0"
6053
6015
  >
6054
6016
  Limpiar
6055
6017
  </ion-button>
6056
6018
  </div>
6057
6019
 
6058
- <!-- Debug button -->
6059
- <div class="search-container" style="background: red; color: white; padding: 4px;">
6060
- <button (click)="debugOptions()">DEBUG: {{ filteredOptions().length }} opciones</button>
6061
- </div>
6062
-
6063
6020
  <!-- Options list -->
6064
6021
  <div class="options-container">
6065
6022
  <ion-list class="options-list">
6066
6023
  <ion-item
6067
- *ngFor="let option of filteredOptions(); trackBy: trackByFn"
6024
+ *ngFor="let option of filteredOptions; trackBy: trackByFn"
6068
6025
  button
6069
6026
  (click)="toggleOption(option)"
6070
6027
  class="option-item"
@@ -6077,9 +6034,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
6077
6034
  </ion-item>
6078
6035
 
6079
6036
  <!-- No results message -->
6080
- <ion-item *ngIf="filteredOptions().length === 0" class="no-results">
6037
+ <ion-item *ngIf="filteredOptions.length === 0" class="no-results">
6081
6038
  <ion-label color="medium">
6082
- {{ searchTerm() ? 'No se encontraron resultados' : 'No hay opciones disponibles' }}
6039
+ {{ searchTerm ? 'No se encontraron resultados' : 'No hay opciones disponibles' }}
6083
6040
  </ion-label>
6084
6041
  </ion-item>
6085
6042
  </ion-list>
@@ -6817,105 +6774,39 @@ class SelectSearchComponent {
6817
6774
  this.valueProperty = 'id';
6818
6775
  this.placeholder = '';
6819
6776
  this.langService = inject(LangService);
6820
- // Signals for reactive state management
6821
- this.isOpen = signal(false);
6822
- this.searchTerm = signal('');
6823
- this.selectedValue = signal(null);
6824
- // Force options to be reactive
6825
- this.optionsSignal = signal([]);
6826
- // Computed signals
6827
- this.displayValue = computed(() => {
6828
- const value = this.selectedValue();
6829
- if (!value)
6830
- return '';
6831
- const option = this.getOptionByValue(value);
6832
- return option ? option[this.labelProperty] : '';
6833
- });
6834
- this.filteredOptions = computed(() => {
6835
- // Use signal instead of props directly
6836
- const options = this.optionsSignal();
6837
- const search = this.searchTerm().toLowerCase();
6838
- // Debug mejorado
6839
- console.log('[SelectSearch] filteredOptions computed:', {
6840
- optionsCount: options.length,
6841
- searchTerm: search,
6842
- options: options,
6843
- labelProperty: this.labelProperty,
6844
- valueProperty: this.valueProperty,
6845
- propsExists: !!this.props,
6846
- propsOptionsExists: !!this.props?.options,
6847
- propsOptionsLength: this.props?.options?.length || 0,
6848
- firstOptionStructure: options[0] ? {
6849
- [this.labelProperty]: options[0][this.labelProperty],
6850
- [this.valueProperty]: options[0][this.valueProperty],
6851
- typeOfId: typeof options[0][this.valueProperty],
6852
- fullOption: options[0]
6853
- } : 'NO_OPTIONS'
6854
- });
6855
- if (!search) {
6856
- return options;
6857
- }
6858
- return options.filter(option => {
6859
- const label = option[this.labelProperty]
6860
- ? replaceSpecialChars(String(option[this.labelProperty]).toLowerCase())
6861
- : '';
6862
- const value = option[this.valueProperty]
6863
- ? replaceSpecialChars(String(option[this.valueProperty]).toLowerCase())
6864
- : '';
6865
- const searchTerm = replaceSpecialChars(search);
6866
- return label.includes(searchTerm) || value.includes(searchTerm);
6867
- });
6868
- });
6777
+ this.changeDetector = inject(ChangeDetectorRef);
6778
+ // Classic Angular properties
6779
+ this.isOpen = false;
6780
+ this.searchTerm = '';
6781
+ this.selectedValue = null;
6782
+ this.displayValue = '';
6783
+ this.filteredOptions = [];
6869
6784
  this.placeholder = this.langService.getText('_global', 'selectOption', 'Seleccione una opción');
6870
6785
  // Close dropdown when clicking outside
6871
6786
  document.addEventListener('click', this.handleClickOutside.bind(this));
6872
- // Debug effect to track when filteredOptions changes
6873
- effect(() => {
6874
- const options = this.filteredOptions();
6875
- console.log('[SelectSearch] EFFECT - filteredOptions changed:', {
6876
- optionsCount: options.length,
6877
- options: options,
6878
- timestamp: new Date().toLocaleTimeString()
6879
- });
6880
- });
6881
6787
  }
6882
6788
  ngOnInit() {
6883
- console.log('[SelectSearch] ngOnInit:', {
6884
- props: !!this.props,
6885
- options: this.props?.options?.length || 0,
6886
- control: !!this.props?.control
6887
- });
6888
- // Update options signal
6889
- if (this.props?.options) {
6890
- this.optionsSignal.set(this.props.options);
6891
- }
6892
6789
  this.applyDefaultValue();
6790
+ this.initializeOptions();
6893
6791
  this.syncSelectedValue();
6792
+ this.updateDisplayValue();
6894
6793
  }
6895
6794
  ngOnDestroy() {
6896
6795
  document.removeEventListener('click', this.handleClickOutside.bind(this));
6897
6796
  }
6898
6797
  ngOnChanges(changes) {
6899
- console.log('[SelectSearch] ngOnChanges:', {
6900
- hasPropsChange: !!changes['props'],
6901
- props: !!this.props,
6902
- options: this.props?.options?.length || 0,
6903
- propsOptions: this.props?.options
6904
- });
6905
6798
  if (changes['props'] && this.props) {
6906
- // Update options signal when props change
6907
- if (this.props.options) {
6908
- console.log('[SelectSearch] Updating optionsSignal with:', this.props.options);
6909
- this.optionsSignal.set(this.props.options);
6910
- }
6799
+ this.initializeOptions();
6911
6800
  this.syncSelectedValue();
6801
+ this.updateDisplayValue();
6802
+ this.changeDetector.detectChanges();
6912
6803
  }
6913
6804
  }
6914
6805
  // Component methods
6915
6806
  toggleDropdown(event) {
6916
6807
  event.stopPropagation();
6917
- this.isOpen.update(value => !value);
6918
- if (this.isOpen()) {
6808
+ this.isOpen = !this.isOpen;
6809
+ if (this.isOpen) {
6919
6810
  // Focus search bar when opening if available
6920
6811
  setTimeout(() => {
6921
6812
  const searchbar = this.dropdownRef?.nativeElement?.querySelector('ion-searchbar');
@@ -6926,13 +6817,16 @@ class SelectSearchComponent {
6926
6817
  }
6927
6818
  }
6928
6819
  onSearch(event) {
6929
- this.searchTerm.set(event.detail.value || '');
6820
+ this.searchTerm = event.detail.value || '';
6821
+ this.filterOptions();
6930
6822
  }
6931
6823
  selectOption(option) {
6932
- const value = String(option[this.valueProperty]); // Convertir a string
6933
- this.selectedValue.set(value);
6934
- this.isOpen.set(false);
6935
- this.searchTerm.set('');
6824
+ const value = String(option[this.valueProperty]);
6825
+ this.selectedValue = value;
6826
+ this.isOpen = false;
6827
+ this.searchTerm = '';
6828
+ this.updateDisplayValue();
6829
+ this.initializeOptions(); // Reset filter
6936
6830
  // Update form control
6937
6831
  if (this.props?.control) {
6938
6832
  this.props.control.setValue(value);
@@ -6941,21 +6835,49 @@ class SelectSearchComponent {
6941
6835
  }
6942
6836
  }
6943
6837
  isSelected(option) {
6944
- return String(this.selectedValue()) === String(option[this.valueProperty]);
6838
+ return String(this.selectedValue) === String(option[this.valueProperty]);
6945
6839
  }
6946
6840
  trackByFn(_index, option) {
6947
6841
  return option[this.valueProperty];
6948
6842
  }
6949
6843
  handleClickOutside(event) {
6950
- if (this.isOpen() &&
6844
+ if (this.isOpen &&
6951
6845
  !this.mainInputRef?.nativeElement?.contains(event.target) &&
6952
6846
  !this.dropdownRef?.nativeElement?.contains(event.target)) {
6953
- this.isOpen.set(false);
6954
- this.searchTerm.set('');
6847
+ this.isOpen = false;
6848
+ this.searchTerm = '';
6849
+ this.initializeOptions();
6955
6850
  }
6956
6851
  }
6957
6852
  getOptionByValue(value) {
6958
- return this.optionsSignal().find(option => String(option[this.valueProperty]) === String(value));
6853
+ return this.filteredOptions.find(option => String(option[this.valueProperty]) === String(value));
6854
+ }
6855
+ initializeOptions() {
6856
+ this.filteredOptions = this.props?.options || [];
6857
+ }
6858
+ filterOptions() {
6859
+ if (!this.searchTerm) {
6860
+ this.initializeOptions();
6861
+ return;
6862
+ }
6863
+ const search = replaceSpecialChars(this.searchTerm.toLowerCase());
6864
+ this.filteredOptions = (this.props?.options || []).filter(option => {
6865
+ const label = option[this.labelProperty]
6866
+ ? replaceSpecialChars(String(option[this.labelProperty]).toLowerCase())
6867
+ : '';
6868
+ const value = option[this.valueProperty]
6869
+ ? replaceSpecialChars(String(option[this.valueProperty]).toLowerCase())
6870
+ : '';
6871
+ return label.includes(search) || value.includes(search);
6872
+ });
6873
+ }
6874
+ updateDisplayValue() {
6875
+ if (!this.selectedValue) {
6876
+ this.displayValue = '';
6877
+ return;
6878
+ }
6879
+ const option = this.getOptionByValue(this.selectedValue);
6880
+ this.displayValue = option ? option[this.labelProperty] : '';
6959
6881
  }
6960
6882
  applyDefaultValue() {
6961
6883
  if (this.props) {
@@ -6965,15 +6887,17 @@ class SelectSearchComponent {
6965
6887
  debugOptions() {
6966
6888
  console.log('[SelectSearch] DEBUG CLICK:', {
6967
6889
  props: this.props,
6968
- filteredOptions: this.filteredOptions(),
6969
- searchTerm: this.searchTerm(),
6890
+ filteredOptions: this.filteredOptions,
6891
+ searchTerm: this.searchTerm,
6970
6892
  propsOptions: this.props?.options,
6971
- computed: this.filteredOptions()
6893
+ displayValue: this.displayValue,
6894
+ selectedValue: this.selectedValue,
6895
+ isOpen: this.isOpen
6972
6896
  });
6973
6897
  }
6974
6898
  syncSelectedValue() {
6975
6899
  if (this.props?.control?.value) {
6976
- this.selectedValue.set(String(this.props.control.value));
6900
+ this.selectedValue = String(this.props.control.value);
6977
6901
  }
6978
6902
  }
6979
6903
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SelectSearchComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
@@ -6983,18 +6907,18 @@ class SelectSearchComponent {
6983
6907
  <ion-input
6984
6908
  #mainInput
6985
6909
  type="text"
6986
- [value]="displayValue()"
6910
+ [value]="displayValue"
6987
6911
  [placeholder]="props?.placeholder || placeholder"
6988
6912
  readonly
6989
6913
  class="main-input"
6990
- [class.is-open]="isOpen()"
6914
+ [class.is-open]="isOpen"
6991
6915
  />
6992
6916
 
6993
6917
  <!-- Dropdown icon -->
6994
6918
  <ion-icon
6995
6919
  name="chevron-down-outline"
6996
6920
  class="dropdown-icon"
6997
- [class.rotated]="isOpen()"
6921
+ [class.rotated]="isOpen"
6998
6922
  ></ion-icon>
6999
6923
 
7000
6924
  <!-- Hidden input for form control -->
@@ -7008,12 +6932,12 @@ class SelectSearchComponent {
7008
6932
  <!-- Dropdown overlay -->
7009
6933
  <div
7010
6934
  class="dropdown-overlay"
7011
- [class.visible]="isOpen()"
6935
+ [class.visible]="isOpen"
7012
6936
  #dropdown
7013
6937
  >
7014
6938
  <!-- Debug button -->
7015
6939
  <div class="search-container" style="background: red; color: white; padding: 4px;">
7016
- <button (click)="debugOptions()">DEBUG: {{ filteredOptions().length }} opciones</button>
6940
+ <button (click)="debugOptions()">DEBUG: {{ filteredOptions.length }} opciones</button>
7017
6941
  </div>
7018
6942
 
7019
6943
  <!-- Search bar -->
@@ -7022,7 +6946,7 @@ class SelectSearchComponent {
7022
6946
  #searchbar
7023
6947
  [placeholder]="'Buscar'"
7024
6948
  (ionInput)="onSearch($event)"
7025
- [value]="searchTerm()"
6949
+ [value]="searchTerm"
7026
6950
  show-clear-button="focus"
7027
6951
  [debounce]="200"
7028
6952
  ></ion-searchbar>
@@ -7032,7 +6956,7 @@ class SelectSearchComponent {
7032
6956
  <div class="options-container">
7033
6957
  <ion-list class="options-list">
7034
6958
  <ion-item
7035
- *ngFor="let option of filteredOptions(); trackBy: trackByFn"
6959
+ *ngFor="let option of filteredOptions; trackBy: trackByFn"
7036
6960
  button
7037
6961
  (click)="selectOption(option)"
7038
6962
  class="option-item"
@@ -7047,11 +6971,11 @@ class SelectSearchComponent {
7047
6971
  </ion-item>
7048
6972
 
7049
6973
  <!-- No results message -->
7050
- <ion-item *ngIf="filteredOptions().length === 0" class="no-results">
6974
+ <ion-item *ngIf="filteredOptions.length === 0" class="no-results">
7051
6975
  <ion-label color="medium">
7052
- {{ searchTerm() ? 'No se encontraron resultados' : 'No hay opciones disponibles' }}
6976
+ {{ searchTerm ? 'No se encontraron resultados' : 'No hay opciones disponibles' }}
7053
6977
  <!-- Debug info -->
7054
- <br><small>Debug: {{ filteredOptions().length }} opciones | Props: {{ !!props }} | Search: "{{ searchTerm() }}"</small>
6978
+ <br><small>Debug: {{ filteredOptions.length }} opciones | Props: {{ !!props }} | Search: "{{ searchTerm }}"</small>
7055
6979
  </ion-label>
7056
6980
  </ion-item>
7057
6981
  </ion-list>
@@ -7067,18 +6991,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
7067
6991
  <ion-input
7068
6992
  #mainInput
7069
6993
  type="text"
7070
- [value]="displayValue()"
6994
+ [value]="displayValue"
7071
6995
  [placeholder]="props?.placeholder || placeholder"
7072
6996
  readonly
7073
6997
  class="main-input"
7074
- [class.is-open]="isOpen()"
6998
+ [class.is-open]="isOpen"
7075
6999
  />
7076
7000
 
7077
7001
  <!-- Dropdown icon -->
7078
7002
  <ion-icon
7079
7003
  name="chevron-down-outline"
7080
7004
  class="dropdown-icon"
7081
- [class.rotated]="isOpen()"
7005
+ [class.rotated]="isOpen"
7082
7006
  ></ion-icon>
7083
7007
 
7084
7008
  <!-- Hidden input for form control -->
@@ -7092,12 +7016,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
7092
7016
  <!-- Dropdown overlay -->
7093
7017
  <div
7094
7018
  class="dropdown-overlay"
7095
- [class.visible]="isOpen()"
7019
+ [class.visible]="isOpen"
7096
7020
  #dropdown
7097
7021
  >
7098
7022
  <!-- Debug button -->
7099
7023
  <div class="search-container" style="background: red; color: white; padding: 4px;">
7100
- <button (click)="debugOptions()">DEBUG: {{ filteredOptions().length }} opciones</button>
7024
+ <button (click)="debugOptions()">DEBUG: {{ filteredOptions.length }} opciones</button>
7101
7025
  </div>
7102
7026
 
7103
7027
  <!-- Search bar -->
@@ -7106,7 +7030,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
7106
7030
  #searchbar
7107
7031
  [placeholder]="'Buscar'"
7108
7032
  (ionInput)="onSearch($event)"
7109
- [value]="searchTerm()"
7033
+ [value]="searchTerm"
7110
7034
  show-clear-button="focus"
7111
7035
  [debounce]="200"
7112
7036
  ></ion-searchbar>
@@ -7116,7 +7040,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
7116
7040
  <div class="options-container">
7117
7041
  <ion-list class="options-list">
7118
7042
  <ion-item
7119
- *ngFor="let option of filteredOptions(); trackBy: trackByFn"
7043
+ *ngFor="let option of filteredOptions; trackBy: trackByFn"
7120
7044
  button
7121
7045
  (click)="selectOption(option)"
7122
7046
  class="option-item"
@@ -7131,11 +7055,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
7131
7055
  </ion-item>
7132
7056
 
7133
7057
  <!-- No results message -->
7134
- <ion-item *ngIf="filteredOptions().length === 0" class="no-results">
7058
+ <ion-item *ngIf="filteredOptions.length === 0" class="no-results">
7135
7059
  <ion-label color="medium">
7136
- {{ searchTerm() ? 'No se encontraron resultados' : 'No hay opciones disponibles' }}
7060
+ {{ searchTerm ? 'No se encontraron resultados' : 'No hay opciones disponibles' }}
7137
7061
  <!-- Debug info -->
7138
- <br><small>Debug: {{ filteredOptions().length }} opciones | Props: {{ !!props }} | Search: "{{ searchTerm() }}"</small>
7062
+ <br><small>Debug: {{ filteredOptions.length }} opciones | Props: {{ !!props }} | Search: "{{ searchTerm }}"</small>
7139
7063
  </ion-label>
7140
7064
  </ion-item>
7141
7065
  </ion-list>
@@ -8357,6 +8281,8 @@ class FormComponent {
8357
8281
  }
8358
8282
  trackSelectChanges(fieldName) {
8359
8283
  const control = this.getControl(fieldName);
8284
+ // Initialize previous value
8285
+ this.previousValues.set(fieldName, control.value);
8360
8286
  const subscription = control.valueChanges
8361
8287
  .pipe(distinctUntilChanged$1()) // Evitar valores duplicados
8362
8288
  .subscribe(value => {
@@ -8442,6 +8368,19 @@ class FormComponent {
8442
8368
  data: this.props,
8443
8369
  };
8444
8370
  }
8371
+ // Helper method to reset field value without triggering change event
8372
+ resetField(fieldName, emitEvent = false) {
8373
+ const control = this.getControl(fieldName);
8374
+ const currentValue = control.value;
8375
+ console.log(`[FormComponent] Resetting field ${fieldName}:`, { currentValue, emitEvent });
8376
+ // Update our cache to avoid triggering change event
8377
+ if (!emitEvent) {
8378
+ this.previousValues.set(fieldName, '');
8379
+ }
8380
+ control.setValue('', { emitEvent });
8381
+ control.markAsPristine();
8382
+ control.markAsUntouched();
8383
+ }
8445
8384
  get actions() {
8446
8385
  if (!this.form) {
8447
8386
  return [];