@colijnit/corecomponents_v12 262.1.10 → 262.1.12
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/fesm2022/colijnit-corecomponents_v12.mjs +241 -144
- package/fesm2022/colijnit-corecomponents_v12.mjs.map +1 -1
- package/index.d.ts +15 -2
- package/lib/components/list-of-values/style/_layout.scss +4 -0
- package/lib/components/list-of-values/style/_material-definition.scss +4 -0
- package/lib/components/list-of-values/style/_theme.scss +8 -0
- package/package.json +1 -1
|
@@ -7190,12 +7190,15 @@ class InputTextComponent extends BaseInputComponent {
|
|
|
7190
7190
|
rightIconData;
|
|
7191
7191
|
selectOnFocus = false;
|
|
7192
7192
|
emptyPlace = false;
|
|
7193
|
-
firstDayOfWeek = '1'; //
|
|
7193
|
+
firstDayOfWeek = '1'; // Monday by default
|
|
7194
7194
|
noStyle = false;
|
|
7195
7195
|
hideArrowButtons = false;
|
|
7196
7196
|
get isDate() {
|
|
7197
7197
|
return this.type === "date";
|
|
7198
7198
|
}
|
|
7199
|
+
get hasValue() {
|
|
7200
|
+
return super.hasValue || (this.placeholder !== '' && this.placeholder !== null && this.placeholder !== undefined);
|
|
7201
|
+
}
|
|
7199
7202
|
leftIconClick = new EventEmitter();
|
|
7200
7203
|
leftIconMouseDown = new EventEmitter();
|
|
7201
7204
|
leftIconMouseUp = new EventEmitter();
|
|
@@ -7266,6 +7269,15 @@ class InputTextComponent extends BaseInputComponent {
|
|
|
7266
7269
|
this.elementRef = elementRef;
|
|
7267
7270
|
super._markAsOnPush();
|
|
7268
7271
|
}
|
|
7272
|
+
ngAfterViewInit() {
|
|
7273
|
+
// label was not correctly being used, so this is a legacy issue fix
|
|
7274
|
+
// if you want to use a placeholder (as a placeholder is meant to be used) then you need to set the label as well
|
|
7275
|
+
if (!this.label) {
|
|
7276
|
+
this.label = this.placeholder;
|
|
7277
|
+
this.placeholder = '';
|
|
7278
|
+
}
|
|
7279
|
+
super.ngAfterViewInit();
|
|
7280
|
+
}
|
|
7269
7281
|
handleLeftIconClick(event) {
|
|
7270
7282
|
event.preventDefault();
|
|
7271
7283
|
event.stopPropagation();
|
|
@@ -7402,18 +7414,19 @@ class InputTextComponent extends BaseInputComponent {
|
|
|
7402
7414
|
// Internal default first day of week
|
|
7403
7415
|
let weekdayOffset = parseInt(this.firstDayOfWeek, 10);
|
|
7404
7416
|
if (isNaN(weekdayOffset) || weekdayOffset < 1 || weekdayOffset > 7) {
|
|
7405
|
-
weekdayOffset =
|
|
7417
|
+
weekdayOffset = 1; // Monday
|
|
7406
7418
|
}
|
|
7407
|
-
|
|
7419
|
+
// 1 = Monday, 2 = Tuesday, 3 = Wednesday, ..., 7 = Sunday
|
|
7420
|
+
const jsWeekdayIndex = weekdayOffset - 1;
|
|
7408
7421
|
const jan4 = new Date(year, 0, 4);
|
|
7409
7422
|
const jan4Day = jan4.getDay();
|
|
7410
7423
|
const diffToMonday = (jan4Day + 6) % 7;
|
|
7411
7424
|
const firstWeekMonday = new Date(jan4);
|
|
7412
|
-
firstWeekMonday.setDate(jan4.getDate() - diffToMonday);
|
|
7425
|
+
firstWeekMonday.setDate(jan4.getDate() - diffToMonday);
|
|
7413
7426
|
const baseWeekStart = new Date(firstWeekMonday);
|
|
7414
|
-
baseWeekStart.setDate(
|
|
7415
|
-
|
|
7416
|
-
targetDate.setDate(
|
|
7427
|
+
baseWeekStart.setDate(firstWeekMonday.getDate() + (week - 1) * 7);
|
|
7428
|
+
let targetDate = new Date(baseWeekStart);
|
|
7429
|
+
targetDate.setDate(targetDate.getDate() + jsWeekdayIndex);
|
|
7417
7430
|
if (targetDate < today) {
|
|
7418
7431
|
year += 1;
|
|
7419
7432
|
const jan4Next = new Date(year, 0, 4);
|
|
@@ -7422,14 +7435,19 @@ class InputTextComponent extends BaseInputComponent {
|
|
|
7422
7435
|
const firstWeekMondayNext = new Date(jan4Next);
|
|
7423
7436
|
firstWeekMondayNext.setDate(jan4Next.getDate() - diffToMondayNext);
|
|
7424
7437
|
const baseWeekStartNext = new Date(firstWeekMondayNext);
|
|
7425
|
-
baseWeekStartNext.setDate(
|
|
7426
|
-
targetDate
|
|
7427
|
-
targetDate.
|
|
7428
|
-
targetDate.setDate(baseWeekStartNext.getDate() + jsWeekdayIndex);
|
|
7438
|
+
baseWeekStartNext.setDate(firstWeekMondayNext.getDate() + (week - 1) * 7);
|
|
7439
|
+
targetDate = new Date(baseWeekStartNext);
|
|
7440
|
+
targetDate.setDate(targetDate.getDate() + jsWeekdayIndex);
|
|
7429
7441
|
}
|
|
7430
|
-
this.model =
|
|
7442
|
+
this.model = this.formatDateLocal(targetDate);
|
|
7431
7443
|
this.modelChange.emit(this.model);
|
|
7432
7444
|
}
|
|
7445
|
+
formatDateLocal(date) {
|
|
7446
|
+
const year = date.getFullYear();
|
|
7447
|
+
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
7448
|
+
const day = String(date.getDate()).padStart(2, '0');
|
|
7449
|
+
return `${year}-${month}-${day}`;
|
|
7450
|
+
}
|
|
7433
7451
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: InputTextComponent, deps: [{ token: FormComponent, optional: true }, { token: i0.ChangeDetectorRef }, { token: OverlayService }, { token: FormInputUserModelChangeListenerService }, { token: NgZoneWrapperService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
7434
7452
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: InputTextComponent, isStandalone: false, selector: "co-input-text", inputs: { useContent: "useContent", placeholder: "placeholder", align: "align", type: "type", formatPipe: "formatPipe", min: "min", max: "max", pattern: "pattern", digitsOnly: "digitsOnly", excludePlusMinus: "excludePlusMinus", showClearButton: "showClearButton", keyDownWhiteList: "keyDownWhiteList", showPlaceholderOnFocus: "showPlaceholderOnFocus", leftIcon: "leftIcon", rightIcon: "rightIcon", leftIconData: "leftIconData", rightIconData: "rightIconData", selectOnFocus: "selectOnFocus", emptyPlace: "emptyPlace", firstDayOfWeek: "firstDayOfWeek", noStyle: "noStyle", hideArrowButtons: "hideArrowButtons", model: "model" }, outputs: { leftIconClick: "leftIconClick", leftIconMouseDown: "leftIconMouseDown", leftIconMouseUp: "leftIconMouseUp", rightIconClick: "rightIconClick", rightIconMouseDown: "rightIconMouseDown", rightIconMouseUp: "rightIconMouseUp", clearIconClick: "clearIconClick", isFocused: "isFocused" }, host: { listeners: { "document:pointerup": "handleDocumentPointerUp($event)", "document:pointercancel": "handleDocumentPointerUp($event)" }, properties: { "class.no-style": "this.noStyle", "class.hide-arrows": "this.hideArrowButtons", "class.isDate": "this.isDate", "class.co-input-text": "this.showClass", "class.has-left-icon": "this.hasLeftIcon", "class.has-right-icon": "this.hasRightIcon", "class.has-own-label": "this.hasOwnLabel" } }, providers: [
|
|
7435
7453
|
OverlayService, {
|
|
@@ -7452,7 +7470,7 @@ class InputTextComponent extends BaseInputComponent {
|
|
|
7452
7470
|
<div class="input-wrapper">
|
|
7453
7471
|
@if (showPlaceholderOnFocus || (!showPlaceholderOnFocus && !hasValue && !focused)) {
|
|
7454
7472
|
<label
|
|
7455
|
-
[textContent]="
|
|
7473
|
+
[textContent]="label"></label>
|
|
7456
7474
|
}
|
|
7457
7475
|
@if (!focused && !useContent && formatPipe) {
|
|
7458
7476
|
<span class="input-text-formatted"
|
|
@@ -7466,7 +7484,7 @@ class InputTextComponent extends BaseInputComponent {
|
|
|
7466
7484
|
[class.input-input-hidden]="useContent"
|
|
7467
7485
|
[ngClass]="align"
|
|
7468
7486
|
[type]="isWeekInputMode ? 'text' : (isFocusedOnDate || (hasValue && emptyPlace)) ? 'date' : (digitsOnly ? 'number' : (type === 'date' ? 'text' : type))"
|
|
7469
|
-
[placeholder]="type === 'date' && !isFocusedOnDate ? '' :
|
|
7487
|
+
[placeholder]="type === 'date' && !isFocusedOnDate ? '' : placeholder"
|
|
7470
7488
|
[pattern]="type === 'date' ? pattern : undefined"
|
|
7471
7489
|
[ngModel]="model"
|
|
7472
7490
|
[min]="(type === 'number' || type === 'date') && this.min ? this.min : undefined"
|
|
@@ -7528,7 +7546,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
7528
7546
|
<div class="input-wrapper">
|
|
7529
7547
|
@if (showPlaceholderOnFocus || (!showPlaceholderOnFocus && !hasValue && !focused)) {
|
|
7530
7548
|
<label
|
|
7531
|
-
[textContent]="
|
|
7549
|
+
[textContent]="label"></label>
|
|
7532
7550
|
}
|
|
7533
7551
|
@if (!focused && !useContent && formatPipe) {
|
|
7534
7552
|
<span class="input-text-formatted"
|
|
@@ -7542,7 +7560,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
7542
7560
|
[class.input-input-hidden]="useContent"
|
|
7543
7561
|
[ngClass]="align"
|
|
7544
7562
|
[type]="isWeekInputMode ? 'text' : (isFocusedOnDate || (hasValue && emptyPlace)) ? 'date' : (digitsOnly ? 'number' : (type === 'date' ? 'text' : type))"
|
|
7545
|
-
[placeholder]="type === 'date' && !isFocusedOnDate ? '' :
|
|
7563
|
+
[placeholder]="type === 'date' && !isFocusedOnDate ? '' : placeholder"
|
|
7546
7564
|
[pattern]="type === 'date' ? pattern : undefined"
|
|
7547
7565
|
[ngModel]="model"
|
|
7548
7566
|
[min]="(type === 'number' || type === 'date') && this.min ? this.min : undefined"
|
|
@@ -13596,12 +13614,38 @@ class LovUtils {
|
|
|
13596
13614
|
.filter(val => val != null && val !== '')
|
|
13597
13615
|
.join(' - ');
|
|
13598
13616
|
}
|
|
13617
|
+
static getHighlightParts(value, term) {
|
|
13618
|
+
const text = value ?? '';
|
|
13619
|
+
if (!text || !term) {
|
|
13620
|
+
return [{ text: text, match: false }];
|
|
13621
|
+
}
|
|
13622
|
+
const regex = new RegExp(LovUtils._escapeRegExp(term), 'gi');
|
|
13623
|
+
const parts = [];
|
|
13624
|
+
let lastIndex = 0;
|
|
13625
|
+
let match;
|
|
13626
|
+
while ((match = regex.exec(text)) !== null) {
|
|
13627
|
+
if (match.index > lastIndex) {
|
|
13628
|
+
parts.push({ text: text.slice(lastIndex, match.index), match: false });
|
|
13629
|
+
}
|
|
13630
|
+
parts.push({ text: match[0], match: true });
|
|
13631
|
+
lastIndex = match.index + match[0].length;
|
|
13632
|
+
if (match.index === regex.lastIndex) {
|
|
13633
|
+
regex.lastIndex++;
|
|
13634
|
+
}
|
|
13635
|
+
}
|
|
13636
|
+
if (lastIndex < text.length) {
|
|
13637
|
+
parts.push({ text: text.slice(lastIndex), match: false });
|
|
13638
|
+
}
|
|
13639
|
+
return parts;
|
|
13640
|
+
}
|
|
13641
|
+
static _escapeRegExp(value) {
|
|
13642
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
13643
|
+
}
|
|
13599
13644
|
}
|
|
13600
13645
|
|
|
13601
13646
|
class ListOfValuesPopupComponent {
|
|
13602
13647
|
iconCacheService;
|
|
13603
13648
|
_elementRef;
|
|
13604
|
-
lovUtils = LovUtils;
|
|
13605
13649
|
set lovItems(children) {
|
|
13606
13650
|
this._lovItems = children.toArray();
|
|
13607
13651
|
this._scrollIntoView();
|
|
@@ -13719,7 +13763,11 @@ class ListOfValuesPopupComponent {
|
|
|
13719
13763
|
}
|
|
13720
13764
|
}
|
|
13721
13765
|
selectModelByViewModel(viewModel, closePopup = true) {
|
|
13722
|
-
|
|
13766
|
+
const found = this.viewModelsMain.find(vm => vm === viewModel);
|
|
13767
|
+
if (!found) {
|
|
13768
|
+
return;
|
|
13769
|
+
}
|
|
13770
|
+
this.model = found.model;
|
|
13723
13771
|
this.modelChange.emit(this.model);
|
|
13724
13772
|
this._scrollIntoView();
|
|
13725
13773
|
if (closePopup) {
|
|
@@ -13752,6 +13800,9 @@ class ListOfValuesPopupComponent {
|
|
|
13752
13800
|
this.modelChange.emit(this.model);
|
|
13753
13801
|
}
|
|
13754
13802
|
selectNextOption(back = false) {
|
|
13803
|
+
if (this.viewModels.length === 0) {
|
|
13804
|
+
return;
|
|
13805
|
+
}
|
|
13755
13806
|
let nextModel;
|
|
13756
13807
|
if (!this.highLightModel) {
|
|
13757
13808
|
nextModel = this.viewModels[back ? this.viewModels.length - 1 : 0];
|
|
@@ -13827,6 +13878,9 @@ class ListOfValuesPopupComponent {
|
|
|
13827
13878
|
}
|
|
13828
13879
|
});
|
|
13829
13880
|
});
|
|
13881
|
+
this.viewModels.forEach((vm) => {
|
|
13882
|
+
vm.highlightParts = LovUtils.getHighlightParts(LovUtils.getDisplayValue(vm.model, this.displayField), this.searchTerm);
|
|
13883
|
+
});
|
|
13830
13884
|
}
|
|
13831
13885
|
_scrollIntoView() {
|
|
13832
13886
|
const activeIndex = this.viewModels.findIndex(vmm => vmm === this.highLightModel);
|
|
@@ -13888,18 +13942,30 @@ class ListOfValuesPopupComponent {
|
|
|
13888
13942
|
<co-icon class="input-text-left-icon" [iconData]="iconCacheService.getIcon(viewModel.model[optionIcon])">
|
|
13889
13943
|
</co-icon>
|
|
13890
13944
|
}
|
|
13891
|
-
<
|
|
13945
|
+
<ng-container [ngTemplateOutlet]="optionText" [ngTemplateOutletContext]="{parts: viewModel.highlightParts}"></ng-container>
|
|
13892
13946
|
}
|
|
13893
13947
|
@if (multiselect) {
|
|
13894
13948
|
<co-input-checkbox [model]="viewModel.checked"
|
|
13895
13949
|
(modelChange)="selectViewModel(viewModel, false)"></co-input-checkbox>
|
|
13896
|
-
<
|
|
13950
|
+
<ng-container [ngTemplateOutlet]="optionText" [ngTemplateOutletContext]="{parts: viewModel.highlightParts}"></ng-container>
|
|
13897
13951
|
}
|
|
13898
13952
|
</li>
|
|
13899
13953
|
}
|
|
13900
13954
|
</ul>
|
|
13901
13955
|
</div>
|
|
13902
|
-
|
|
13956
|
+
|
|
13957
|
+
<ng-template #optionText let-parts="parts">
|
|
13958
|
+
<span class="lov-options-text">
|
|
13959
|
+
@for (part of parts; track $index) {
|
|
13960
|
+
@if (part.match) {
|
|
13961
|
+
<mark class="lov-highlight" [textContent]="part.text"></mark>
|
|
13962
|
+
} @else {
|
|
13963
|
+
<span [textContent]="part.text"></span>
|
|
13964
|
+
}
|
|
13965
|
+
}
|
|
13966
|
+
</span>
|
|
13967
|
+
</ng-template>
|
|
13968
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: InputCheckboxComponent, selector: "co-input-checkbox", inputs: ["cssClass", "clickableLabel"], outputs: ["modelChange"] }, { kind: "directive", type: OverlayDirective, selector: "[overlay]", inputs: ["overlay", "view", "inline", "keepInView", "inheritWidth", "rightAlign", "fullSize"] }, { kind: "directive", type: ClickOutsideDirective, selector: "[clickOutside]", inputs: ["clickOutside", "alwaysTrigger"], outputs: ["clickOutside"], exportAs: ["clickOutside"] }, { kind: "component", type: IconComponent, selector: "co-icon", inputs: ["icon", "iconData"] }, { kind: "component", type: InputSearchComponent, selector: "co-input-search", inputs: ["placeholder", "handleKeydown", "useLeftIcon", "useRightIcon", "leftIconData", "rightIconData", "centerLabel"], outputs: ["search", "isFocused", "leftIconClick", "rightIconClick"] }, { kind: "pipe", type: CoreLocalizePipe, name: "coreLocalize" }], encapsulation: i0.ViewEncapsulation.None });
|
|
13903
13969
|
}
|
|
13904
13970
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ListOfValuesPopupComponent, decorators: [{
|
|
13905
13971
|
type: Component,
|
|
@@ -13939,17 +14005,29 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
13939
14005
|
<co-icon class="input-text-left-icon" [iconData]="iconCacheService.getIcon(viewModel.model[optionIcon])">
|
|
13940
14006
|
</co-icon>
|
|
13941
14007
|
}
|
|
13942
|
-
<
|
|
14008
|
+
<ng-container [ngTemplateOutlet]="optionText" [ngTemplateOutletContext]="{parts: viewModel.highlightParts}"></ng-container>
|
|
13943
14009
|
}
|
|
13944
14010
|
@if (multiselect) {
|
|
13945
14011
|
<co-input-checkbox [model]="viewModel.checked"
|
|
13946
14012
|
(modelChange)="selectViewModel(viewModel, false)"></co-input-checkbox>
|
|
13947
|
-
<
|
|
14013
|
+
<ng-container [ngTemplateOutlet]="optionText" [ngTemplateOutletContext]="{parts: viewModel.highlightParts}"></ng-container>
|
|
13948
14014
|
}
|
|
13949
14015
|
</li>
|
|
13950
14016
|
}
|
|
13951
14017
|
</ul>
|
|
13952
14018
|
</div>
|
|
14019
|
+
|
|
14020
|
+
<ng-template #optionText let-parts="parts">
|
|
14021
|
+
<span class="lov-options-text">
|
|
14022
|
+
@for (part of parts; track $index) {
|
|
14023
|
+
@if (part.match) {
|
|
14024
|
+
<mark class="lov-highlight" [textContent]="part.text"></mark>
|
|
14025
|
+
} @else {
|
|
14026
|
+
<span [textContent]="part.text"></span>
|
|
14027
|
+
}
|
|
14028
|
+
}
|
|
14029
|
+
</span>
|
|
14030
|
+
</ng-template>
|
|
13953
14031
|
`,
|
|
13954
14032
|
encapsulation: ViewEncapsulation.None,
|
|
13955
14033
|
standalone: false
|
|
@@ -14047,6 +14125,7 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
14047
14125
|
isLoading = false;
|
|
14048
14126
|
_collection = [];
|
|
14049
14127
|
debounceTimeout;
|
|
14128
|
+
_filterRequestId = 0;
|
|
14050
14129
|
_lovPopupComponentRef;
|
|
14051
14130
|
constructor(formComponent, iconCacheService, changeDetector, overlayService, formUserChangeListener, ngZoneWrapper, elementRef) {
|
|
14052
14131
|
super(changeDetector, overlayService, formUserChangeListener, ngZoneWrapper, elementRef);
|
|
@@ -14063,6 +14142,25 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
14063
14142
|
super.ngOnInit();
|
|
14064
14143
|
this._setSelectedModel();
|
|
14065
14144
|
}
|
|
14145
|
+
// Value shown in the input: the search text while fetching (largeCollection), otherwise the
|
|
14146
|
+
// selected model(s). Lets a single <co-input-text> serve both modes without a template split.
|
|
14147
|
+
get inputModel() {
|
|
14148
|
+
if (this.largeCollection) {
|
|
14149
|
+
return this.filterText;
|
|
14150
|
+
}
|
|
14151
|
+
if (this.multiselect) {
|
|
14152
|
+
return (!this.selectedModels || this.selectedModels.length === 0) ? null : this.selectedModels;
|
|
14153
|
+
}
|
|
14154
|
+
return this.selectedModel;
|
|
14155
|
+
}
|
|
14156
|
+
handleModelChange(model) {
|
|
14157
|
+
if (this.largeCollection) {
|
|
14158
|
+
this.onModelChange(model);
|
|
14159
|
+
}
|
|
14160
|
+
else {
|
|
14161
|
+
this.handleInputModelChange(model);
|
|
14162
|
+
}
|
|
14163
|
+
}
|
|
14066
14164
|
handleInputModelChange(model) {
|
|
14067
14165
|
if (this._lovPopupComponentRef) {
|
|
14068
14166
|
this._lovPopupComponentRef.instance.searchTerm = model;
|
|
@@ -14077,26 +14175,33 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
14077
14175
|
}
|
|
14078
14176
|
onModelChange(model) {
|
|
14079
14177
|
this.isLoading = true;
|
|
14178
|
+
// Mark this keystroke as the latest request immediately, so an older in-flight
|
|
14179
|
+
// request that resolves within the debounce window is still discarded.
|
|
14180
|
+
const requestId = ++this._filterRequestId;
|
|
14080
14181
|
clearTimeout(this.debounceTimeout);
|
|
14081
14182
|
this.debounceTimeout = setTimeout(() => {
|
|
14082
|
-
this.applyFilter(model);
|
|
14183
|
+
this.applyFilter(model, requestId);
|
|
14083
14184
|
}, 300);
|
|
14084
14185
|
}
|
|
14085
|
-
async applyFilter(text) {
|
|
14186
|
+
async applyFilter(text, requestId = ++this._filterRequestId) {
|
|
14187
|
+
await new Promise(resolve => setTimeout(resolve, 300));
|
|
14188
|
+
if (requestId !== this._filterRequestId) {
|
|
14189
|
+
return;
|
|
14190
|
+
}
|
|
14086
14191
|
if (text?.length < 3) {
|
|
14087
|
-
await new Promise(resolve => setTimeout(resolve, 300));
|
|
14088
14192
|
this.collection = undefined;
|
|
14193
|
+
this.filterText = text;
|
|
14194
|
+
this.closePopup();
|
|
14195
|
+
this.isLoading = false;
|
|
14196
|
+
this.changeDetector.detectChanges();
|
|
14197
|
+
return;
|
|
14089
14198
|
}
|
|
14090
|
-
|
|
14091
|
-
|
|
14092
|
-
|
|
14199
|
+
const loaded = await this.collectionLoadFn(text);
|
|
14200
|
+
if (requestId !== this._filterRequestId) {
|
|
14201
|
+
return;
|
|
14093
14202
|
}
|
|
14203
|
+
this.collection = loaded;
|
|
14094
14204
|
this.filterText = text;
|
|
14095
|
-
if (!this.collection) {
|
|
14096
|
-
this.changeDetector.detectChanges();
|
|
14097
|
-
this.isLoading = false;
|
|
14098
|
-
return [];
|
|
14099
|
-
}
|
|
14100
14205
|
this.filteredCollection = this.collection?.filter((item) => {
|
|
14101
14206
|
if (this.collectionLoadFnProp && this.collectionLoadFnProp.length > 0) {
|
|
14102
14207
|
return item[this.collectionLoadFnProp] && item[this.collectionLoadFnProp].toLowerCase().includes(text.toLowerCase());
|
|
@@ -14105,12 +14210,19 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
14105
14210
|
return true;
|
|
14106
14211
|
}
|
|
14107
14212
|
});
|
|
14108
|
-
(this.filteredCollection?.length > 0 && this.filterText?.length > 2)
|
|
14213
|
+
if (this.filteredCollection?.length > 0 && this.filterText?.length > 2) {
|
|
14214
|
+
this.openPopup(); // no-op when already open
|
|
14215
|
+
if (this._lovPopupComponentRef) {
|
|
14216
|
+
// Refresh the open popup in place; no re-create, so no flicker.
|
|
14217
|
+
this._lovPopupComponentRef.instance.collection = this.collection;
|
|
14218
|
+
this._lovPopupComponentRef.instance.searchTerm = text;
|
|
14219
|
+
}
|
|
14220
|
+
}
|
|
14221
|
+
else {
|
|
14222
|
+
this.closePopup();
|
|
14223
|
+
}
|
|
14109
14224
|
this.isLoading = false;
|
|
14110
14225
|
this.changeDetector.detectChanges();
|
|
14111
|
-
if (this._lovPopupComponentRef) {
|
|
14112
|
-
this._lovPopupComponentRef.instance.searchTerm = text;
|
|
14113
|
-
}
|
|
14114
14226
|
}
|
|
14115
14227
|
handleInputKeyDown(event) {
|
|
14116
14228
|
if (event) {
|
|
@@ -14155,6 +14267,11 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
14155
14267
|
if (this.readonly) {
|
|
14156
14268
|
return;
|
|
14157
14269
|
}
|
|
14270
|
+
// Idempotent: keep the existing popup so continued typing refreshes it in place
|
|
14271
|
+
// instead of re-creating it (which would replay the open animation / flicker).
|
|
14272
|
+
if (this._lovPopupComponentRef) {
|
|
14273
|
+
return;
|
|
14274
|
+
}
|
|
14158
14275
|
this.isSelectOpen = true;
|
|
14159
14276
|
this._lovPopupComponentRef = this.overlayService.createComponent(ListOfValuesPopupComponent, {
|
|
14160
14277
|
parentForOverlay: this.elementRef,
|
|
@@ -14213,6 +14330,11 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
14213
14330
|
this.focused = false;
|
|
14214
14331
|
}
|
|
14215
14332
|
checkModel() {
|
|
14333
|
+
if (this.largeCollection) {
|
|
14334
|
+
// The input holds the search text (not a to-be-resolved value) and selection happens via the
|
|
14335
|
+
// popup, so blur must not try to match/clear the model here.
|
|
14336
|
+
return;
|
|
14337
|
+
}
|
|
14216
14338
|
if (!this.multiselect && this.selectedModel && this.collection) {
|
|
14217
14339
|
const model = this.collection.find(c => LovUtils.getDisplayValue(c, this.displayField) === this.selectedModel);
|
|
14218
14340
|
if (model) {
|
|
@@ -14245,6 +14367,7 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
14245
14367
|
}
|
|
14246
14368
|
else {
|
|
14247
14369
|
this.selectedModel = '';
|
|
14370
|
+
this.filterText = '';
|
|
14248
14371
|
}
|
|
14249
14372
|
}
|
|
14250
14373
|
}
|
|
@@ -14256,59 +14379,46 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
14256
14379
|
useExisting: forwardRef(() => ListOfValuesComponent)
|
|
14257
14380
|
}
|
|
14258
14381
|
], viewQueries: [{ propertyName: "parentForOverlay", first: true, predicate: ["parentForOverlay"], descendants: true, read: ElementRef }], usesInheritance: true, ngImport: i0, template: `
|
|
14259
|
-
|
|
14260
|
-
|
|
14261
|
-
|
|
14262
|
-
|
|
14263
|
-
|
|
14264
|
-
|
|
14265
|
-
|
|
14266
|
-
|
|
14267
|
-
|
|
14268
|
-
|
|
14269
|
-
|
|
14270
|
-
|
|
14271
|
-
|
|
14272
|
-
|
|
14273
|
-
|
|
14274
|
-
|
|
14275
|
-
|
|
14276
|
-
|
|
14277
|
-
|
|
14278
|
-
|
|
14279
|
-
|
|
14280
|
-
|
|
14281
|
-
|
|
14282
|
-
|
|
14283
|
-
|
|
14284
|
-
|
|
14285
|
-
|
|
14286
|
-
|
|
14287
|
-
|
|
14288
|
-
|
|
14289
|
-
|
|
14290
|
-
|
|
14291
|
-
|
|
14292
|
-
|
|
14293
|
-
|
|
14294
|
-
|
|
14295
|
-
|
|
14296
|
-
|
|
14297
|
-
|
|
14298
|
-
|
|
14299
|
-
</co-input-text>
|
|
14300
|
-
}
|
|
14301
|
-
|
|
14302
|
-
@if (largeCollection) {
|
|
14303
|
-
<co-input-text
|
|
14304
|
-
[model]="filterText"
|
|
14305
|
-
[placeholder]="label"
|
|
14306
|
-
[required]="required"
|
|
14307
|
-
[disabled]="disabled"
|
|
14308
|
-
[readonly]="readonly"
|
|
14309
|
-
(modelChange)="onModelChange($event)">
|
|
14310
|
-
</co-input-text>
|
|
14311
|
-
}
|
|
14382
|
+
<co-input-text
|
|
14383
|
+
aria-haspopup="listbox"
|
|
14384
|
+
[attr.aria-expanded]="isSelectOpen"
|
|
14385
|
+
aria-controls="lov-popup"
|
|
14386
|
+
role="combobox"
|
|
14387
|
+
class="no-focus-line"
|
|
14388
|
+
overlayParent
|
|
14389
|
+
#parentForOverlay="overlayParent"
|
|
14390
|
+
type="text"
|
|
14391
|
+
[id]="label"
|
|
14392
|
+
[model]="inputModel"
|
|
14393
|
+
[placeholder]="label"
|
|
14394
|
+
[myFormInputInstance]="this"
|
|
14395
|
+
[readonly]="readonly"
|
|
14396
|
+
[disabled]="disabled"
|
|
14397
|
+
[required]="required"
|
|
14398
|
+
[noClickFocus]="false"
|
|
14399
|
+
[leftIconData]=" model && model[optionIcon] ? iconCacheService.getIcon(model[optionIcon]) : leftIconData"
|
|
14400
|
+
[rightIcon]="isSelectOpen ? icons.ChevronUpRegular : icons.ChevronDownRegular"
|
|
14401
|
+
[showClearButton]="true"
|
|
14402
|
+
[useContent]="multiselect"
|
|
14403
|
+
[customHeight]="multiselect"
|
|
14404
|
+
[keepFocussed]="keepFocussed"
|
|
14405
|
+
(modelChange)="handleModelChange($event)"
|
|
14406
|
+
(click)="openPopup()"
|
|
14407
|
+
(rightIconClick)="toggleSelect()"
|
|
14408
|
+
(keydown)="handleInputKeyDown($event)"
|
|
14409
|
+
(clearIconClick)="clearModel($event)"
|
|
14410
|
+
(blur)="checkModel()">
|
|
14411
|
+
@if (multiselect && showChips) {
|
|
14412
|
+
<div class="multiselect-chips-wrapper">
|
|
14413
|
+
@for (chip of model; track chip) {
|
|
14414
|
+
<div class="chips">
|
|
14415
|
+
<span class="chips-description" [textContent]="lovUtils.getDisplayValue(chip, displayField)"></span>
|
|
14416
|
+
<co-icon class="remove-chip-icon" [icon]="icons.CrossSkinny" (click)="removeOptionFromModel(chip)"></co-icon>
|
|
14417
|
+
</div>
|
|
14418
|
+
}
|
|
14419
|
+
</div>
|
|
14420
|
+
}
|
|
14421
|
+
</co-input-text>
|
|
14312
14422
|
@if (isLoading) {
|
|
14313
14423
|
<div class="filter-loader"><span></span></div>
|
|
14314
14424
|
}
|
|
@@ -14320,59 +14430,46 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
14320
14430
|
args: [{
|
|
14321
14431
|
selector: 'co-list-of-values',
|
|
14322
14432
|
template: `
|
|
14323
|
-
|
|
14324
|
-
|
|
14325
|
-
|
|
14326
|
-
|
|
14327
|
-
|
|
14328
|
-
|
|
14329
|
-
|
|
14330
|
-
|
|
14331
|
-
|
|
14332
|
-
|
|
14333
|
-
|
|
14334
|
-
|
|
14335
|
-
|
|
14336
|
-
|
|
14337
|
-
|
|
14338
|
-
|
|
14339
|
-
|
|
14340
|
-
|
|
14341
|
-
|
|
14342
|
-
|
|
14343
|
-
|
|
14344
|
-
|
|
14345
|
-
|
|
14346
|
-
|
|
14347
|
-
|
|
14348
|
-
|
|
14349
|
-
|
|
14350
|
-
|
|
14351
|
-
|
|
14352
|
-
|
|
14353
|
-
|
|
14354
|
-
|
|
14355
|
-
|
|
14356
|
-
|
|
14357
|
-
|
|
14358
|
-
|
|
14359
|
-
|
|
14360
|
-
|
|
14361
|
-
|
|
14362
|
-
|
|
14363
|
-
</co-input-text>
|
|
14364
|
-
}
|
|
14365
|
-
|
|
14366
|
-
@if (largeCollection) {
|
|
14367
|
-
<co-input-text
|
|
14368
|
-
[model]="filterText"
|
|
14369
|
-
[placeholder]="label"
|
|
14370
|
-
[required]="required"
|
|
14371
|
-
[disabled]="disabled"
|
|
14372
|
-
[readonly]="readonly"
|
|
14373
|
-
(modelChange)="onModelChange($event)">
|
|
14374
|
-
</co-input-text>
|
|
14375
|
-
}
|
|
14433
|
+
<co-input-text
|
|
14434
|
+
aria-haspopup="listbox"
|
|
14435
|
+
[attr.aria-expanded]="isSelectOpen"
|
|
14436
|
+
aria-controls="lov-popup"
|
|
14437
|
+
role="combobox"
|
|
14438
|
+
class="no-focus-line"
|
|
14439
|
+
overlayParent
|
|
14440
|
+
#parentForOverlay="overlayParent"
|
|
14441
|
+
type="text"
|
|
14442
|
+
[id]="label"
|
|
14443
|
+
[model]="inputModel"
|
|
14444
|
+
[placeholder]="label"
|
|
14445
|
+
[myFormInputInstance]="this"
|
|
14446
|
+
[readonly]="readonly"
|
|
14447
|
+
[disabled]="disabled"
|
|
14448
|
+
[required]="required"
|
|
14449
|
+
[noClickFocus]="false"
|
|
14450
|
+
[leftIconData]=" model && model[optionIcon] ? iconCacheService.getIcon(model[optionIcon]) : leftIconData"
|
|
14451
|
+
[rightIcon]="isSelectOpen ? icons.ChevronUpRegular : icons.ChevronDownRegular"
|
|
14452
|
+
[showClearButton]="true"
|
|
14453
|
+
[useContent]="multiselect"
|
|
14454
|
+
[customHeight]="multiselect"
|
|
14455
|
+
[keepFocussed]="keepFocussed"
|
|
14456
|
+
(modelChange)="handleModelChange($event)"
|
|
14457
|
+
(click)="openPopup()"
|
|
14458
|
+
(rightIconClick)="toggleSelect()"
|
|
14459
|
+
(keydown)="handleInputKeyDown($event)"
|
|
14460
|
+
(clearIconClick)="clearModel($event)"
|
|
14461
|
+
(blur)="checkModel()">
|
|
14462
|
+
@if (multiselect && showChips) {
|
|
14463
|
+
<div class="multiselect-chips-wrapper">
|
|
14464
|
+
@for (chip of model; track chip) {
|
|
14465
|
+
<div class="chips">
|
|
14466
|
+
<span class="chips-description" [textContent]="lovUtils.getDisplayValue(chip, displayField)"></span>
|
|
14467
|
+
<co-icon class="remove-chip-icon" [icon]="icons.CrossSkinny" (click)="removeOptionFromModel(chip)"></co-icon>
|
|
14468
|
+
</div>
|
|
14469
|
+
}
|
|
14470
|
+
</div>
|
|
14471
|
+
}
|
|
14472
|
+
</co-input-text>
|
|
14376
14473
|
@if (isLoading) {
|
|
14377
14474
|
<div class="filter-loader"><span></span></div>
|
|
14378
14475
|
}
|