@jvsoft/components 1.0.0-alpha.8 → 1.0.0-alpha.9

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.
@@ -0,0 +1,613 @@
1
+ import * as i0 from '@angular/core';
2
+ import { signal, Injectable, InjectionToken, inject, input, output, Component } from '@angular/core';
3
+ import * as i1 from '@angular/common';
4
+ import { CommonModule } from '@angular/common';
5
+ import { BehaviorSubject, Subject } from 'rxjs';
6
+ import moment from 'moment';
7
+ import * as i2 from '@angular/forms';
8
+ import { FormBuilder, FormsModule, ReactiveFormsModule } from '@angular/forms';
9
+ import * as i3 from '@angular/material/autocomplete';
10
+ import { MatAutocompleteModule } from '@angular/material/autocomplete';
11
+ import { MatCheckboxModule } from '@angular/material/checkbox';
12
+ import * as i4 from '@angular/material/datepicker';
13
+ import { MatDatepickerModule } from '@angular/material/datepicker';
14
+ import * as i5 from '@angular/material/form-field';
15
+ import { MatFormFieldModule } from '@angular/material/form-field';
16
+ import * as i6 from '@angular/material/icon';
17
+ import { MatIconModule } from '@angular/material/icon';
18
+ import { MatInputModule } from '@angular/material/input';
19
+ import * as i7 from '@angular/material/core';
20
+ import { MatOptionModule, MatRippleModule } from '@angular/material/core';
21
+ import { MatRadioModule } from '@angular/material/radio';
22
+ import { MatSelectModule } from '@angular/material/select';
23
+ import * as i8 from '@angular/material/tabs';
24
+ import { MatTabsModule } from '@angular/material/tabs';
25
+ import { TextFieldModule } from '@angular/cdk/text-field';
26
+ import { debounceTime, takeUntil, distinctUntilChanged } from 'rxjs/operators';
27
+ import { ToastrService } from 'ngx-toastr';
28
+ import { generateRandomString, dataEnLista, tipoValorFuncion, getUniqueValues, establecerQuitarRequired, mostrarValorEnBusqueda, getFormValidationErrors } from '@jvsoft/utils';
29
+
30
+ class FiltroBusquedaService {
31
+ // We maintain legacy subjects for compatibility if needed, but favor Signals
32
+ _filtrosActivos = signal(new Map());
33
+ // Exposed signals
34
+ filtrosActivos = this._filtrosActivos.asReadonly();
35
+ nombreColeccionFiltroBusquedaPrincipal = 'filtro_busqueda_principal';
36
+ dFiltroBusqueda = {};
37
+ coleccionDataServidorSuscripcion = {};
38
+ crearFiltro(nombreFiltro) {
39
+ if (!this.dFiltroBusqueda[nombreFiltro]) {
40
+ this.dFiltroBusqueda[nombreFiltro] = new BehaviorSubject(null);
41
+ }
42
+ }
43
+ setValue(nombreFiltro, val) {
44
+ this.crearFiltro(nombreFiltro);
45
+ this.dFiltroBusqueda[nombreFiltro].next(val);
46
+ // Update signal state
47
+ this._filtrosActivos.update(map => {
48
+ const nextMap = new Map(map);
49
+ nextMap.set(nombreFiltro, val);
50
+ return nextMap;
51
+ });
52
+ }
53
+ getValue(nombreFiltro) {
54
+ return this.dFiltroBusqueda[nombreFiltro]?.getValue();
55
+ }
56
+ setDataServidorSuscripcion(nombreFiltro, campo, data) {
57
+ if (!this.coleccionDataServidorSuscripcion[nombreFiltro]) {
58
+ this.coleccionDataServidorSuscripcion[nombreFiltro] = {};
59
+ }
60
+ if (!this.coleccionDataServidorSuscripcion[nombreFiltro][campo]) {
61
+ this.coleccionDataServidorSuscripcion[nombreFiltro][campo] = new BehaviorSubject(null);
62
+ }
63
+ this.coleccionDataServidorSuscripcion[nombreFiltro][campo].next(data);
64
+ }
65
+ getDataServidorSuscripcion(nombreFiltro, campo) {
66
+ return this.coleccionDataServidorSuscripcion[nombreFiltro]?.[campo];
67
+ }
68
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: FiltroBusquedaService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
69
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: FiltroBusquedaService, providedIn: 'root' });
70
+ }
71
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: FiltroBusquedaService, decorators: [{
72
+ type: Injectable,
73
+ args: [{
74
+ providedIn: 'root',
75
+ }]
76
+ }] });
77
+
78
+ const QUERY_SERVICE_TOKEN = new InjectionToken('QUERY_SERVICE_TOKEN');
79
+ class FiltroBusquedaComponent {
80
+ fb = inject(FormBuilder);
81
+ toastr = inject(ToastrService);
82
+ filtroBusquedaService = inject(FiltroBusquedaService);
83
+ queryService = inject(QUERY_SERVICE_TOKEN, { optional: true });
84
+ opciones = input([]);
85
+ nombreColeccionInput = input(generateRandomString(10), { alias: 'nombreColeccion' });
86
+ prefijoConsulta = input('grl');
87
+ busquedaAutomatica = input(false);
88
+ opciones$ = input();
89
+ modificarOpciones$ = input();
90
+ defaultTab = input(0);
91
+ dataFiltro = output();
92
+ resultados = output();
93
+ cargaCompleta = output();
94
+ tabActual = signal(0);
95
+ dataOpcionesNuevo = signal([]);
96
+ isCargaCompleta = signal(false);
97
+ frmFiltroBusqueda = this.fb.group({
98
+ opcion: [0],
99
+ opciones: this.fb.array([]),
100
+ });
101
+ get opcionesTabs() {
102
+ return this.frmFiltroBusqueda.get('opciones');
103
+ }
104
+ get frmGroupSeleccionado() {
105
+ return this.opcionesTabs.at(this.tabActual()) || this.fb.group({});
106
+ }
107
+ getControl(nombre) {
108
+ return this.frmGroupSeleccionado.get(nombre);
109
+ }
110
+ getControlRaiz(nombre) {
111
+ return this.frmFiltroBusqueda.get(nombre);
112
+ }
113
+ getAutocompleteLabel(controlData, value) {
114
+ if (!value)
115
+ return '';
116
+ const config = controlData.autocomplete;
117
+ if (!config)
118
+ return '';
119
+ const list = this.dataServidorSuscripcion[config.data]?.getValue() || [];
120
+ const item = dataEnLista(list, config.campoValor || controlData.campo, value);
121
+ if (item) {
122
+ return this.campoTextEval(controlData, item);
123
+ }
124
+ // Fallback search in the filtered results if not in the main list
125
+ const filteredList = this.filtrados[controlData.campo] || [];
126
+ const filteredItem = dataEnLista(filteredList, config.campoValor || controlData.campo, value);
127
+ if (filteredItem) {
128
+ return this.campoTextEval(controlData, filteredItem);
129
+ }
130
+ return value?.toString() || '';
131
+ }
132
+ dataServidor = {};
133
+ dataServidorSuscripcion = {};
134
+ filtrados = {};
135
+ inputParaEnviarAutocomplete = new Subject();
136
+ destroy$ = new Subject();
137
+ sufixTemporal = '_temporal';
138
+ tipoValorFuncion = tipoValorFuncion;
139
+ fechaActual = moment().toDate();
140
+ constructor() {
141
+ this.inputParaEnviarAutocomplete.pipe(debounceTime(500), takeUntil(this.destroy$)).subscribe((param) => {
142
+ this.queryService?.cargar(this, [param.reqQuery], param.reqData, false, this.prefijoConsulta()).then((dRet) => {
143
+ if (dRet) {
144
+ this.filtrados[param.controlData.campo] = dRet[param.reqQuery];
145
+ this.filtroBusquedaService.setDataServidorSuscripcion(this.nombreColeccionInput(), param.controlData.campo, dRet[param.reqQuery]);
146
+ }
147
+ });
148
+ });
149
+ }
150
+ ngOnInit() {
151
+ this.tabActual.set(this.defaultTab());
152
+ this.frmFiltroBusqueda.get('opcion')?.setValue(this.tabActual());
153
+ if (this.opciones().length > 0) {
154
+ this.initOpciones(this.opciones());
155
+ }
156
+ this.opciones$()?.pipe(takeUntil(this.destroy$)).subscribe(val => {
157
+ if (val)
158
+ this.initOpciones(val);
159
+ });
160
+ this.modificarOpciones$()?.pipe(takeUntil(this.destroy$)).subscribe(val => {
161
+ if (val) {
162
+ Object.keys(val).forEach(x => {
163
+ const ev = val[x];
164
+ this.actualizarEnFormArray(x, ev.value ?? ev['val'], { disabled: ev.disabled });
165
+ });
166
+ }
167
+ });
168
+ this.frmFiltroBusqueda.valueChanges.pipe(distinctUntilChanged(), takeUntil(this.destroy$)).subscribe(() => {
169
+ this.actualizarEstadoService();
170
+ });
171
+ this.frmFiltroBusqueda.get('opcion')?.valueChanges.pipe(distinctUntilChanged(), takeUntil(this.destroy$)).subscribe((val) => {
172
+ if (val !== null) {
173
+ this.tabActual.set(val);
174
+ this.cargarDatosFiltroNuevo(val);
175
+ }
176
+ });
177
+ }
178
+ initOpciones(val) {
179
+ const nOpc = this.reorganizarOpcionesNuevas(val);
180
+ this.dataOpcionesNuevo.set(nOpc);
181
+ this.cargarDatosFiltroNuevo();
182
+ }
183
+ reorganizarOpcionesNuevas(val) {
184
+ return val.filter(tab => !tab.esVisible || tipoValorFuncion(tab.esVisible, true, tab)).map(tab => ({
185
+ label: tab.label,
186
+ campos: tab.campos || []
187
+ }));
188
+ }
189
+ async cargarDatosFiltroNuevo(idTab) {
190
+ const tabIdx = idTab !== undefined ? idTab : this.tabActual();
191
+ const currentTab = this.dataOpcionesNuevo()[tabIdx];
192
+ if (!currentTab)
193
+ return;
194
+ let llamadasJuntas = [[], [], [], [], []];
195
+ let llamadasJuntasParams = [{}, {}, {}, {}, {}];
196
+ const camposDisabled = [];
197
+ const camposRequired = [];
198
+ const procesarCampos = (campos, grupoFrm, agrupado = false) => {
199
+ campos.forEach((campo) => {
200
+ let val = campo;
201
+ if (val.modificadorDatos)
202
+ val = val.modificadorDatos(val);
203
+ if (val.disabled)
204
+ camposDisabled.push(val.campo);
205
+ if (val.required)
206
+ camposRequired.push(val.campo);
207
+ if (val.dateRange) {
208
+ const [fIni, fFin] = val.dateRange.campo;
209
+ grupoFrm[fIni] = val.dateRange.value?.[0] === '*fechaActual*' ? this.fechaActual : (val.dateRange.value?.[0] || '');
210
+ grupoFrm[fFin] = val.dateRange.value?.[1] === '*fechaActual*' ? this.fechaActual : (val.dateRange.value?.[1] || '');
211
+ }
212
+ else if (val.autocomplete) {
213
+ grupoFrm[val.campo + this.sufixTemporal] = val.value || '';
214
+ grupoFrm[val.campo] = val.value || '';
215
+ }
216
+ else if (val.controlAgrupado) {
217
+ grupoFrm[val.campo] = val.value || '';
218
+ procesarCampos(val.controlAgrupado, grupoFrm, true);
219
+ }
220
+ else {
221
+ grupoFrm[val.campo] = val.value === '*fechaActual*' ? this.fechaActual : (val.value || '');
222
+ }
223
+ if (val.select || val.autocomplete) {
224
+ const config = (val.select || val.autocomplete);
225
+ if (agrupado)
226
+ config.ordenPeticion = 3;
227
+ if (config.customData) {
228
+ this.setCustomData(config.data, config.customData);
229
+ }
230
+ else {
231
+ const level = config.ordenPeticion || 0;
232
+ if (config.data)
233
+ llamadasJuntas[level].push(config.data);
234
+ if (val.reqParams?.fields) {
235
+ val.reqParams.fields.forEach(f => {
236
+ if (grupoFrm[f] && !['*primero*', '*deUsuario*'].includes(grupoFrm[f])) {
237
+ llamadasJuntasParams[level][f] = grupoFrm[f];
238
+ }
239
+ });
240
+ }
241
+ if (val.reqParams?.params) {
242
+ llamadasJuntasParams[level] = { ...llamadasJuntasParams[level], ...val.reqParams.params };
243
+ }
244
+ }
245
+ }
246
+ });
247
+ };
248
+ const targetOpciones = idTab !== undefined ? [this.dataOpcionesNuevo()[idTab]] : this.dataOpcionesNuevo();
249
+ targetOpciones.forEach(tab => {
250
+ const grupoFrm = {};
251
+ procesarCampos(tab.campos, grupoFrm);
252
+ const group = this.fb.group(grupoFrm);
253
+ if (idTab === undefined) {
254
+ this.opcionesTabs.push(group);
255
+ }
256
+ else {
257
+ this.opcionesTabs.setControl(idTab, group);
258
+ }
259
+ });
260
+ getUniqueValues(camposDisabled).forEach(c => this.actualizarEnFormArray(c, undefined, { disabled: true }));
261
+ establecerQuitarRequired(this.frmGroupSeleccionado, getUniqueValues(camposRequired));
262
+ const cargaNivel = async (idx) => {
263
+ const types = getUniqueValues(llamadasJuntas[idx]);
264
+ if (types.length === 0)
265
+ return;
266
+ const dRet = await this.queryService?.cargar(this, types, llamadasJuntasParams[idx], false, this.prefijoConsulta());
267
+ if (dRet) {
268
+ this.procesarRetornoDatos(idx, dRet, llamadasJuntasParams);
269
+ }
270
+ };
271
+ await cargaNivel(0);
272
+ await cargaNivel(1);
273
+ await cargaNivel(2);
274
+ await cargaNivel(3);
275
+ await cargaNivel(4);
276
+ this.isCargaCompleta.set(true);
277
+ this.actualizarEstadoService();
278
+ this.cargaCompleta.emit(true);
279
+ }
280
+ actualizarEstadoService() {
281
+ if (this.isCargaCompleta()) {
282
+ const res = this.getFiltroResultante();
283
+ this.filtroBusquedaService.setValue(this.nombreColeccionInput(), res);
284
+ this.dataFiltro.emit(res.datosFiltro);
285
+ }
286
+ }
287
+ setCustomData(key, data) {
288
+ if (!this.dataServidorSuscripcion[key]) {
289
+ this.dataServidorSuscripcion[key] = new BehaviorSubject(null);
290
+ }
291
+ this.dataServidorSuscripcion[key].next(data);
292
+ }
293
+ procesarRetornoDatos(idxLevel, data, paramsRef) {
294
+ const tabCampos = this.dataOpcionesNuevo()[this.tabActual()].campos;
295
+ const affected = tabCampos.filter(c => {
296
+ const config = c.select || c.autocomplete;
297
+ return config && (config.ordenPeticion || 0) === idxLevel;
298
+ });
299
+ affected.forEach(campo => {
300
+ const config = (campo.select || campo.autocomplete);
301
+ const res = data[config.data];
302
+ if (!this.dataServidorSuscripcion[config.data]) {
303
+ this.dataServidorSuscripcion[config.data] = new BehaviorSubject(null);
304
+ }
305
+ this.dataServidorSuscripcion[config.data].next(res);
306
+ this.filtroBusquedaService.setDataServidorSuscripcion(this.nombreColeccionInput(), campo.campo, res);
307
+ if (campo.value === '*primero*' && res?.length > 0) {
308
+ const firstVal = config.campoValor === '*objeto*' ? res[0] : res[0][config.campoValor || campo.campo];
309
+ this.actualizarEnFormArray(campo.campo, firstVal);
310
+ paramsRef.forEach((p, i) => {
311
+ if (i > idxLevel && p[campo.campo] === '')
312
+ p[campo.campo] = firstVal;
313
+ });
314
+ }
315
+ if (campo.autocomplete) {
316
+ this.filtrados[campo.campo] = res;
317
+ }
318
+ if (campo.change) {
319
+ this.cambiarSeleccionNuevo(campo);
320
+ }
321
+ });
322
+ }
323
+ getFiltroResultante() {
324
+ const rawForm = this.frmGroupSeleccionado.getRawValue();
325
+ const datosFiltro = { opcion: this.tabActual() };
326
+ const datosFiltroConLabel = [];
327
+ const resumenItems = [];
328
+ const campos = this.dataOpcionesNuevo()[this.tabActual()]?.campos || [];
329
+ const procesarMetadatos = (campo) => {
330
+ const meta = { campo: campo.campo, label: campo.label || '', value: null };
331
+ if (campo.dateRange) {
332
+ const [fIni, fFin] = campo.dateRange.campo;
333
+ datosFiltro[fIni] = rawForm[fIni] ? moment(rawForm[fIni]).format('YYYYMMDD') : '';
334
+ datosFiltro[fFin] = rawForm[fFin] ? moment(rawForm[fFin]).format('YYYYMMDD') : '';
335
+ if (rawForm[fIni] && rawForm[fFin]) {
336
+ meta.value = `${moment(rawForm[fIni]).format('DD/MM/YYYY')} - ${moment(rawForm[fFin]).format('DD/MM/YYYY')}`;
337
+ resumenItems.push(`${meta.label}: ${meta.value}`);
338
+ }
339
+ }
340
+ else if (campo.control === 'date') {
341
+ const val = rawForm[campo.campo];
342
+ datosFiltro[campo.campo] = val ? moment(val).format('YYYYMMDD') : '';
343
+ meta.value = val ? moment(val).format('DD/MM/YYYY') : '';
344
+ if (meta.value)
345
+ resumenItems.push(`${meta.label}: ${meta.value}`);
346
+ }
347
+ else if (campo.control === 'checkbox') {
348
+ datosFiltro[campo.campo] = rawForm[campo.campo];
349
+ meta.value = rawForm[campo.campo];
350
+ if (meta.value)
351
+ resumenItems.push(`${meta.label}`);
352
+ }
353
+ else {
354
+ const val = rawForm[campo.campo];
355
+ datosFiltro[campo.campo] = val;
356
+ meta.value = val;
357
+ if (campo.select || campo.autocomplete) {
358
+ const config = (campo.select || campo.autocomplete);
359
+ const list = this.dataServidorSuscripcion[config.data]?.getValue() || [];
360
+ const item = config.campoValor === '*objeto*' ? val : dataEnLista(list, config.campoValor || campo.campo, val);
361
+ if (item) {
362
+ meta.list = list;
363
+ meta.valueObject = item;
364
+ meta.valueString = this.campoTextEval(campo, item);
365
+ resumenItems.push(`${meta.label}: ${meta.valueString}`);
366
+ }
367
+ }
368
+ else if (val !== null && val !== undefined && val !== '') {
369
+ resumenItems.push(`${meta.label}: ${val}`);
370
+ }
371
+ }
372
+ datosFiltroConLabel.push(meta);
373
+ };
374
+ campos.forEach(c => {
375
+ if (c.controlAgrupado) {
376
+ c.controlAgrupado.forEach(sub => procesarMetadatos(sub));
377
+ }
378
+ else {
379
+ procesarMetadatos(c);
380
+ }
381
+ });
382
+ const labelResumen = resumenItems.join(' | ');
383
+ return { datosFiltro, datosFiltroConLabel, labelResumen };
384
+ }
385
+ mostrarValorEnBusqueda = mostrarValorEnBusqueda;
386
+ campoValorEval(campoFiltro, itemSelect) {
387
+ if (campoFiltro.select || campoFiltro.autocomplete) {
388
+ const selectOrAutocomplete = campoFiltro.select ? campoFiltro.select : campoFiltro.autocomplete;
389
+ if (selectOrAutocomplete?.campoValor === '*objeto*') {
390
+ return itemSelect;
391
+ }
392
+ if (campoFiltro.campo === '*objeto*') {
393
+ return itemSelect;
394
+ }
395
+ if (selectOrAutocomplete && itemSelect[selectOrAutocomplete.campoValor] !== undefined) {
396
+ return itemSelect[selectOrAutocomplete.campoValor];
397
+ }
398
+ }
399
+ return itemSelect[campoFiltro.campo];
400
+ }
401
+ campoTextEval(campoFiltro, itemSelect) {
402
+ if (campoFiltro.select || campoFiltro.autocomplete) {
403
+ const selectOrAutocomplete = (campoFiltro.select || campoFiltro.autocomplete);
404
+ if (selectOrAutocomplete.optionText) {
405
+ return selectOrAutocomplete.optionText(itemSelect);
406
+ }
407
+ if (selectOrAutocomplete.camposText) {
408
+ return selectOrAutocomplete.camposText.map(c => itemSelect[c]).join(' ');
409
+ }
410
+ return itemSelect[campoFiltro.campo];
411
+ }
412
+ return '';
413
+ }
414
+ concatenarCadenasArray(array, objData) {
415
+ if (typeof array === 'string') {
416
+ return objData[array];
417
+ }
418
+ const nTxtArray = [];
419
+ array.forEach(campo => {
420
+ if (campo.charAt(0) === '*') {
421
+ nTxtArray.push(campo.replace('*', ''));
422
+ }
423
+ else {
424
+ nTxtArray.push(objData[campo]);
425
+ }
426
+ });
427
+ return nTxtArray.join(' ');
428
+ }
429
+ filtrarData() {
430
+ if (this.frmGroupSeleccionado.invalid) {
431
+ const errors = getFormValidationErrors(this.frmGroupSeleccionado);
432
+ const labels = errors.map(e => {
433
+ const found = this.dataOpcionesNuevo()[this.tabActual()].campos.find(c => c.campo === e.control);
434
+ return found?.label || e.control;
435
+ });
436
+ this.toastr.error(`Campos requeridos:<br>${labels.join(', ')}`, undefined, { enableHtml: true });
437
+ return;
438
+ }
439
+ this.actualizarEstadoService();
440
+ const res = this.getFiltroResultante();
441
+ this.resultados.emit(res.datosFiltro);
442
+ }
443
+ actualizarEnFormArray(name, value, extra) {
444
+ this.opcionesTabs.controls.forEach((control) => {
445
+ const fc = control.get(name);
446
+ if (fc) {
447
+ if (value !== undefined)
448
+ fc.setValue(value, { emitEvent: false });
449
+ if (extra?.disabled === true)
450
+ fc.disable();
451
+ if (extra?.disabled === false)
452
+ fc.enable();
453
+ fc.updateValueAndValidity();
454
+ }
455
+ });
456
+ }
457
+ accionPosteriorCambioAutocomplete(controlData, valControl) {
458
+ const list = this.dataServidorSuscripcion[controlData.autocomplete?.data]?.getValue() || [];
459
+ this.filtrados[controlData.campo] = list.filter((algo) => {
460
+ let nTextVerif = this.concatenarCadenasArray(controlData.autocomplete?.camposText, algo);
461
+ if (controlData.autocomplete?.searchFields) {
462
+ const nTextVerifExtra = this.concatenarCadenasArray(controlData.autocomplete.searchFields, algo);
463
+ nTextVerif = nTextVerif.concat(nTextVerifExtra);
464
+ }
465
+ const textBuscar = valControl && typeof valControl === 'string' ? valControl.toLowerCase() : null;
466
+ if (nTextVerif) {
467
+ return nTextVerif.toLowerCase().includes(textBuscar) ? algo : null;
468
+ }
469
+ return null;
470
+ });
471
+ }
472
+ cambiarNuevo(campo, val) {
473
+ if (campo.autocomplete) {
474
+ const valControl = this.frmGroupSeleccionado.get(campo.campo + this.sufixTemporal)?.value;
475
+ if (!valControl) {
476
+ this.filtrados[campo.campo] = this.dataServidorSuscripcion[campo.autocomplete.data]?.getValue() || [];
477
+ }
478
+ else {
479
+ const config = campo.autocomplete;
480
+ if (config.campotxtBuscar && val && val.length > (config.campotxtBuscarLength || 3)) {
481
+ const reqQuery = config.data;
482
+ let reqData = {};
483
+ if (campo.reqParams?.fields) {
484
+ campo.reqParams.fields.forEach(f => {
485
+ const ctrl = this.buscarControl(f);
486
+ reqData[ctrl?.aliasCampoEnviar || f] = this.frmGroupSeleccionado.get(f)?.value;
487
+ });
488
+ }
489
+ reqData[config.campotxtBuscar || campo.campo] = val;
490
+ if (campo.reqParams?.params)
491
+ Object.assign(reqData, campo.reqParams.params);
492
+ this.inputParaEnviarAutocomplete.next({ reqQuery, reqData, controlData: campo });
493
+ }
494
+ else {
495
+ this.accionPosteriorCambioAutocomplete(campo, valControl);
496
+ }
497
+ }
498
+ }
499
+ }
500
+ cambiarSeleccionNuevo(campo, event) {
501
+ const val = event?.option?.value ?? event?.value ?? (event?.target ? event.target.value : event);
502
+ if (val !== undefined) {
503
+ this.actualizarEnFormArray(campo.campo, val);
504
+ if (campo.autocomplete) {
505
+ const config = campo.autocomplete;
506
+ const list = this.dataServidorSuscripcion[config.data]?.getValue() || [];
507
+ const item = config.campoValor === '*objeto*' ? val : dataEnLista(list, config.campoValor || campo.campo, val);
508
+ if (item) {
509
+ const text = this.campoTextEval(campo, item);
510
+ this.actualizarEnFormArray(campo.campo + this.sufixTemporal, text);
511
+ }
512
+ }
513
+ const groupedMatch = this.dataOpcionesNuevo()[this.tabActual()].campos
514
+ .filter(c => c.controlAgrupado)
515
+ .find(c => c.controlAgrupado?.some(sub => sub.campo === campo.campo));
516
+ if (groupedMatch)
517
+ this.frmGroupSeleccionado.get(groupedMatch.campo)?.setValue(val);
518
+ }
519
+ if (campo.change?.filterFields) {
520
+ campo.change.filterFields.forEach(target => {
521
+ const targetMeta = this.buscarControl(target);
522
+ if (targetMeta) {
523
+ const params = this.generarParams(targetMeta, campo);
524
+ this.actualizarEnFormArray(target, null);
525
+ this.actualizarEnFormArray(target + this.sufixTemporal, null);
526
+ this.dataServidorSuscripcion[target]?.next(null);
527
+ const config = (targetMeta.select || targetMeta.autocomplete);
528
+ if (config?.data) {
529
+ this.queryService?.cargar(this, [config.data], params, false, this.prefijoConsulta()).then(d => {
530
+ if (d) {
531
+ const res = d[config.data];
532
+ this.actualizarEnFormArray(target, targetMeta.value || null);
533
+ this.actualizarEnFormArray(target + this.sufixTemporal, targetMeta.value || null);
534
+ if (!this.dataServidorSuscripcion[config.data]) {
535
+ this.dataServidorSuscripcion[config.data] = new BehaviorSubject(null);
536
+ }
537
+ this.dataServidorSuscripcion[config.data].next(res);
538
+ this.filtrados[target] = res;
539
+ }
540
+ });
541
+ }
542
+ }
543
+ });
544
+ }
545
+ else if (campo.change?.filter) {
546
+ setTimeout(() => this.filtrarData(), 1);
547
+ }
548
+ }
549
+ buscarControl(campo) {
550
+ const rootCampos = this.dataOpcionesNuevo()[this.tabActual()].campos;
551
+ let found = rootCampos.find(c => c.campo === campo);
552
+ if (!found) {
553
+ found = rootCampos.filter(c => c.controlAgrupado).flatMap(c => c.controlAgrupado).find(c => c.campo === campo);
554
+ }
555
+ return found;
556
+ }
557
+ generarParams(meta, trigger) {
558
+ const params = {};
559
+ if (meta.reqParams?.fields) {
560
+ meta.reqParams.fields.forEach(f => {
561
+ const ctrl = this.buscarControl(f);
562
+ params[ctrl?.aliasCampoEnviar || f] = this.frmGroupSeleccionado.get(f)?.value;
563
+ });
564
+ }
565
+ else {
566
+ params[meta.aliasCampoEnviar || trigger.campo || meta.campo] = this.frmGroupSeleccionado.get(trigger.campo || meta.campo)?.value;
567
+ }
568
+ if (meta.reqParams?.params)
569
+ Object.assign(params, meta.reqParams.params);
570
+ return params;
571
+ }
572
+ limpiarAutocomplete(campo, event) {
573
+ this.actualizarEnFormArray(campo.campo, '');
574
+ this.actualizarEnFormArray(campo.campo + this.sufixTemporal, '');
575
+ this.cambiarSeleccionNuevo(campo, { option: { value: '' } });
576
+ event.preventDefault();
577
+ }
578
+ ngOnDestroy() {
579
+ this.destroy$.next();
580
+ this.destroy$.complete();
581
+ }
582
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: FiltroBusquedaComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
583
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: FiltroBusquedaComponent, isStandalone: true, selector: "jvs-filtro-busqueda", inputs: { opciones: { classPropertyName: "opciones", publicName: "opciones", isSignal: true, isRequired: false, transformFunction: null }, nombreColeccionInput: { classPropertyName: "nombreColeccionInput", publicName: "nombreColeccion", isSignal: true, isRequired: false, transformFunction: null }, prefijoConsulta: { classPropertyName: "prefijoConsulta", publicName: "prefijoConsulta", isSignal: true, isRequired: false, transformFunction: null }, busquedaAutomatica: { classPropertyName: "busquedaAutomatica", publicName: "busquedaAutomatica", isSignal: true, isRequired: false, transformFunction: null }, opciones$: { classPropertyName: "opciones$", publicName: "opciones$", isSignal: true, isRequired: false, transformFunction: null }, modificarOpciones$: { classPropertyName: "modificarOpciones$", publicName: "modificarOpciones$", isSignal: true, isRequired: false, transformFunction: null }, defaultTab: { classPropertyName: "defaultTab", publicName: "defaultTab", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dataFiltro: "dataFiltro", resultados: "resultados", cargaCompleta: "cargaCompleta" }, host: { classAttribute: "jvsFiltroBusqueda" }, ngImport: i0, template: "@if (isCargaCompleta()) {\n <div class=\"filtroBusqueda w-full\">\n <div class=\"border-none p-0 flex flex-col\">\n\n @if (dataOpcionesNuevo().length === 1) {\n <div class=\"flex-1 flex items-end max-sm:flex-col flex-wrap gap-2\">\n <ng-container [ngTemplateOutlet]=\"verOpcionesT\"></ng-container>\n </div>\n } @else if (dataOpcionesNuevo().length > 1) {\n <div class=\"flex-1 flex flex-col flex-wrap gap-2 border\">\n <mat-tab-group\n [selectedIndex]=\"tabActual()\"\n (selectedIndexChange)=\"getControlRaiz('opcion').setValue($event)\"\n class=\"flex-1 flex flex-wrap\"\n [mat-stretch-tabs]=\"false\"\n dynamicHeight\n mat-align-tabs=\"start\"\n >\n @for (item of dataOpcionesNuevo(); track $index) {\n <mat-tab [aria-label]=\"(tabActual() === $index) ? 'primary' : ''\">\n <ng-template mat-tab-label>\n @if (tabActual() === $index) {\n <mat-icon class=\"icon-xs\" svgIcon=\"roundVerified\"></mat-icon>\n }\n &nbsp;{{ item.label }}\n </ng-template>\n\n <div class=\"mx-2 mt-0 pt-0 flex flex-col items-end sm:flex-row flex-wrap gap-2\">\n <ng-container [ngTemplateOutlet]=\"verOpcionesT\"></ng-container>\n </div>\n </mat-tab>\n }\n </mat-tab-group>\n </div>\n }\n </div>\n </div>\n}\n\n<ng-template #verOpcionesT>\n @for (campo of dataOpcionesNuevo()[tabActual()]?.campos; track campo.campo) {\n <ng-container [ngTemplateOutletContext]=\"{controlData: campo}\" [ngTemplateOutlet]=\"controlesFormularioNuevo\"></ng-container>\n }\n <ng-container [ngTemplateOutlet]=\"botonFiltrar\"></ng-container>\n</ng-template>\n\n<ng-template #botonFiltrar>\n <button (click)=\"filtrarData()\"\n class=\"flex items-center justify-center bg-primary text-primary-contrast font-bold uppercase text-xs px-2 py-1 rounded shadow-md hover:shadow-lg outline-none focus:outline-none mr-1 mb-1 ease-linear transition-all duration-150\"\n matRipple type=\"button\"\n [disabled]=\"!isCargaCompleta()\"\n >\n <mat-icon class=\"icon-xs\" svgIcon=\"roundFilterAlt\"></mat-icon>&nbsp;\n <span>Filtrar</span>\n </button>\n</ng-template>\n\n<ng-template #controlesFormularioNuevo let-controlData=\"controlData\">\n @switch (controlData.control) {\n @case ('controlAgrupado') {\n <ng-container [ngTemplateOutletContext]=\"{template: inputControlAgrupado, controlData: controlData}\" [ngTemplateOutlet]=\"contenedorInput\"></ng-container>\n }\n @case ('select') {\n <ng-container [ngTemplateOutletContext]=\"{template: inputSelect, controlData: controlData}\" [ngTemplateOutlet]=\"contenedorInput\"></ng-container>\n }\n @case ('autocomplete') {\n <ng-container [ngTemplateOutletContext]=\"{template: inputAutocomplete, controlData: controlData}\" [ngTemplateOutlet]=\"contenedorInput\"></ng-container>\n }\n @case ('date') {\n <ng-container [ngTemplateOutletContext]=\"{template: inputDate, controlData: controlData}\" [ngTemplateOutlet]=\"contenedorInput\"></ng-container>\n }\n @case ('date_range') {\n <ng-container [ngTemplateOutletContext]=\"{template: inputDateRange, controlData: controlData}\" [ngTemplateOutlet]=\"contenedorInput\"></ng-container>\n }\n @case ('checkbox') {\n <ng-container [ngTemplateOutletContext]=\"{template: inputCheckBox, controlData: controlData}\" [ngTemplateOutlet]=\"contenedorInput\"></ng-container>\n }\n @default {\n @if (controlData.control === 'text' || controlData.control === 'number') {\n <ng-container [ngTemplateOutletContext]=\"{template: inputTextNumber, controlData: controlData}\" [ngTemplateOutlet]=\"contenedorInput\"></ng-container>\n }\n }\n }\n</ng-template>\n\n<ng-template #contenedorInput let-template=\"template\" let-controlData=\"controlData\">\n <fieldset [class.flex-auto]=\"!controlData.cssClass\" [class]=\"controlData.cssClass\" class=\"appearance-none contenedorCampo relative\">\n <legend>\n <label [for]=\"controlData.campo\">{{ controlData.label }}@if(controlData.required){<span class=\"text-red-700 font-bold\"> *</span>}</label>\n </legend>\n <ng-container [ngTemplateOutletContext]=\"{controlData: controlData}\" [ngTemplateOutlet]=\"template\"></ng-container>\n </fieldset>\n</ng-template>\n\n<ng-template #inputSelect let-controlData=\"controlData\">\n <select [formControl]=\"getControl(controlData.campo)\"\n (change)=\"cambiarSeleccionNuevo(controlData, $event);\"\n [class]=\"controlData.select?.cssClass?.class\"\n [id]=\"controlData.campo\"\n [required]=\"controlData.required\"\n [class.border-b-red-700]=\"getControl(controlData.campo).invalid\"\n >\n @if (controlData.select?.textoCuandoNulo) {\n <option value=\"\">{{ controlData.select?.textoCuandoNulo }}</option>\n }\n @for (itemSelect of dataServidorSuscripcion[controlData.select?.data!] | async; track $index) {\n <option [class]=\"controlData.select?.cssClass?.option\" [value]=\"campoValorEval(controlData, itemSelect)\">\n {{ campoTextEval(controlData, itemSelect) }}\n </option>\n }\n </select>\n</ng-template>\n\n<ng-template #inputControlAgrupado let-controlData=\"controlData\">\n <div class=\"flex items-center campos-container\">\n @for (sub of controlData.controlAgrupado; track sub.campo) {\n @switch (sub.control) {\n @case ('select') {\n <ng-container [ngTemplateOutletContext]=\"{controlData: sub}\" [ngTemplateOutlet]=\"inputSelect\"></ng-container>\n }\n @case ('autocomplete') {\n <ng-container [ngTemplateOutletContext]=\"{controlData: sub}\" [ngTemplateOutlet]=\"inputAutocomplete\"></ng-container>\n }\n @case ('date') {\n <ng-container [ngTemplateOutletContext]=\"{controlData: sub}\" [ngTemplateOutlet]=\"inputDate\"></ng-container>\n }\n @case ('date_range') {\n <ng-container [ngTemplateOutletContext]=\"{controlData: sub}\" [ngTemplateOutlet]=\"inputDateRange\"></ng-container>\n }\n @case ('checkbox') {\n <ng-container [ngTemplateOutletContext]=\"{controlData: sub}\" [ngTemplateOutlet]=\"inputCheckBox\"></ng-container>\n }\n @default {\n @if (sub.control === 'text' || sub.control === 'number') {\n <ng-container [ngTemplateOutletContext]=\"{controlData: sub}\" [ngTemplateOutlet]=\"inputTextNumber\"></ng-container>\n }\n }\n }\n }\n </div>\n</ng-template>\n\n<ng-template #inputAutocomplete let-controlData=\"controlData\">\n <div class=\"flex items-center formcontrol-container\">\n <input [formControl]=\"getControl(controlData.campo + sufixTemporal)\"\n (input)=\"cambiarNuevo(controlData, $any($event.target).value)\"\n [matAutocomplete]=\"auto\"\n autocomplete=\"off\"\n [id]=\"controlData.campo\"\n placeholder=\"{{ controlData.autocomplete?.textoCuandoNulo ?? controlData.label }}\"\n [required]=\"controlData.required\"\n [class.border-b-red-700]=\"getControl(controlData.campo).invalid\"\n >\n <mat-autocomplete #auto=\"matAutocomplete\"\n (optionSelected)=\"cambiarSeleccionNuevo(controlData, $event)\"\n [panelWidth]=\"'auto'\"\n [displayWith]=\"getAutocompleteLabel.bind(this, controlData)\"\n >\n @for (itemSelect of filtrados[controlData.campo]; track $index) {\n <mat-option [class]=\"controlData.autocomplete?.cssClass?.option\" [value]=\"campoValorEval(controlData, itemSelect)\">\n @if (controlData.autocomplete?.optionInnerHtml) {\n <div [innerHTML]=\"controlData.autocomplete?.optionInnerHtml!(itemSelect)\"></div>\n } @else {\n {{ campoTextEval(controlData, itemSelect) }}\n }\n </mat-option>\n }\n </mat-autocomplete>\n\n <div class=\"flex items-center justify-start\">\n <button (click)=\"limpiarAutocomplete(controlData, $event)\" class=\"boton-circular-gris\"\n matRipple\n type=\"button\"\n >\n <mat-icon [svgIcon]=\"(getControl(controlData.campo).value ? 'roundCancel' : 'roundSearch')\" class=\"icon-2xs\"></mat-icon>\n </button>\n </div>\n </div>\n</ng-template>\n\n<ng-template #inputTextNumber let-controlData=\"controlData\">\n <input (keyup.enter)=\"controlData.keyUpEnter ? filtrarData() : null\"\n [formControl]=\"getControl(controlData.campo)\"\n [type]=\"controlData.control\"\n autocomplete=\"off\"\n [id]=\"controlData.campo\"\n placeholder=\"{{ controlData.label }}\"\n [required]=\"controlData.required\"\n [class.border-b-red-700]=\"getControl(controlData.campo).invalid\"\n >\n</ng-template>\n\n<ng-template #inputDate let-controlData=\"controlData\">\n <div class=\"flex items-center date-container\">\n <input (keyup.enter)=\"controlData.keyUpEnter ? filtrarData() : null\"\n [formControl]=\"getControl(controlData.campo)\"\n (dateChange)=\"cambiarSeleccionNuevo(controlData, $event)\"\n [matDatepicker]=\"i\"\n autocomplete=\"off\"\n [id]=\"controlData.campo\"\n placeholder=\"{{ controlData.label }}\"\n type=\"text\"\n [required]=\"controlData.required\"\n [class.border-b-red-700]=\"getControl(controlData.campo).invalid\"\n >\n <mat-datepicker-toggle [for]=\"i\" class=\"icon-xs\" matSuffix></mat-datepicker-toggle>\n <mat-datepicker #i></mat-datepicker>\n </div>\n</ng-template>\n\n<ng-template #inputDateRange let-controlData=\"controlData\">\n <div class=\"flex items-center daterange-container\">\n <mat-date-range-input [rangePicker]=\"i\">\n <input [formControl]=\"getControl(controlData.dateRange?.campo![0])\" matStartDate placeholder=\"Desde\">\n <input [formControl]=\"getControl(controlData.dateRange?.campo![1])\" matEndDate placeholder=\"Hasta\">\n </mat-date-range-input>\n <mat-datepicker-toggle [for]=\"i\" class=\"icon-xs\"></mat-datepicker-toggle>\n <mat-date-range-picker #i></mat-date-range-picker>\n </div>\n</ng-template>\n\n<ng-template #inputCheckBox let-controlData=\"controlData\">\n <input [formControl]=\"getControl(controlData.campo)\"\n [id]=\"controlData.campo\"\n [required]=\"controlData.required\"\n [class.border-b-red-700]=\"getControl(controlData.campo).invalid\"\n type=\"checkbox\"\n (change)=\"cambiarSeleccionNuevo(controlData, $event)\"\n >\n</ng-template>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2.CheckboxRequiredValidator, selector: "input[type=checkbox][required][formControlName],input[type=checkbox][required][formControl],input[type=checkbox][required][ngModel]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatAutocompleteModule }, { kind: "component", type: i3.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "component", type: i3.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i3.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i4.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i4.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i4.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "component", type: i4.MatDateRangeInput, selector: "mat-date-range-input", inputs: ["rangePicker", "required", "dateFilter", "min", "max", "disabled", "separator", "comparisonStart", "comparisonEnd"], exportAs: ["matDateRangeInput"] }, { kind: "directive", type: i4.MatStartDate, selector: "input[matStartDate]", outputs: ["dateChange", "dateInput"] }, { kind: "directive", type: i4.MatEndDate, selector: "input[matEndDate]", outputs: ["dateChange", "dateInput"] }, { kind: "component", type: i4.MatDateRangePicker, selector: "mat-date-range-picker", exportAs: ["matDateRangePicker"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "directive", type: i5.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: MatOptionModule }, { kind: "ngmodule", type: MatRadioModule }, { kind: "ngmodule", type: MatRippleModule }, { kind: "directive", type: i7.MatRipple, selector: "[mat-ripple], [matRipple]", inputs: ["matRippleColor", "matRippleUnbounded", "matRippleCentered", "matRippleRadius", "matRippleAnimation", "matRippleDisabled", "matRippleTrigger"], exportAs: ["matRipple"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "ngmodule", type: MatTabsModule }, { kind: "directive", type: i8.MatTabLabel, selector: "[mat-tab-label], [matTabLabel]" }, { kind: "component", type: i8.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i8.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: TextFieldModule }] });
584
+ }
585
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: FiltroBusquedaComponent, decorators: [{
586
+ type: Component,
587
+ args: [{ selector: 'jvs-filtro-busqueda', standalone: true, imports: [
588
+ CommonModule,
589
+ FormsModule,
590
+ ReactiveFormsModule,
591
+ MatAutocompleteModule,
592
+ MatCheckboxModule,
593
+ MatDatepickerModule,
594
+ MatFormFieldModule,
595
+ MatIconModule,
596
+ MatInputModule,
597
+ MatOptionModule,
598
+ MatRadioModule,
599
+ MatRippleModule,
600
+ MatSelectModule,
601
+ MatTabsModule,
602
+ TextFieldModule,
603
+ ], host: {
604
+ class: 'jvsFiltroBusqueda',
605
+ }, template: "@if (isCargaCompleta()) {\n <div class=\"filtroBusqueda w-full\">\n <div class=\"border-none p-0 flex flex-col\">\n\n @if (dataOpcionesNuevo().length === 1) {\n <div class=\"flex-1 flex items-end max-sm:flex-col flex-wrap gap-2\">\n <ng-container [ngTemplateOutlet]=\"verOpcionesT\"></ng-container>\n </div>\n } @else if (dataOpcionesNuevo().length > 1) {\n <div class=\"flex-1 flex flex-col flex-wrap gap-2 border\">\n <mat-tab-group\n [selectedIndex]=\"tabActual()\"\n (selectedIndexChange)=\"getControlRaiz('opcion').setValue($event)\"\n class=\"flex-1 flex flex-wrap\"\n [mat-stretch-tabs]=\"false\"\n dynamicHeight\n mat-align-tabs=\"start\"\n >\n @for (item of dataOpcionesNuevo(); track $index) {\n <mat-tab [aria-label]=\"(tabActual() === $index) ? 'primary' : ''\">\n <ng-template mat-tab-label>\n @if (tabActual() === $index) {\n <mat-icon class=\"icon-xs\" svgIcon=\"roundVerified\"></mat-icon>\n }\n &nbsp;{{ item.label }}\n </ng-template>\n\n <div class=\"mx-2 mt-0 pt-0 flex flex-col items-end sm:flex-row flex-wrap gap-2\">\n <ng-container [ngTemplateOutlet]=\"verOpcionesT\"></ng-container>\n </div>\n </mat-tab>\n }\n </mat-tab-group>\n </div>\n }\n </div>\n </div>\n}\n\n<ng-template #verOpcionesT>\n @for (campo of dataOpcionesNuevo()[tabActual()]?.campos; track campo.campo) {\n <ng-container [ngTemplateOutletContext]=\"{controlData: campo}\" [ngTemplateOutlet]=\"controlesFormularioNuevo\"></ng-container>\n }\n <ng-container [ngTemplateOutlet]=\"botonFiltrar\"></ng-container>\n</ng-template>\n\n<ng-template #botonFiltrar>\n <button (click)=\"filtrarData()\"\n class=\"flex items-center justify-center bg-primary text-primary-contrast font-bold uppercase text-xs px-2 py-1 rounded shadow-md hover:shadow-lg outline-none focus:outline-none mr-1 mb-1 ease-linear transition-all duration-150\"\n matRipple type=\"button\"\n [disabled]=\"!isCargaCompleta()\"\n >\n <mat-icon class=\"icon-xs\" svgIcon=\"roundFilterAlt\"></mat-icon>&nbsp;\n <span>Filtrar</span>\n </button>\n</ng-template>\n\n<ng-template #controlesFormularioNuevo let-controlData=\"controlData\">\n @switch (controlData.control) {\n @case ('controlAgrupado') {\n <ng-container [ngTemplateOutletContext]=\"{template: inputControlAgrupado, controlData: controlData}\" [ngTemplateOutlet]=\"contenedorInput\"></ng-container>\n }\n @case ('select') {\n <ng-container [ngTemplateOutletContext]=\"{template: inputSelect, controlData: controlData}\" [ngTemplateOutlet]=\"contenedorInput\"></ng-container>\n }\n @case ('autocomplete') {\n <ng-container [ngTemplateOutletContext]=\"{template: inputAutocomplete, controlData: controlData}\" [ngTemplateOutlet]=\"contenedorInput\"></ng-container>\n }\n @case ('date') {\n <ng-container [ngTemplateOutletContext]=\"{template: inputDate, controlData: controlData}\" [ngTemplateOutlet]=\"contenedorInput\"></ng-container>\n }\n @case ('date_range') {\n <ng-container [ngTemplateOutletContext]=\"{template: inputDateRange, controlData: controlData}\" [ngTemplateOutlet]=\"contenedorInput\"></ng-container>\n }\n @case ('checkbox') {\n <ng-container [ngTemplateOutletContext]=\"{template: inputCheckBox, controlData: controlData}\" [ngTemplateOutlet]=\"contenedorInput\"></ng-container>\n }\n @default {\n @if (controlData.control === 'text' || controlData.control === 'number') {\n <ng-container [ngTemplateOutletContext]=\"{template: inputTextNumber, controlData: controlData}\" [ngTemplateOutlet]=\"contenedorInput\"></ng-container>\n }\n }\n }\n</ng-template>\n\n<ng-template #contenedorInput let-template=\"template\" let-controlData=\"controlData\">\n <fieldset [class.flex-auto]=\"!controlData.cssClass\" [class]=\"controlData.cssClass\" class=\"appearance-none contenedorCampo relative\">\n <legend>\n <label [for]=\"controlData.campo\">{{ controlData.label }}@if(controlData.required){<span class=\"text-red-700 font-bold\"> *</span>}</label>\n </legend>\n <ng-container [ngTemplateOutletContext]=\"{controlData: controlData}\" [ngTemplateOutlet]=\"template\"></ng-container>\n </fieldset>\n</ng-template>\n\n<ng-template #inputSelect let-controlData=\"controlData\">\n <select [formControl]=\"getControl(controlData.campo)\"\n (change)=\"cambiarSeleccionNuevo(controlData, $event);\"\n [class]=\"controlData.select?.cssClass?.class\"\n [id]=\"controlData.campo\"\n [required]=\"controlData.required\"\n [class.border-b-red-700]=\"getControl(controlData.campo).invalid\"\n >\n @if (controlData.select?.textoCuandoNulo) {\n <option value=\"\">{{ controlData.select?.textoCuandoNulo }}</option>\n }\n @for (itemSelect of dataServidorSuscripcion[controlData.select?.data!] | async; track $index) {\n <option [class]=\"controlData.select?.cssClass?.option\" [value]=\"campoValorEval(controlData, itemSelect)\">\n {{ campoTextEval(controlData, itemSelect) }}\n </option>\n }\n </select>\n</ng-template>\n\n<ng-template #inputControlAgrupado let-controlData=\"controlData\">\n <div class=\"flex items-center campos-container\">\n @for (sub of controlData.controlAgrupado; track sub.campo) {\n @switch (sub.control) {\n @case ('select') {\n <ng-container [ngTemplateOutletContext]=\"{controlData: sub}\" [ngTemplateOutlet]=\"inputSelect\"></ng-container>\n }\n @case ('autocomplete') {\n <ng-container [ngTemplateOutletContext]=\"{controlData: sub}\" [ngTemplateOutlet]=\"inputAutocomplete\"></ng-container>\n }\n @case ('date') {\n <ng-container [ngTemplateOutletContext]=\"{controlData: sub}\" [ngTemplateOutlet]=\"inputDate\"></ng-container>\n }\n @case ('date_range') {\n <ng-container [ngTemplateOutletContext]=\"{controlData: sub}\" [ngTemplateOutlet]=\"inputDateRange\"></ng-container>\n }\n @case ('checkbox') {\n <ng-container [ngTemplateOutletContext]=\"{controlData: sub}\" [ngTemplateOutlet]=\"inputCheckBox\"></ng-container>\n }\n @default {\n @if (sub.control === 'text' || sub.control === 'number') {\n <ng-container [ngTemplateOutletContext]=\"{controlData: sub}\" [ngTemplateOutlet]=\"inputTextNumber\"></ng-container>\n }\n }\n }\n }\n </div>\n</ng-template>\n\n<ng-template #inputAutocomplete let-controlData=\"controlData\">\n <div class=\"flex items-center formcontrol-container\">\n <input [formControl]=\"getControl(controlData.campo + sufixTemporal)\"\n (input)=\"cambiarNuevo(controlData, $any($event.target).value)\"\n [matAutocomplete]=\"auto\"\n autocomplete=\"off\"\n [id]=\"controlData.campo\"\n placeholder=\"{{ controlData.autocomplete?.textoCuandoNulo ?? controlData.label }}\"\n [required]=\"controlData.required\"\n [class.border-b-red-700]=\"getControl(controlData.campo).invalid\"\n >\n <mat-autocomplete #auto=\"matAutocomplete\"\n (optionSelected)=\"cambiarSeleccionNuevo(controlData, $event)\"\n [panelWidth]=\"'auto'\"\n [displayWith]=\"getAutocompleteLabel.bind(this, controlData)\"\n >\n @for (itemSelect of filtrados[controlData.campo]; track $index) {\n <mat-option [class]=\"controlData.autocomplete?.cssClass?.option\" [value]=\"campoValorEval(controlData, itemSelect)\">\n @if (controlData.autocomplete?.optionInnerHtml) {\n <div [innerHTML]=\"controlData.autocomplete?.optionInnerHtml!(itemSelect)\"></div>\n } @else {\n {{ campoTextEval(controlData, itemSelect) }}\n }\n </mat-option>\n }\n </mat-autocomplete>\n\n <div class=\"flex items-center justify-start\">\n <button (click)=\"limpiarAutocomplete(controlData, $event)\" class=\"boton-circular-gris\"\n matRipple\n type=\"button\"\n >\n <mat-icon [svgIcon]=\"(getControl(controlData.campo).value ? 'roundCancel' : 'roundSearch')\" class=\"icon-2xs\"></mat-icon>\n </button>\n </div>\n </div>\n</ng-template>\n\n<ng-template #inputTextNumber let-controlData=\"controlData\">\n <input (keyup.enter)=\"controlData.keyUpEnter ? filtrarData() : null\"\n [formControl]=\"getControl(controlData.campo)\"\n [type]=\"controlData.control\"\n autocomplete=\"off\"\n [id]=\"controlData.campo\"\n placeholder=\"{{ controlData.label }}\"\n [required]=\"controlData.required\"\n [class.border-b-red-700]=\"getControl(controlData.campo).invalid\"\n >\n</ng-template>\n\n<ng-template #inputDate let-controlData=\"controlData\">\n <div class=\"flex items-center date-container\">\n <input (keyup.enter)=\"controlData.keyUpEnter ? filtrarData() : null\"\n [formControl]=\"getControl(controlData.campo)\"\n (dateChange)=\"cambiarSeleccionNuevo(controlData, $event)\"\n [matDatepicker]=\"i\"\n autocomplete=\"off\"\n [id]=\"controlData.campo\"\n placeholder=\"{{ controlData.label }}\"\n type=\"text\"\n [required]=\"controlData.required\"\n [class.border-b-red-700]=\"getControl(controlData.campo).invalid\"\n >\n <mat-datepicker-toggle [for]=\"i\" class=\"icon-xs\" matSuffix></mat-datepicker-toggle>\n <mat-datepicker #i></mat-datepicker>\n </div>\n</ng-template>\n\n<ng-template #inputDateRange let-controlData=\"controlData\">\n <div class=\"flex items-center daterange-container\">\n <mat-date-range-input [rangePicker]=\"i\">\n <input [formControl]=\"getControl(controlData.dateRange?.campo![0])\" matStartDate placeholder=\"Desde\">\n <input [formControl]=\"getControl(controlData.dateRange?.campo![1])\" matEndDate placeholder=\"Hasta\">\n </mat-date-range-input>\n <mat-datepicker-toggle [for]=\"i\" class=\"icon-xs\"></mat-datepicker-toggle>\n <mat-date-range-picker #i></mat-date-range-picker>\n </div>\n</ng-template>\n\n<ng-template #inputCheckBox let-controlData=\"controlData\">\n <input [formControl]=\"getControl(controlData.campo)\"\n [id]=\"controlData.campo\"\n [required]=\"controlData.required\"\n [class.border-b-red-700]=\"getControl(controlData.campo).invalid\"\n type=\"checkbox\"\n (change)=\"cambiarSeleccionNuevo(controlData, $event)\"\n >\n</ng-template>\n" }]
606
+ }], ctorParameters: () => [] });
607
+
608
+ /**
609
+ * Generated bundle index. Do not edit.
610
+ */
611
+
612
+ export { FiltroBusquedaComponent, FiltroBusquedaService, QUERY_SERVICE_TOKEN };
613
+ //# sourceMappingURL=jvsoft-components-filtro-busqueda.mjs.map