@mediusinc/mng-commons 7.4.0-rc.0 → 7.4.0
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.
- package/dev-scripts/version-info.js +18 -19
- package/fesm2022/mediusinc-mng-commons-core.mjs +69 -6
- package/fesm2022/mediusinc-mng-commons-core.mjs.map +1 -1
- package/fesm2022/mediusinc-mng-commons-filter.mjs +9 -3
- package/fesm2022/mediusinc-mng-commons-filter.mjs.map +1 -1
- package/fesm2022/mediusinc-mng-commons-form.mjs +287 -230
- package/fesm2022/mediusinc-mng-commons-form.mjs.map +1 -1
- package/fesm2022/{mediusinc-mng-commons-table-column-toggle.component-D7fm83ug.mjs → mediusinc-mng-commons-table-column-toggle.component-BS5xvoDR.mjs} +2 -2
- package/fesm2022/{mediusinc-mng-commons-table-column-toggle.component-D7fm83ug.mjs.map → mediusinc-mng-commons-table-column-toggle.component-BS5xvoDR.mjs.map} +1 -1
- package/fesm2022/{mediusinc-mng-commons-table-mediusinc-mng-commons-table-Czmm5fLT.mjs → mediusinc-mng-commons-table-mediusinc-mng-commons-table-BfEYZG7s.mjs} +279 -117
- package/fesm2022/mediusinc-mng-commons-table-mediusinc-mng-commons-table-BfEYZG7s.mjs.map +1 -0
- package/fesm2022/mediusinc-mng-commons-table.mjs +1 -1
- package/fesm2022/mediusinc-mng-commons-tableview-api.mjs +42 -13
- package/fesm2022/mediusinc-mng-commons-tableview-api.mjs.map +1 -1
- package/fesm2022/mediusinc-mng-commons-tableview.mjs +40 -19
- package/fesm2022/mediusinc-mng-commons-tableview.mjs.map +1 -1
- package/i18n/en.json +5 -2
- package/i18n/sl.json +5 -1
- package/package.json +1 -1
- package/types/mediusinc-mng-commons-core.d.ts +2 -1
- package/types/mediusinc-mng-commons-filter.d.ts +6 -3
- package/types/mediusinc-mng-commons-form.d.ts +49 -77
- package/types/mediusinc-mng-commons-table-api.d.ts +12 -2
- package/types/mediusinc-mng-commons-table.d.ts +13 -5
- package/types/mediusinc-mng-commons-tableview-api.d.ts +47 -8
- package/types/mediusinc-mng-commons-tableview.d.ts +8 -2
- package/fesm2022/mediusinc-mng-commons-table-mediusinc-mng-commons-table-Czmm5fLT.mjs.map +0 -1
- package/version-info.json +0 -11
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NgTemplateOutlet } from '@angular/common';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
|
-
import { InjectionToken, inject, Injectable, forwardRef, Injector, DestroyRef, input, booleanAttribute, output, viewChild, signal, computed, ChangeDetectionStrategy, ViewEncapsulation, Component, numberAttribute, ChangeDetectorRef, effect, ElementRef, Renderer2,
|
|
3
|
+
import { InjectionToken, inject, Injectable, forwardRef, Injector, DestroyRef, input, booleanAttribute, output, viewChild, signal, computed, afterNextRender, ChangeDetectionStrategy, ViewEncapsulation, Component, numberAttribute, ChangeDetectorRef, effect, ElementRef, Renderer2, Directive } from '@angular/core';
|
|
4
4
|
import { takeUntilDestroyed, toObservable as toObservable$1 } from '@angular/core/rxjs-interop';
|
|
5
5
|
import * as i1$1 from '@angular/forms';
|
|
6
6
|
import { NG_VALUE_ACCESSOR, FormsModule, NG_VALIDATORS, FormBuilder, Validators, ReactiveFormsModule, NgControl } from '@angular/forms';
|
|
@@ -8,9 +8,10 @@ import { TranslateService, TranslatePipe } from '@ngx-translate/core';
|
|
|
8
8
|
import { AutoComplete } from 'primeng/autocomplete';
|
|
9
9
|
import { InputGroup } from 'primeng/inputgroup';
|
|
10
10
|
import { InputGroupAddon } from 'primeng/inputgroupaddon';
|
|
11
|
-
import {
|
|
11
|
+
import { Tag } from 'primeng/tag';
|
|
12
|
+
import { of, tap, merge, ReplaySubject, take, Subject, distinctUntilChanged, debounceTime, combineLatest, switchMap, map as map$1 } from 'rxjs';
|
|
12
13
|
import { map } from 'rxjs/operators';
|
|
13
|
-
import { FilterMatchMode, toObservable, LoggerService,
|
|
14
|
+
import { FilterMatchMode, toObservable, LoggerService, effectWithDeps, CommonsInternalError, fromSubscribeError, getErrorLogLevel, RerenderDirective, booleanWithDefaultAttribute, narrowI18nToTranslation, TemplateDirective, CommonsFeatureTypeEnum } from '@mediusinc/mng-commons/core';
|
|
14
15
|
import { Divider } from 'primeng/divider';
|
|
15
16
|
import { DatePicker } from 'primeng/datepicker';
|
|
16
17
|
import * as i1 from 'primeng/inputmask';
|
|
@@ -136,25 +137,69 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
136
137
|
args: [{ providedIn: 'root' }]
|
|
137
138
|
}] });
|
|
138
139
|
|
|
140
|
+
function createAutocompleteItem(item, opts) {
|
|
141
|
+
// If item is already an AutocompleteItem, return it as-is to prevent double wrapping
|
|
142
|
+
if (item != null && typeof item === 'object' && '__original' in item && '__value' in item) {
|
|
143
|
+
return item;
|
|
144
|
+
}
|
|
145
|
+
const valueProp = opts?.optionsValueProperty;
|
|
146
|
+
const labelProp = opts?.optionsLabelProperty;
|
|
147
|
+
const trackProp = opts?.optionsTrackProperty;
|
|
148
|
+
const isTranslate = opts?.optionsLabelTranslate;
|
|
149
|
+
const acValue = valueProp != null && item[valueProp] != null ? item[valueProp] : item;
|
|
150
|
+
const labelFromItem = ((labelProp != null && item[labelProp] != null ? item[labelProp] : item) ?? '').toString();
|
|
151
|
+
const trackValue = trackProp ? (item[trackProp] ?? acValue) : acValue;
|
|
152
|
+
return {
|
|
153
|
+
__original: item,
|
|
154
|
+
__track: typeof trackValue === 'object' ? trackValue : trackValue?.toString(),
|
|
155
|
+
__value: acValue,
|
|
156
|
+
__label: isTranslate && opts?.translate ? opts.translate.instant(labelFromItem) : labelFromItem,
|
|
157
|
+
__labelI18nKey: isTranslate ? labelFromItem : undefined
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
139
161
|
const AUTOCOMPLETE_VALUE_ACCESSOR = {
|
|
140
162
|
provide: NG_VALUE_ACCESSOR,
|
|
141
163
|
useExisting: forwardRef(() => AutocompleteComponent),
|
|
142
164
|
multi: true
|
|
143
165
|
};
|
|
144
166
|
class AutocompleteComponent {
|
|
167
|
+
#injector;
|
|
168
|
+
#destroyRef;
|
|
169
|
+
#translate;
|
|
170
|
+
#labelLookupService;
|
|
171
|
+
#logger;
|
|
172
|
+
#isInited;
|
|
173
|
+
#searchSubscription;
|
|
174
|
+
#dataProviderService;
|
|
175
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
176
|
+
#onChangeFn;
|
|
177
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
178
|
+
#onTouchedFn;
|
|
179
|
+
#value;
|
|
180
|
+
#valueItem;
|
|
181
|
+
#disabledWritable;
|
|
182
|
+
#isPanelShown;
|
|
183
|
+
#isFocused;
|
|
184
|
+
#userSelectedItem;
|
|
185
|
+
#queryResultCacheSubject;
|
|
186
|
+
#currentQuery;
|
|
145
187
|
get value() {
|
|
146
|
-
return this
|
|
188
|
+
return this.#value;
|
|
189
|
+
}
|
|
190
|
+
get valueAsItem() {
|
|
191
|
+
return this.#valueItem;
|
|
147
192
|
}
|
|
148
193
|
constructor() {
|
|
149
|
-
this
|
|
150
|
-
this
|
|
151
|
-
this
|
|
152
|
-
this
|
|
153
|
-
this
|
|
194
|
+
this.#injector = inject(Injector);
|
|
195
|
+
this.#destroyRef = inject(DestroyRef);
|
|
196
|
+
this.#translate = inject(TranslateService);
|
|
197
|
+
this.#labelLookupService = inject(LookupLabelResolutionService);
|
|
198
|
+
this.#logger = inject(LoggerService).create('AutocompleteComponent');
|
|
154
199
|
this.dataProvider = input.required(...(ngDevMode ? [{ debugName: "dataProvider" }] : []));
|
|
155
200
|
this.optionsTrackProperty = input(...(ngDevMode ? [undefined, { debugName: "optionsTrackProperty" }] : []));
|
|
156
|
-
this.
|
|
157
|
-
this.
|
|
201
|
+
this.optionsValueProperty = input(undefined, ...(ngDevMode ? [{ debugName: "optionsValueProperty" }] : []));
|
|
202
|
+
this.optionsLabelProperty = input(undefined, ...(ngDevMode ? [{ debugName: "optionsLabelProperty" }] : []));
|
|
158
203
|
this.optionsLabelTranslate = input(false, { ...(ngDevMode ? { debugName: "optionsLabelTranslate" } : {}), transform: booleanAttribute });
|
|
159
204
|
this.inlineSearch = input(false, { ...(ngDevMode ? { debugName: "inlineSearch" } : {}), transform: booleanAttribute });
|
|
160
205
|
this.openOnFocus = input(false, { ...(ngDevMode ? { debugName: "openOnFocus" } : {}), transform: booleanAttribute });
|
|
@@ -165,6 +210,7 @@ class AutocompleteComponent {
|
|
|
165
210
|
this.showClear = input(false, { ...(ngDevMode ? { debugName: "showClear" } : {}), transform: booleanAttribute });
|
|
166
211
|
this.autoClear = input(false, { ...(ngDevMode ? { debugName: "autoClear" } : {}), transform: booleanAttribute });
|
|
167
212
|
this.selectFirst = input(false, { ...(ngDevMode ? { debugName: "selectFirst" } : {}), transform: booleanAttribute }); //on every input field change return first given value (or null)
|
|
213
|
+
this.allowInput = input(false, { ...(ngDevMode ? { debugName: "allowInput" } : {}), transform: booleanAttribute });
|
|
168
214
|
this.searchTrim = input(undefined, ...(ngDevMode ? [{ debugName: "searchTrim" }] : []));
|
|
169
215
|
this.disabledInput = input(false, { ...(ngDevMode ? { debugName: "disabledInput" } : {}), transform: booleanAttribute, alias: 'disabled' });
|
|
170
216
|
this.templates = input([], ...(ngDevMode ? [{ debugName: "templates" }] : []));
|
|
@@ -172,69 +218,49 @@ class AutocompleteComponent {
|
|
|
172
218
|
// eslint-disable-next-line @angular-eslint/no-output-native
|
|
173
219
|
this.blur = output();
|
|
174
220
|
this.primeAutocomplete = viewChild(AutoComplete, ...(ngDevMode ? [{ debugName: "primeAutocomplete" }] : []));
|
|
175
|
-
this
|
|
176
|
-
this
|
|
177
|
-
this
|
|
221
|
+
this.#isInited = false;
|
|
222
|
+
this.#searchSubscription = null;
|
|
223
|
+
this.#dataProviderService = null;
|
|
178
224
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
179
|
-
this
|
|
225
|
+
this.#onChangeFn = () => { };
|
|
180
226
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
181
|
-
this
|
|
227
|
+
this.#onTouchedFn = () => { };
|
|
182
228
|
this.ngModelValue = signal(undefined, ...(ngDevMode ? [{ debugName: "ngModelValue" }] : []));
|
|
183
|
-
this
|
|
184
|
-
this.disabled = computed(() => this
|
|
229
|
+
this.#disabledWritable = signal(false, ...(ngDevMode ? [{ debugName: "#disabledWritable" }] : []));
|
|
230
|
+
this.disabled = computed(() => this.#disabledWritable() || this.disabledInput(), ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
185
231
|
this.suggestions = signal([], ...(ngDevMode ? [{ debugName: "suggestions" }] : []));
|
|
186
|
-
this
|
|
187
|
-
this
|
|
232
|
+
this.#isPanelShown = false;
|
|
233
|
+
this.#isFocused = false;
|
|
188
234
|
this.prependTemplates = computed(() => this.templates().filter(t => t.name() === 'prepend'), ...(ngDevMode ? [{ debugName: "prependTemplates" }] : []));
|
|
189
235
|
this.appendTemplates = computed(() => this.templates().filter(t => t.name() === 'append'), ...(ngDevMode ? [{ debugName: "appendTemplates" }] : []));
|
|
190
|
-
this.optionsLabelProperty = computed(() => {
|
|
191
|
-
if (this.optionsLabelTranslate()) {
|
|
192
|
-
// setup translation properties
|
|
193
|
-
if (this.optionsLabelPropertyInit()) {
|
|
194
|
-
return `${this.optionsLabelPropertyInit()}_i18n`;
|
|
195
|
-
}
|
|
196
|
-
else if (!this.optionsLabelPropertyInit() && !this.optionsValuePropertyInit()) {
|
|
197
|
-
return 'title_i18n';
|
|
198
|
-
}
|
|
199
|
-
else {
|
|
200
|
-
throw new CommonsInternalError(`Invalid use with value (${this.optionsValuePropertyInit()}) and label (${this.optionsLabelPropertyInit()}) property setup.`, {
|
|
201
|
-
name: 'AutocompleteComponentError'
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
return this.optionsLabelPropertyInit();
|
|
206
|
-
}, ...(ngDevMode ? [{ debugName: "optionsLabelProperty" }] : []));
|
|
207
|
-
this.optionsValueProperty = computed(() => {
|
|
208
|
-
if (this.optionsLabelTranslate()) {
|
|
209
|
-
// setup translation properties
|
|
210
|
-
if (!this.optionsLabelPropertyInit() && !this.optionsValuePropertyInit()) {
|
|
211
|
-
return 'value';
|
|
212
|
-
}
|
|
213
|
-
else if (!this.optionsLabelPropertyInit()) {
|
|
214
|
-
throw new CommonsInternalError(`Invalid use with value (${this.optionsValuePropertyInit()}) and label (${this.optionsLabelPropertyInit()}) property setup.`, {
|
|
215
|
-
name: 'AutocompleteComponentError'
|
|
216
|
-
});
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
return this.optionsValuePropertyInit();
|
|
220
|
-
}, ...(ngDevMode ? [{ debugName: "optionsValueProperty" }] : []));
|
|
221
236
|
effectWithDeps([this.ngModelValue, this.primeAutocomplete, this.multiselect], ([ngModelValue, primeAutocomplete, multiselect]) => {
|
|
222
|
-
|
|
223
|
-
this
|
|
224
|
-
this._rawValue = ngModelValue;
|
|
237
|
+
this.#value = this.#getValueFromItem(ngModelValue);
|
|
238
|
+
this.#valueItem = ngModelValue;
|
|
225
239
|
// sync to autcomplete only if all is ready
|
|
226
240
|
if (primeAutocomplete != null &&
|
|
227
241
|
multiselect === primeAutocomplete?.multiple &&
|
|
228
|
-
(this
|
|
229
|
-
primeAutocomplete?.updateModel(this
|
|
242
|
+
(this.#valueItem == null || (multiselect && Array.isArray(this.#valueItem)) || (!multiselect && !Array.isArray(this.#valueItem)))) {
|
|
243
|
+
primeAutocomplete?.updateModel(this.#valueItem);
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
effectWithDeps([this.optionsLabelTranslate, this.optionsLabelProperty, this.optionsValueProperty], ([isLabelTranslate, labelProp, valueProp]) => {
|
|
247
|
+
if (isLabelTranslate && labelProp == null && valueProp) {
|
|
248
|
+
throw new CommonsInternalError(`Invalid use with value (${valueProp}) and label (${labelProp}) property setup.`, {
|
|
249
|
+
name: 'AutocompleteComponentError'
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
merge([this.#translate.onTranslationChange, this.#translate.onLangChange])
|
|
254
|
+
.pipe(takeUntilDestroyed())
|
|
255
|
+
.subscribe(() => {
|
|
256
|
+
this.suggestions.update(items => items.map(item => this.#createAutocompleteItem(item.__original)));
|
|
257
|
+
});
|
|
258
|
+
afterNextRender(() => {
|
|
259
|
+
this.#setItemsAndDataProvider();
|
|
260
|
+
if (this.selectFirst() && !this.#value) {
|
|
261
|
+
this.onSearch(undefined, true);
|
|
230
262
|
}
|
|
231
263
|
});
|
|
232
|
-
}
|
|
233
|
-
ngOnInit() {
|
|
234
|
-
this.setItemsAndDataProvider();
|
|
235
|
-
if (this.selectFirst() && !this._value) {
|
|
236
|
-
this.onSearch(undefined, true);
|
|
237
|
-
}
|
|
238
264
|
}
|
|
239
265
|
onSearch(event, isInit = false) {
|
|
240
266
|
// openOnFocus enables this method to be called when input is focused. The dropdown button calls this method and puts the focus on the input field, which causes 2 calls.
|
|
@@ -243,11 +269,11 @@ class AutocompleteComponent {
|
|
|
243
269
|
return;
|
|
244
270
|
// cancel any existing requests
|
|
245
271
|
if (!this.inlineSearch()) {
|
|
246
|
-
this
|
|
272
|
+
this.#searchSubscription?.unsubscribe();
|
|
247
273
|
}
|
|
248
274
|
const optionsLabelProperty = this.optionsLabelProperty();
|
|
249
|
-
const query = this
|
|
250
|
-
this
|
|
275
|
+
const query = this.#trimSearchQuery(event?.query);
|
|
276
|
+
this.#currentQuery = query;
|
|
251
277
|
const params = {
|
|
252
278
|
limit: 50
|
|
253
279
|
};
|
|
@@ -262,159 +288,154 @@ class AutocompleteComponent {
|
|
|
262
288
|
}
|
|
263
289
|
};
|
|
264
290
|
}
|
|
265
|
-
if (!this
|
|
266
|
-
if (!this
|
|
267
|
-
this
|
|
291
|
+
if (!this.#queryResultCacheSubject || !this.inlineSearch()) {
|
|
292
|
+
if (!this.#queryResultCacheSubject) {
|
|
293
|
+
this.#queryResultCacheSubject = new ReplaySubject(1);
|
|
268
294
|
}
|
|
269
|
-
this
|
|
270
|
-
.pipe(takeUntilDestroyed(this
|
|
295
|
+
this.#searchSubscription = this.#getLookup(params, query)
|
|
296
|
+
.pipe(takeUntilDestroyed(this.#destroyRef))
|
|
271
297
|
.subscribe({
|
|
272
298
|
next: items => {
|
|
273
|
-
this
|
|
299
|
+
this.#queryResultCacheSubject?.next(items);
|
|
274
300
|
const optionsValueProperty = this.optionsValueProperty();
|
|
275
301
|
const dataProvider = this.dataProvider();
|
|
276
302
|
if (dataProvider && optionsValueProperty) {
|
|
277
|
-
items.forEach(item => this
|
|
303
|
+
items.forEach(item => this.#labelLookupService.storeEntry(dataProvider, optionsValueProperty, item[optionsValueProperty], item));
|
|
278
304
|
}
|
|
279
|
-
this
|
|
280
|
-
if (isInit && !this
|
|
281
|
-
this
|
|
305
|
+
this.#setSuggestionsFromLookupItems(items, query);
|
|
306
|
+
if (isInit && !this.#value) {
|
|
307
|
+
this.#selectFirstItem();
|
|
282
308
|
}
|
|
283
309
|
},
|
|
284
310
|
error: err => {
|
|
285
|
-
this
|
|
311
|
+
this.#setSuggestionsFromLookupItems([], query);
|
|
286
312
|
const error = fromSubscribeError(err, 'AutocompleteComponentError', {
|
|
287
313
|
search: query,
|
|
288
314
|
params: params
|
|
289
315
|
});
|
|
290
|
-
this
|
|
316
|
+
this.#logger.log(error, getErrorLogLevel(error));
|
|
291
317
|
}
|
|
292
318
|
});
|
|
293
319
|
}
|
|
294
|
-
else if (this
|
|
295
|
-
this
|
|
296
|
-
this
|
|
320
|
+
else if (this.#queryResultCacheSubject) {
|
|
321
|
+
this.#searchSubscription = this.#queryResultCacheSubject.pipe(take(1)).subscribe(result => {
|
|
322
|
+
this.#setSuggestionsFromLookupItems(result, query);
|
|
297
323
|
});
|
|
298
324
|
}
|
|
299
325
|
}
|
|
300
|
-
selectFirstItem() {
|
|
301
|
-
if (!this.selectFirst() || this.multiselect())
|
|
302
|
-
return;
|
|
303
|
-
const suggestions = this.suggestions();
|
|
304
|
-
if (suggestions.length > 0 && !this.userSelectedItem) {
|
|
305
|
-
this.setValue(suggestions[0]);
|
|
306
|
-
}
|
|
307
|
-
else if (!this.userSelectedItem) {
|
|
308
|
-
// handles the case if the user provides an input and de-focuses the input field before suggestions are loaded or if there are no suggestions at all
|
|
309
|
-
this.setValue(null);
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
326
|
/**
|
|
313
327
|
* Triggered by user when selecting an item from an autocomplete suggestion list.
|
|
314
328
|
*/
|
|
315
329
|
onSelect(event) {
|
|
316
330
|
let newValue = event.value;
|
|
317
|
-
if (this.multiselect() && Array.isArray(this
|
|
318
|
-
newValue = [...this
|
|
331
|
+
if (this.multiselect() && Array.isArray(this.#valueItem) && this.#valueItem.length > 0) {
|
|
332
|
+
newValue = [...this.#valueItem, newValue];
|
|
319
333
|
}
|
|
320
334
|
else if (this.multiselect()) {
|
|
321
335
|
newValue = [newValue];
|
|
322
336
|
}
|
|
323
|
-
this
|
|
324
|
-
this
|
|
337
|
+
this.#setValueItem(newValue, true);
|
|
338
|
+
this.#isFocused = false;
|
|
325
339
|
}
|
|
326
340
|
/**
|
|
327
341
|
* Triggered by user when selecting an item from an autocomplete suggestion list.
|
|
328
342
|
*/
|
|
329
343
|
onUnselect(event) {
|
|
330
344
|
let newValue = null;
|
|
331
|
-
if (this.multiselect() && Array.isArray(this
|
|
332
|
-
|
|
333
|
-
newValue = this._rawValue.filter(i => (cmpProp ? i[cmpProp] !== event.value[cmpProp] : i !== event.value));
|
|
345
|
+
if (this.multiselect() && Array.isArray(this.#valueItem) && this.#valueItem.length > 0) {
|
|
346
|
+
newValue = this.#valueItem.filter(i => i.__track !== event.value.__track);
|
|
334
347
|
}
|
|
335
348
|
else if (this.multiselect()) {
|
|
336
349
|
newValue = [];
|
|
337
350
|
}
|
|
338
|
-
this
|
|
339
|
-
this
|
|
351
|
+
this.#setValueItem(newValue, true);
|
|
352
|
+
this.#isFocused = false;
|
|
340
353
|
}
|
|
341
354
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
342
355
|
onFocus(event) {
|
|
343
|
-
this
|
|
356
|
+
this.#isFocused = true;
|
|
344
357
|
}
|
|
345
358
|
/**
|
|
346
359
|
* calls the selectFirst item anytime the input field goes out of focus and if the suggestions panel is not displayed.
|
|
347
360
|
*/
|
|
348
361
|
onBlur(event) {
|
|
349
|
-
this
|
|
362
|
+
this.#isFocused = false;
|
|
350
363
|
const inputSearchVal = this.primeAutocomplete()?.inputEL?.nativeElement?.value;
|
|
351
|
-
if (this.autoClear() && this
|
|
352
|
-
this
|
|
364
|
+
if (this.autoClear() && this.#value != null && (inputSearchVal == null || inputSearchVal === '')) {
|
|
365
|
+
this.#propagateValueItemChange(null);
|
|
353
366
|
}
|
|
354
|
-
else if (!this
|
|
355
|
-
this
|
|
367
|
+
else if (!this.#isPanelShown) {
|
|
368
|
+
this.#selectFirstItem();
|
|
356
369
|
}
|
|
357
|
-
this
|
|
370
|
+
this.#onTouchedFn();
|
|
358
371
|
this.blur.emit(event);
|
|
359
372
|
}
|
|
360
|
-
|
|
361
|
-
this
|
|
373
|
+
onPanelShow() {
|
|
374
|
+
this.#isPanelShown = true;
|
|
362
375
|
}
|
|
363
376
|
/**
|
|
364
377
|
* calls the selectFirst item anytime the suggestions panel is closed and input field isn't focused.
|
|
365
378
|
*/
|
|
366
|
-
|
|
367
|
-
this
|
|
368
|
-
if (!this
|
|
369
|
-
this
|
|
379
|
+
onPanelHide() {
|
|
380
|
+
this.#isPanelShown = false;
|
|
381
|
+
if (!this.#isFocused) {
|
|
382
|
+
this.#selectFirstItem();
|
|
370
383
|
}
|
|
371
384
|
}
|
|
372
385
|
onClear() {
|
|
373
|
-
if (this
|
|
374
|
-
this
|
|
386
|
+
if (this.#value != null) {
|
|
387
|
+
this.#propagateValueItemChange(this.multiselect() ? [] : null);
|
|
375
388
|
}
|
|
376
389
|
}
|
|
377
390
|
registerOnChange(fn) {
|
|
378
|
-
this
|
|
391
|
+
this.#onChangeFn = fn;
|
|
379
392
|
}
|
|
380
393
|
registerOnTouched(fn) {
|
|
381
|
-
this
|
|
394
|
+
this.#onTouchedFn = fn;
|
|
382
395
|
}
|
|
383
396
|
setDisabledState(isDisabled) {
|
|
384
|
-
setTimeout(() => this.
|
|
397
|
+
setTimeout(() => this.#disabledWritable.set(isDisabled));
|
|
385
398
|
}
|
|
386
399
|
writeValue(value) {
|
|
387
|
-
this
|
|
400
|
+
this.#setItemsAndDataProvider();
|
|
388
401
|
// write value immediately - it is important so that first select is not triggered!
|
|
389
|
-
this
|
|
390
|
-
const optionsValuePropertyInit = this.
|
|
391
|
-
if (optionsValuePropertyInit && value != null && (typeof value !== 'object' || (Array.isArray(value) && value?.length > 0))) {
|
|
402
|
+
this.#value = value;
|
|
403
|
+
const optionsValuePropertyInit = this.optionsValueProperty();
|
|
404
|
+
if (optionsValuePropertyInit && value != null && (typeof value !== 'object' || (Array.isArray(value) && value?.filter(v => v != null).length > 0))) {
|
|
392
405
|
const isMultiValue = Array.isArray(value);
|
|
393
|
-
const
|
|
394
|
-
const matchedItems =
|
|
395
|
-
if (matchedItems
|
|
396
|
-
this
|
|
406
|
+
const valueAsItemsArray = (isMultiValue ? [...value.filter(v => v != null)] : [value]).map(i => this.#createAutocompleteItem(i));
|
|
407
|
+
const matchedItems = valueAsItemsArray?.map(v => this.suggestions().find(i => v.__track === i.__track)).filter(Boolean);
|
|
408
|
+
if (matchedItems.length === valueAsItemsArray?.length) {
|
|
409
|
+
this.#setValueFromWrite(isMultiValue ? matchedItems : matchedItems[0]);
|
|
397
410
|
}
|
|
398
411
|
else {
|
|
399
|
-
this
|
|
400
|
-
.getEntries(this.dataProvider(), this
|
|
412
|
+
this.#labelLookupService
|
|
413
|
+
.getEntries(this.dataProvider(), this.#dataProviderService, optionsValuePropertyInit, valueAsItemsArray.map(i => i.__track))
|
|
401
414
|
.pipe(take(1))
|
|
402
415
|
.subscribe({
|
|
403
416
|
next: items => {
|
|
404
|
-
|
|
405
|
-
|
|
417
|
+
// transform items to autocomplete items for comparation needs
|
|
418
|
+
const lookupAutocompleteItems = items.map(i => this.#createAutocompleteItem(i));
|
|
419
|
+
const matchedItems = valueAsItemsArray?.map((v, idx) => lookupAutocompleteItems.find(i => v.__track === i.__track)?.__original ??
|
|
420
|
+
this.#createValueLabelObjectFromOnlyValue(valueAsItemsArray[idx].__original));
|
|
421
|
+
this.#setValueFromWrite(isMultiValue ? matchedItems : matchedItems[0]);
|
|
406
422
|
},
|
|
407
423
|
error: () => {
|
|
408
|
-
this
|
|
424
|
+
this.#setValueFromWrite(isMultiValue
|
|
425
|
+
? this.#createValueLabelObjectFromOnlyValue(valueAsItemsArray[0].__original)
|
|
426
|
+
: valueAsItemsArray?.map(v => this.#createValueLabelObjectFromOnlyValue(v.__original)));
|
|
409
427
|
}
|
|
410
428
|
});
|
|
411
429
|
}
|
|
412
430
|
}
|
|
413
431
|
else {
|
|
414
|
-
this
|
|
432
|
+
this.#setValueFromWrite(value);
|
|
415
433
|
}
|
|
416
434
|
}
|
|
417
|
-
|
|
435
|
+
/**
|
|
436
|
+
* Transforms value and create fake object with value as value prop and label prop.
|
|
437
|
+
*/
|
|
438
|
+
#createValueLabelObjectFromOnlyValue(val) {
|
|
418
439
|
if (val == null) {
|
|
419
440
|
return val;
|
|
420
441
|
}
|
|
@@ -429,93 +450,116 @@ class AutocompleteComponent {
|
|
|
429
450
|
}
|
|
430
451
|
return obj;
|
|
431
452
|
}
|
|
432
|
-
setItemsAndDataProvider() {
|
|
433
|
-
if (this
|
|
453
|
+
#setItemsAndDataProvider() {
|
|
454
|
+
if (this.#isInited) {
|
|
434
455
|
return;
|
|
435
456
|
}
|
|
436
457
|
const dataProvider = this.dataProvider();
|
|
437
|
-
this
|
|
438
|
-
this
|
|
458
|
+
this.#dataProviderService = dataProvider.serviceType ? this.#injector.get(dataProvider.serviceType) : null;
|
|
459
|
+
this.#isInited = true;
|
|
439
460
|
}
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
461
|
+
/**
|
|
462
|
+
* Sets value from write. This must not be of type AutocompleteItem.
|
|
463
|
+
* @param value
|
|
464
|
+
* @private
|
|
465
|
+
*/
|
|
466
|
+
#setValueFromWrite(value) {
|
|
467
|
+
// Normalize value to always be internal item
|
|
468
|
+
let normalizedValue = value;
|
|
469
|
+
if (Array.isArray(value)) {
|
|
470
|
+
normalizedValue = value.map(v => this.#createAutocompleteItem(v));
|
|
443
471
|
}
|
|
444
|
-
if (
|
|
472
|
+
else if (value != null) {
|
|
473
|
+
normalizedValue = this.#createAutocompleteItem(value);
|
|
474
|
+
}
|
|
475
|
+
if (this.ngModelValue() == null && this.#valueItem != null) {
|
|
445
476
|
// value must first be set to synchronise states, then in next async cycle set to wanted null value
|
|
446
|
-
this.ngModelValue.set(this
|
|
477
|
+
this.ngModelValue.set(this.#valueItem);
|
|
447
478
|
setTimeout(() => {
|
|
448
|
-
this.ngModelValue.set(
|
|
479
|
+
this.ngModelValue.set(normalizedValue);
|
|
449
480
|
});
|
|
450
481
|
}
|
|
451
482
|
else {
|
|
452
|
-
this.ngModelValue.set(
|
|
483
|
+
this.ngModelValue.set(normalizedValue);
|
|
453
484
|
}
|
|
454
485
|
}
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
}
|
|
467
|
-
}));
|
|
468
|
-
}
|
|
469
|
-
i18nGetItemsKeys(items) {
|
|
470
|
-
return items.map(item => (typeof item === 'object' && this.optionsLabelPropertyInit() ? item[this.optionsLabelPropertyInit()] : item));
|
|
471
|
-
}
|
|
472
|
-
i18nPopulateItems(items, i18nMap) {
|
|
473
|
-
return items.map(item => {
|
|
474
|
-
if (typeof item === 'object' && this.optionsLabelPropertyInit()) {
|
|
475
|
-
const label = item[this.optionsLabelPropertyInit()];
|
|
476
|
-
const translation = narrowI18nToTranslation(i18nMap, label);
|
|
477
|
-
if (translation) {
|
|
478
|
-
return { ...item, [this.optionsLabelProperty()]: translation };
|
|
479
|
-
}
|
|
480
|
-
return { ...item };
|
|
481
|
-
}
|
|
482
|
-
else {
|
|
483
|
-
const translation = narrowI18nToTranslation(i18nMap, item);
|
|
484
|
-
return {
|
|
485
|
-
[this.optionsLabelProperty()]: translation ?? item,
|
|
486
|
-
[this.optionsValueProperty()]: item
|
|
487
|
-
};
|
|
488
|
-
}
|
|
489
|
-
});
|
|
486
|
+
#selectFirstItem() {
|
|
487
|
+
if (!this.selectFirst() || this.multiselect())
|
|
488
|
+
return;
|
|
489
|
+
const suggestions = this.suggestions();
|
|
490
|
+
if (suggestions.length > 0 && !this.#userSelectedItem) {
|
|
491
|
+
this.#setValueItem(suggestions[0]);
|
|
492
|
+
}
|
|
493
|
+
else if (!this.#userSelectedItem) {
|
|
494
|
+
// handles the case if the user provides an input and de-focuses the input field before suggestions are loaded or if there are no suggestions at all
|
|
495
|
+
this.#setValueItem(null);
|
|
496
|
+
}
|
|
490
497
|
}
|
|
491
|
-
|
|
492
|
-
|
|
498
|
+
#getLookup(params, query) {
|
|
499
|
+
return toObservable(this.dataProvider().lookup(params, this.#dataProviderService, query)).pipe(map(res => res.map(item => this.#createAutocompleteItem(item))));
|
|
500
|
+
}
|
|
501
|
+
#setSuggestionsFromLookupItems(items, query) {
|
|
502
|
+
if (query && query !== this.#currentQuery) {
|
|
493
503
|
// Skip processing to avoid outdated queries during inline search updates.
|
|
494
504
|
return;
|
|
495
505
|
}
|
|
506
|
+
// Normalize items to always be objects
|
|
507
|
+
const autocompleteItems = items.map(i => this.#createAutocompleteItem(i));
|
|
496
508
|
if (this.inlineSearch()) {
|
|
497
509
|
const queryLowerCase = query?.toLowerCase() ?? '';
|
|
498
|
-
const filteredItems =
|
|
499
|
-
|
|
500
|
-
const optionsLabelProperty = this.optionsLabelProperty();
|
|
501
|
-
if (optionsLabelProperty && typeof i === 'object') {
|
|
502
|
-
itemLabel = i[optionsLabelProperty];
|
|
503
|
-
}
|
|
504
|
-
if (itemLabel == null) {
|
|
505
|
-
return queryLowerCase == null || !queryLowerCase.length;
|
|
506
|
-
}
|
|
507
|
-
if (typeof itemLabel !== 'string') {
|
|
508
|
-
itemLabel = itemLabel.toString();
|
|
509
|
-
}
|
|
510
|
-
return itemLabel.toLowerCase().startsWith(queryLowerCase);
|
|
510
|
+
const filteredItems = autocompleteItems.filter(i => {
|
|
511
|
+
return i.__label.toLowerCase().startsWith(queryLowerCase);
|
|
511
512
|
});
|
|
512
|
-
this
|
|
513
|
-
this
|
|
513
|
+
this.#setSuggestionsWithCustomInput(filteredItems, query);
|
|
514
|
+
this.#userSelectedItem = undefined;
|
|
514
515
|
}
|
|
515
516
|
else {
|
|
516
|
-
this
|
|
517
|
-
this
|
|
517
|
+
this.#setSuggestionsWithCustomInput(autocompleteItems, query);
|
|
518
|
+
this.#userSelectedItem = undefined;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
#setSuggestionsWithCustomInput(items, query) {
|
|
522
|
+
// Mark items as selected or suggested
|
|
523
|
+
const currentValue = this.#valueItem;
|
|
524
|
+
// Directly modify items array instead of creating copies
|
|
525
|
+
items = items
|
|
526
|
+
.filter(item => item != null)
|
|
527
|
+
.map(item => {
|
|
528
|
+
let isSelected = false;
|
|
529
|
+
// Check if item is selected
|
|
530
|
+
if (currentValue != null) {
|
|
531
|
+
if (Array.isArray(currentValue)) {
|
|
532
|
+
isSelected = this.multiselect() ? currentValue.some(v => v.__track === item.__track) : false;
|
|
533
|
+
}
|
|
534
|
+
else {
|
|
535
|
+
isSelected = currentValue.__track === item.__track;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
return {
|
|
539
|
+
...item,
|
|
540
|
+
__isCustomInput: false,
|
|
541
|
+
__isSuggested: !isSelected,
|
|
542
|
+
__isSelected: isSelected
|
|
543
|
+
};
|
|
544
|
+
});
|
|
545
|
+
let finalItems = items;
|
|
546
|
+
// Add custom input as first item if allowCustomInput is enabled and query exists
|
|
547
|
+
if (this.allowInput() && query && query.length > 0) {
|
|
548
|
+
// Check if custom input already exists in items
|
|
549
|
+
const customInputExists = items.some(item => item.__label.toLowerCase() === query.toLowerCase());
|
|
550
|
+
if (!customInputExists) {
|
|
551
|
+
finalItems = [
|
|
552
|
+
{
|
|
553
|
+
...this.#createAutocompleteItem(query),
|
|
554
|
+
__isCustom: true,
|
|
555
|
+
__isSuggested: false,
|
|
556
|
+
__isSelected: false
|
|
557
|
+
},
|
|
558
|
+
...finalItems
|
|
559
|
+
];
|
|
560
|
+
}
|
|
518
561
|
}
|
|
562
|
+
this.suggestions.set(finalItems);
|
|
519
563
|
}
|
|
520
564
|
/**
|
|
521
565
|
* Selects and sets new value.
|
|
@@ -523,16 +567,16 @@ class AutocompleteComponent {
|
|
|
523
567
|
* @param value Represents the object value.
|
|
524
568
|
* @param fromUser If set value is triggered from user.
|
|
525
569
|
*/
|
|
526
|
-
|
|
570
|
+
#setValueItem(value, fromUser = false) {
|
|
527
571
|
if (fromUser) {
|
|
528
|
-
this
|
|
572
|
+
this.#userSelectedItem = value ?? undefined;
|
|
529
573
|
}
|
|
530
574
|
else {
|
|
531
575
|
this.ngModelValue.set(value);
|
|
532
576
|
}
|
|
533
|
-
this
|
|
577
|
+
this.#propagateValueItemChange(value);
|
|
534
578
|
}
|
|
535
|
-
|
|
579
|
+
#trimSearchQuery(value) {
|
|
536
580
|
switch (this.searchTrim()) {
|
|
537
581
|
case 'start':
|
|
538
582
|
return value?.trimStart();
|
|
@@ -544,42 +588,42 @@ class AutocompleteComponent {
|
|
|
544
588
|
return value;
|
|
545
589
|
}
|
|
546
590
|
}
|
|
591
|
+
#createAutocompleteItem(item) {
|
|
592
|
+
return createAutocompleteItem(item, {
|
|
593
|
+
translate: this.#translate,
|
|
594
|
+
optionsTrackProperty: this.optionsTrackProperty(),
|
|
595
|
+
optionsValueProperty: this.optionsValueProperty(),
|
|
596
|
+
optionsLabelProperty: this.optionsLabelProperty(),
|
|
597
|
+
optionsLabelTranslate: this.optionsLabelTranslate()
|
|
598
|
+
});
|
|
599
|
+
}
|
|
547
600
|
/**
|
|
548
|
-
* Propagates final value to
|
|
601
|
+
* Propagates final value to #value, on change fn and outputs.
|
|
549
602
|
*/
|
|
550
|
-
|
|
551
|
-
this
|
|
552
|
-
this
|
|
553
|
-
this
|
|
554
|
-
this.valueChange.emit(this
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
return value;
|
|
560
|
-
}
|
|
561
|
-
if (this.multiselect() && Array.isArray(value)) {
|
|
562
|
-
return value.map((item) => {
|
|
563
|
-
if (item && typeof item === 'object') {
|
|
564
|
-
return item[optionsValueProperty];
|
|
565
|
-
}
|
|
566
|
-
return null;
|
|
567
|
-
});
|
|
603
|
+
#propagateValueItemChange(value) {
|
|
604
|
+
this.#value = this.#getValueFromItem(value);
|
|
605
|
+
this.#valueItem = value;
|
|
606
|
+
this.#onChangeFn(this.#value);
|
|
607
|
+
this.valueChange.emit(this.#value);
|
|
608
|
+
}
|
|
609
|
+
#getValueFromItem(item) {
|
|
610
|
+
if (item == null) {
|
|
611
|
+
return item;
|
|
568
612
|
}
|
|
569
|
-
else if (
|
|
570
|
-
return
|
|
613
|
+
else if (Array.isArray(item)) {
|
|
614
|
+
return this.multiselect() ? item.map(item => item.__value) : [];
|
|
571
615
|
}
|
|
572
616
|
else {
|
|
573
|
-
return
|
|
617
|
+
return item?.__value;
|
|
574
618
|
}
|
|
575
619
|
}
|
|
576
620
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AutocompleteComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
577
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.8", type: AutocompleteComponent, isStandalone: true, selector: "mng-autocomplete", inputs: { dataProvider: { classPropertyName: "dataProvider", publicName: "dataProvider", isSignal: true, isRequired: true, transformFunction: null }, optionsTrackProperty: { classPropertyName: "optionsTrackProperty", publicName: "optionsTrackProperty", isSignal: true, isRequired: false, transformFunction: null },
|
|
621
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.8", type: AutocompleteComponent, isStandalone: true, selector: "mng-autocomplete", inputs: { dataProvider: { classPropertyName: "dataProvider", publicName: "dataProvider", isSignal: true, isRequired: true, transformFunction: null }, optionsTrackProperty: { classPropertyName: "optionsTrackProperty", publicName: "optionsTrackProperty", isSignal: true, isRequired: false, transformFunction: null }, optionsValueProperty: { classPropertyName: "optionsValueProperty", publicName: "optionsValueProperty", isSignal: true, isRequired: false, transformFunction: null }, optionsLabelProperty: { classPropertyName: "optionsLabelProperty", publicName: "optionsLabelProperty", isSignal: true, isRequired: false, transformFunction: null }, optionsLabelTranslate: { classPropertyName: "optionsLabelTranslate", publicName: "optionsLabelTranslate", isSignal: true, isRequired: false, transformFunction: null }, inlineSearch: { classPropertyName: "inlineSearch", publicName: "inlineSearch", isSignal: true, isRequired: false, transformFunction: null }, openOnFocus: { classPropertyName: "openOnFocus", publicName: "openOnFocus", isSignal: true, isRequired: false, transformFunction: null }, multiselect: { classPropertyName: "multiselect", publicName: "multiselect", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, dropdownClassName: { classPropertyName: "dropdownClassName", publicName: "dropdownClassName", isSignal: true, isRequired: false, transformFunction: null }, showClear: { classPropertyName: "showClear", publicName: "showClear", isSignal: true, isRequired: false, transformFunction: null }, autoClear: { classPropertyName: "autoClear", publicName: "autoClear", isSignal: true, isRequired: false, transformFunction: null }, selectFirst: { classPropertyName: "selectFirst", publicName: "selectFirst", isSignal: true, isRequired: false, transformFunction: null }, allowInput: { classPropertyName: "allowInput", publicName: "allowInput", isSignal: true, isRequired: false, transformFunction: null }, searchTrim: { classPropertyName: "searchTrim", publicName: "searchTrim", isSignal: true, isRequired: false, transformFunction: null }, disabledInput: { classPropertyName: "disabledInput", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, templates: { classPropertyName: "templates", publicName: "templates", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", blur: "blur" }, providers: [AUTOCOMPLETE_VALUE_ACCESSOR], viewQueries: [{ propertyName: "primeAutocomplete", first: true, predicate: AutoComplete, descendants: true, isSignal: true }], ngImport: i0, template: "<p-inputgroup [class]=\"{'has-prepends': prependTemplates().length > 0}\">\n @for (pt of prependTemplates(); track $index) {\n <p-inputgroup-addon>\n <ng-container *ngTemplateOutlet=\"pt.template\"></ng-container>\n </p-inputgroup-addon>\n }\n <p-autoComplete\n *mngRerender=\"multiselect()\"\n [placeholder]=\"placeholder()\"\n [dropdown]=\"true\"\n dataKey=\"__track\"\n optionLabel=\"__label\"\n optionValue=\"__value\"\n [suggestions]=\"suggestions()\"\n [multiple]=\"multiselect()\"\n [showEmptyMessage]=\"true\"\n [emptyMessage]=\"'mngAutocomplete.noMatches' | translate\"\n [class]=\"className()\"\n [panelStyleClass]=\"dropdownClassName()\"\n [minQueryLength]=\"openOnFocus() ? 0 : 1\"\n [showClear]=\"showClear()\"\n [forceSelection]=\"autoClear() || allowInput()\"\n autoOptionFocus=\"true\"\n [selectOnFocus]=\"allowInput()\"\n [disabled]=\"disabled()\"\n [completeOnFocus]=\"openOnFocus()\"\n (completeMethod)=\"onSearch($event)\"\n (onSelect)=\"onSelect($event)\"\n (onUnselect)=\"onUnselect($event)\"\n (onFocus)=\"onFocus($event)\"\n (onBlur)=\"onBlur($event)\"\n (onClear)=\"onClear()\"\n (onShow)=\"onPanelShow()\"\n (onHide)=\"onPanelHide()\"\n appendTo=\"body\"\n dropdownMode=\"current\">\n <ng-template let-item #item>\n <div style=\"display: flex; align-items: center; justify-content: space-between; width: 100%\">\n <span>{{ item.__label }}</span>\n @if (allowInput()) {\n <div style=\"display: flex; gap: 0.25rem\">\n @if (item.__isSelected) {\n <p-tag [value]=\"'general.selected' | translate\" severity=\"success\" />\n } @else if (item.__isSuggested) {\n <p-tag [value]=\"'general.suggested' | translate\" />\n } @else if (item.__isCustom) {\n <p-tag [value]=\"'general.custom' | translate\" severity=\"warn\" />\n }\n </div>\n }\n </div>\n </ng-template>\n </p-autoComplete>\n @for (at of appendTemplates(); track $index) {\n <p-inputgroup-addon>\n <ng-container *ngTemplateOutlet=\"at.template\"></ng-container>\n </p-inputgroup-addon>\n }\n</p-inputgroup>\n", styles: ["mng-autocomplete .has-prepends .p-autocomplete-input-multiple{border-top-left-radius:0!important;border-bottom-left-radius:0!important}mng-autocomplete p-inputgroup{font-size:1rem}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "component", type: AutoComplete, selector: "p-autoComplete, p-autocomplete, p-auto-complete", inputs: ["minLength", "minQueryLength", "delay", "panelStyle", "styleClass", "panelStyleClass", "inputStyle", "inputId", "inputStyleClass", "placeholder", "readonly", "scrollHeight", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "autoHighlight", "forceSelection", "type", "autoZIndex", "baseZIndex", "ariaLabel", "dropdownAriaLabel", "ariaLabelledBy", "dropdownIcon", "unique", "group", "completeOnFocus", "showClear", "dropdown", "showEmptyMessage", "dropdownMode", "multiple", "addOnTab", "tabindex", "dataKey", "emptyMessage", "showTransitionOptions", "hideTransitionOptions", "autofocus", "autocomplete", "optionGroupChildren", "optionGroupLabel", "overlayOptions", "suggestions", "optionLabel", "optionValue", "id", "searchMessage", "emptySelectionMessage", "selectionMessage", "autoOptionFocus", "selectOnFocus", "searchLocale", "optionDisabled", "focusOnHover", "typeahead", "addOnBlur", "separator", "appendTo", "motionOptions"], outputs: ["completeMethod", "onSelect", "onUnselect", "onAdd", "onFocus", "onBlur", "onDropdownClick", "onClear", "onInputKeydown", "onKeyUp", "onShow", "onHide", "onLazyLoad"] }, { kind: "component", type: InputGroup, selector: "p-inputgroup, p-inputGroup, p-input-group", inputs: ["styleClass"] }, { kind: "component", type: InputGroupAddon, selector: "p-inputgroup-addon, p-inputGroupAddon", inputs: ["style", "styleClass"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: RerenderDirective, selector: "[mngRerender]", inputs: ["mngRerender"] }, { kind: "component", type: Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
578
622
|
}
|
|
579
623
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AutocompleteComponent, decorators: [{
|
|
580
624
|
type: Component,
|
|
581
|
-
args: [{ selector: 'mng-autocomplete', encapsulation: ViewEncapsulation.None, providers: [AUTOCOMPLETE_VALUE_ACCESSOR], imports: [TranslatePipe, FormsModule, AutoComplete, InputGroup, InputGroupAddon, NgTemplateOutlet, RerenderDirective], changeDetection: ChangeDetectionStrategy.OnPush, template: "<p-inputgroup [class]=\"{'has-prepends': prependTemplates().length > 0}\">\n @for (pt of prependTemplates(); track $index) {\n <p-inputgroup-addon>\n <ng-container *ngTemplateOutlet=\"pt.template\"></ng-container>\n </p-inputgroup-addon>\n }\n <p-autoComplete\n *mngRerender=\"multiselect()\"\n [placeholder]=\"placeholder()\"\n [dropdown]=\"true\"\n
|
|
582
|
-
}], ctorParameters: () => [], propDecorators: { dataProvider: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataProvider", required: true }] }], optionsTrackProperty: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionsTrackProperty", required: false }] }],
|
|
625
|
+
args: [{ selector: 'mng-autocomplete', encapsulation: ViewEncapsulation.None, providers: [AUTOCOMPLETE_VALUE_ACCESSOR], imports: [TranslatePipe, FormsModule, AutoComplete, InputGroup, InputGroupAddon, NgTemplateOutlet, RerenderDirective, Tag], changeDetection: ChangeDetectionStrategy.OnPush, template: "<p-inputgroup [class]=\"{'has-prepends': prependTemplates().length > 0}\">\n @for (pt of prependTemplates(); track $index) {\n <p-inputgroup-addon>\n <ng-container *ngTemplateOutlet=\"pt.template\"></ng-container>\n </p-inputgroup-addon>\n }\n <p-autoComplete\n *mngRerender=\"multiselect()\"\n [placeholder]=\"placeholder()\"\n [dropdown]=\"true\"\n dataKey=\"__track\"\n optionLabel=\"__label\"\n optionValue=\"__value\"\n [suggestions]=\"suggestions()\"\n [multiple]=\"multiselect()\"\n [showEmptyMessage]=\"true\"\n [emptyMessage]=\"'mngAutocomplete.noMatches' | translate\"\n [class]=\"className()\"\n [panelStyleClass]=\"dropdownClassName()\"\n [minQueryLength]=\"openOnFocus() ? 0 : 1\"\n [showClear]=\"showClear()\"\n [forceSelection]=\"autoClear() || allowInput()\"\n autoOptionFocus=\"true\"\n [selectOnFocus]=\"allowInput()\"\n [disabled]=\"disabled()\"\n [completeOnFocus]=\"openOnFocus()\"\n (completeMethod)=\"onSearch($event)\"\n (onSelect)=\"onSelect($event)\"\n (onUnselect)=\"onUnselect($event)\"\n (onFocus)=\"onFocus($event)\"\n (onBlur)=\"onBlur($event)\"\n (onClear)=\"onClear()\"\n (onShow)=\"onPanelShow()\"\n (onHide)=\"onPanelHide()\"\n appendTo=\"body\"\n dropdownMode=\"current\">\n <ng-template let-item #item>\n <div style=\"display: flex; align-items: center; justify-content: space-between; width: 100%\">\n <span>{{ item.__label }}</span>\n @if (allowInput()) {\n <div style=\"display: flex; gap: 0.25rem\">\n @if (item.__isSelected) {\n <p-tag [value]=\"'general.selected' | translate\" severity=\"success\" />\n } @else if (item.__isSuggested) {\n <p-tag [value]=\"'general.suggested' | translate\" />\n } @else if (item.__isCustom) {\n <p-tag [value]=\"'general.custom' | translate\" severity=\"warn\" />\n }\n </div>\n }\n </div>\n </ng-template>\n </p-autoComplete>\n @for (at of appendTemplates(); track $index) {\n <p-inputgroup-addon>\n <ng-container *ngTemplateOutlet=\"at.template\"></ng-container>\n </p-inputgroup-addon>\n }\n</p-inputgroup>\n", styles: ["mng-autocomplete .has-prepends .p-autocomplete-input-multiple{border-top-left-radius:0!important;border-bottom-left-radius:0!important}mng-autocomplete p-inputgroup{font-size:1rem}\n"] }]
|
|
626
|
+
}], ctorParameters: () => [], propDecorators: { dataProvider: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataProvider", required: true }] }], optionsTrackProperty: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionsTrackProperty", required: false }] }], optionsValueProperty: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionsValueProperty", required: false }] }], optionsLabelProperty: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionsLabelProperty", required: false }] }], optionsLabelTranslate: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionsLabelTranslate", required: false }] }], inlineSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "inlineSearch", required: false }] }], openOnFocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "openOnFocus", required: false }] }], multiselect: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiselect", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], dropdownClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "dropdownClassName", required: false }] }], showClear: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClear", required: false }] }], autoClear: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoClear", required: false }] }], selectFirst: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectFirst", required: false }] }], allowInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowInput", required: false }] }], searchTrim: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchTrim", required: false }] }], disabledInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], templates: [{ type: i0.Input, args: [{ isSignal: true, alias: "templates", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], blur: [{ type: i0.Output, args: ["blur"] }], primeAutocomplete: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AutoComplete), { isSignal: true }] }] } });
|
|
583
627
|
|
|
584
628
|
const DATETIME_PICKER_VALUE_ACCESSOR = {
|
|
585
629
|
provide: NG_VALUE_ACCESSOR,
|
|
@@ -1227,7 +1271,7 @@ class DropdownComponent {
|
|
|
1227
1271
|
}
|
|
1228
1272
|
this.setItems(res, query);
|
|
1229
1273
|
this._loading.set(false);
|
|
1230
|
-
this.
|
|
1274
|
+
this.selectFirstOrRefreshOption(); // only selects first item if selectFirstItemInput is set accordingly
|
|
1231
1275
|
this.adjustValueOnItemsValuePropertyTypeMismatch();
|
|
1232
1276
|
},
|
|
1233
1277
|
error: err => {
|
|
@@ -1307,7 +1351,7 @@ class DropdownComponent {
|
|
|
1307
1351
|
this.propagateValueChange(primeMultiselect.value);
|
|
1308
1352
|
}
|
|
1309
1353
|
}
|
|
1310
|
-
|
|
1354
|
+
selectFirstOrRefreshOption() {
|
|
1311
1355
|
if (this.firstTimeSettingItems && this.items().length > 0 && this.selectFirstItemInput() && !this._value) {
|
|
1312
1356
|
const optionsValueProperty = this.optionsValueProperty();
|
|
1313
1357
|
const value = optionsValueProperty ? this.items()[0][optionsValueProperty] : this.items()[0];
|
|
@@ -1315,6 +1359,19 @@ class DropdownComponent {
|
|
|
1315
1359
|
this.firstTimeSettingItems = false;
|
|
1316
1360
|
this.propagateValueChange(value);
|
|
1317
1361
|
}
|
|
1362
|
+
else {
|
|
1363
|
+
const valueProperty = this.optionsValueProperty();
|
|
1364
|
+
const labelProperty = this.optionsLabelProperty();
|
|
1365
|
+
if (this._value == null || !labelProperty || this.items().length === 0) {
|
|
1366
|
+
return;
|
|
1367
|
+
}
|
|
1368
|
+
if (valueProperty) {
|
|
1369
|
+
const selectedOption = this.items().find(item => item[valueProperty] === this._value);
|
|
1370
|
+
if (selectedOption) {
|
|
1371
|
+
this.ngModelValue.set(selectedOption[valueProperty]);
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1318
1375
|
}
|
|
1319
1376
|
transformItems(items) {
|
|
1320
1377
|
if (this.optionsLabelTranslate()) {
|