@colijnit/corecomponents_v12 261.20.17 → 261.20.18
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 +660 -354
- package/fesm2022/colijnit-corecomponents_v12.mjs.map +1 -1
- package/index.d.ts +59 -9
- package/lib/components/grid-toolbar/style/_layout.scss +1 -0
- package/lib/components/grid-toolbar-button/style/_layout.scss +1 -0
- package/lib/components/input-number-picker/style/_layout.scss +8 -0
- 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/lib/components/simple-grid/style/_layout.scss +1 -0
- package/package.json +1 -1
- package/colijnit-corecomponents_v12-262.1.9.tgz +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { __decorate } from 'tslib';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
|
-
import { Input, Injectable, HostBinding, ViewEncapsulation, Component, Directive, ElementRef, Pipe, EventEmitter, Output, ViewChildren, ViewContainerRef, HostListener, ViewChild, Optional, NgModule, SkipSelf, InjectionToken, Inject, forwardRef, ChangeDetectionStrategy, ContentChildren, NO_ERRORS_SCHEMA, Injector, QueryList } from '@angular/core';
|
|
3
|
+
import { Input, Injectable, HostBinding, ViewEncapsulation, Component, Directive, ElementRef, Pipe, EventEmitter, Output, ViewChildren, ViewContainerRef, HostListener, ViewChild, Optional, NgModule, SkipSelf, InjectionToken, Inject, forwardRef, ChangeDetectionStrategy, ContentChildren, LOCALE_ID, NO_ERRORS_SCHEMA, Injector, QueryList } from '@angular/core';
|
|
4
4
|
import * as i5 from '@angular/forms';
|
|
5
5
|
import { NgModel, UntypedFormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
6
6
|
import * as i1 from '@angular/platform-browser';
|
|
@@ -532,6 +532,28 @@ class NumberUtils {
|
|
|
532
532
|
return { isOk: false, nearestOkNr: nearestOkNr };
|
|
533
533
|
}
|
|
534
534
|
}
|
|
535
|
+
/**
|
|
536
|
+
* Decides whether typing one more digit onto the given numeric text would exceed the configured
|
|
537
|
+
* digit limits. When `decimals` (scale) is set, `maxLength` is treated as the total precision: the
|
|
538
|
+
* integer part is capped at (maxLength - decimals) digits and the fractional part at `decimals`
|
|
539
|
+
* digits. When `decimals` is not set, `maxLength` caps the total number of digits.
|
|
540
|
+
*
|
|
541
|
+
* Note: assumes the digit is appended at the end of the value, because native number inputs expose
|
|
542
|
+
* no caret/selection information to constrain mid-string edits.
|
|
543
|
+
*/
|
|
544
|
+
static WouldExceedDigitLimits(currentValue, maxLength, decimals) {
|
|
545
|
+
const digits = ('' + (currentValue ?? '')).replace('-', '');
|
|
546
|
+
if (decimals > 0) {
|
|
547
|
+
const separatorIndex = digits.search(/[.,]/);
|
|
548
|
+
if (separatorIndex === -1) {
|
|
549
|
+
const maxIntegerDigits = maxLength > 0 ? maxLength - decimals : Number.POSITIVE_INFINITY;
|
|
550
|
+
return digits.length >= maxIntegerDigits;
|
|
551
|
+
}
|
|
552
|
+
const decimalDigits = digits.length - separatorIndex - 1;
|
|
553
|
+
return decimalDigits >= decimals;
|
|
554
|
+
}
|
|
555
|
+
return maxLength > 0 && digits.length >= maxLength;
|
|
556
|
+
}
|
|
535
557
|
static _GetLargestDecimalPrecisionOf(...args) {
|
|
536
558
|
return ArrayUtils.GetMaxCalculatedValue(args, (arg) => {
|
|
537
559
|
return NumberUtils.GetDecimalPlaces(arg);
|
|
@@ -934,8 +956,12 @@ function requiredValidator(control) {
|
|
|
934
956
|
function precisionScaleValidator(precision, scale) {
|
|
935
957
|
return function (control) {
|
|
936
958
|
let isValid = true;
|
|
937
|
-
if (control) {
|
|
938
|
-
|
|
959
|
+
if (control && control.value !== null && control.value !== undefined && control.value !== '') {
|
|
960
|
+
// The value may be a locale display string (e.g. "1234567,89"); normalize it to a number so the
|
|
961
|
+
// decimal separator is not counted as an integer digit by CheckPrecisionAndScale.
|
|
962
|
+
const raw = control.value;
|
|
963
|
+
const numeric = typeof raw === 'string' ? Number(raw.replace(',', '.')) : raw;
|
|
964
|
+
isValid = isNaN(numeric) || NumberUtils.CheckPrecisionAndScale(numeric, precision, scale).isOk;
|
|
939
965
|
}
|
|
940
966
|
return isValid ? null : { 'precision-scale': "MESSAGE_FIELD_PRECISION_OVERRIDDEN||" + precision };
|
|
941
967
|
};
|
|
@@ -2031,27 +2057,28 @@ class CommitButtonsComponent {
|
|
|
2031
2057
|
event.currentTarget.removeEventListener('animationiteration', this._handleAnimationIteration);
|
|
2032
2058
|
};
|
|
2033
2059
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CommitButtonsComponent, deps: [{ token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component });
|
|
2034
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: CommitButtonsComponent, isStandalone: false, selector: "co-commit-buttons", inputs: { committing: "committing", commitFinished: "commitFinished", parentForOverlay: "parentForOverlay" }, outputs: { cancelClick: "cancelClick", commitClick: "commitClick" }, host: { properties: { "class.co-commit-buttons": "this.showClass" } }, viewQueries: [{ propertyName: "content", predicate: ["animatediv"], descendants: true, read: ElementRef }], ngImport: i0, template: `
|
|
2035
|
-
<div class="commit-buttons-wrapper" [overlay]="parentForOverlay" [rightAlign]="true" @showHideSaveCancel>
|
|
2036
|
-
<div class="commit-buttons-button save" [class.finished]="commitFinished"
|
|
2037
|
-
(
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
<div #animatediv></div>
|
|
2042
|
-
<div #animatediv></div>
|
|
2043
|
-
<div #animatediv></div>
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
<
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2060
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: CommitButtonsComponent, isStandalone: false, selector: "co-commit-buttons", inputs: { committing: "committing", commitFinished: "commitFinished", parentForOverlay: "parentForOverlay" }, outputs: { cancelClick: "cancelClick", commitClick: "commitClick" }, host: { properties: { "class.co-commit-buttons": "this.showClass" } }, viewQueries: [{ propertyName: "content", predicate: ["animatediv"], descendants: true, read: ElementRef }], ngImport: i0, template: `
|
|
2061
|
+
<div class="commit-buttons-wrapper" [overlay]="parentForOverlay" [rightAlign]="true" @showHideSaveCancel>
|
|
2062
|
+
<div class="commit-buttons-button save" [class.finished]="commitFinished"
|
|
2063
|
+
(mousedown)="$event.preventDefault()"
|
|
2064
|
+
(click)="commitClick.emit($event)">
|
|
2065
|
+
@if (committing) {
|
|
2066
|
+
<div class="save-button-spinner">
|
|
2067
|
+
<div #animatediv></div>
|
|
2068
|
+
<div #animatediv></div>
|
|
2069
|
+
<div #animatediv></div>
|
|
2070
|
+
<div #animatediv></div>
|
|
2071
|
+
</div>
|
|
2072
|
+
}
|
|
2073
|
+
@if (firstShow || commitFinished) {
|
|
2074
|
+
<svg class="checkmark" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52">
|
|
2075
|
+
<path class="checkmark-check" [class.first-show]="firstShow" fill="none" d="M14.1 27.2l7.1 7.2 16.7-16.8"/></svg>
|
|
2076
|
+
}
|
|
2077
|
+
</div>
|
|
2078
|
+
<div class="commit-buttons-button cancel" (mousedown)="$event.preventDefault()" (click)="cancelClick.emit($event)">
|
|
2079
|
+
<div class="cancel-button"></div>
|
|
2080
|
+
</div>
|
|
2081
|
+
</div>
|
|
2055
2082
|
`, isInline: true, dependencies: [{ kind: "directive", type: OverlayDirective, selector: "[overlay]", inputs: ["overlay", "view", "inline", "keepInView", "inheritWidth", "rightAlign", "fullSize"] }], animations: [
|
|
2056
2083
|
trigger('showHideSaveCancel', [
|
|
2057
2084
|
state('*', style({ transform: 'scaleY(1)', opacity: 1 })),
|
|
@@ -2064,27 +2091,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
2064
2091
|
type: Component,
|
|
2065
2092
|
args: [{
|
|
2066
2093
|
selector: 'co-commit-buttons',
|
|
2067
|
-
template: `
|
|
2068
|
-
<div class="commit-buttons-wrapper" [overlay]="parentForOverlay" [rightAlign]="true" @showHideSaveCancel>
|
|
2069
|
-
<div class="commit-buttons-button save" [class.finished]="commitFinished"
|
|
2070
|
-
(
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
<div #animatediv></div>
|
|
2075
|
-
<div #animatediv></div>
|
|
2076
|
-
<div #animatediv></div>
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
<
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2094
|
+
template: `
|
|
2095
|
+
<div class="commit-buttons-wrapper" [overlay]="parentForOverlay" [rightAlign]="true" @showHideSaveCancel>
|
|
2096
|
+
<div class="commit-buttons-button save" [class.finished]="commitFinished"
|
|
2097
|
+
(mousedown)="$event.preventDefault()"
|
|
2098
|
+
(click)="commitClick.emit($event)">
|
|
2099
|
+
@if (committing) {
|
|
2100
|
+
<div class="save-button-spinner">
|
|
2101
|
+
<div #animatediv></div>
|
|
2102
|
+
<div #animatediv></div>
|
|
2103
|
+
<div #animatediv></div>
|
|
2104
|
+
<div #animatediv></div>
|
|
2105
|
+
</div>
|
|
2106
|
+
}
|
|
2107
|
+
@if (firstShow || commitFinished) {
|
|
2108
|
+
<svg class="checkmark" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52">
|
|
2109
|
+
<path class="checkmark-check" [class.first-show]="firstShow" fill="none" d="M14.1 27.2l7.1 7.2 16.7-16.8"/></svg>
|
|
2110
|
+
}
|
|
2111
|
+
</div>
|
|
2112
|
+
<div class="commit-buttons-button cancel" (mousedown)="$event.preventDefault()" (click)="cancelClick.emit($event)">
|
|
2113
|
+
<div class="cancel-button"></div>
|
|
2114
|
+
</div>
|
|
2115
|
+
</div>
|
|
2088
2116
|
`,
|
|
2089
2117
|
animations: [
|
|
2090
2118
|
trigger('showHideSaveCancel', [
|
|
@@ -2267,7 +2295,7 @@ class BaseInputComponent {
|
|
|
2267
2295
|
get model() {
|
|
2268
2296
|
return this._model;
|
|
2269
2297
|
}
|
|
2270
|
-
label;
|
|
2298
|
+
label = '';
|
|
2271
2299
|
noValidation = false;
|
|
2272
2300
|
initFocus;
|
|
2273
2301
|
noClickFocus;
|
|
@@ -2517,7 +2545,6 @@ class BaseInputComponent {
|
|
|
2517
2545
|
// @implements ConfigurationAdapterComponent
|
|
2518
2546
|
objectConfigName;
|
|
2519
2547
|
validationError = '';
|
|
2520
|
-
shouldCommit = true;
|
|
2521
2548
|
_markedAsUserTouched = false;
|
|
2522
2549
|
_destroyed = false;
|
|
2523
2550
|
_hasOnPushCdStrategy = false;
|
|
@@ -2543,6 +2570,7 @@ class BaseInputComponent {
|
|
|
2543
2570
|
_formReadonlyChangeSub;
|
|
2544
2571
|
_clearMarkedAsUserTouchedSub;
|
|
2545
2572
|
_canSaveOrCancel = false;
|
|
2573
|
+
_committing = false;
|
|
2546
2574
|
_commitButtonsComponentRef;
|
|
2547
2575
|
_validationComponentRef;
|
|
2548
2576
|
constructor(changeDetector, overlayService, formUserChangeListener, ngZoneWrapper, elementRef) {
|
|
@@ -2614,7 +2642,6 @@ class BaseInputComponent {
|
|
|
2614
2642
|
return Promise.resolve(true);
|
|
2615
2643
|
};
|
|
2616
2644
|
cancelClick(event) {
|
|
2617
|
-
this.shouldCommit = false;
|
|
2618
2645
|
this.keepFocus = true;
|
|
2619
2646
|
if (this._initialModelSet) {
|
|
2620
2647
|
this.model = this._initialModel;
|
|
@@ -2669,7 +2696,7 @@ class BaseInputComponent {
|
|
|
2669
2696
|
this.focus.next();
|
|
2670
2697
|
}
|
|
2671
2698
|
async doBlur(event, handleCommit = true) {
|
|
2672
|
-
if (this.showSaveCancel && handleCommit && this._modelDirtyForCommit
|
|
2699
|
+
if (this.showSaveCancel && handleCommit && this._modelDirtyForCommit) {
|
|
2673
2700
|
await this._handleCommit(event, false);
|
|
2674
2701
|
}
|
|
2675
2702
|
setTimeout(() => {
|
|
@@ -2799,23 +2826,37 @@ class BaseInputComponent {
|
|
|
2799
2826
|
}
|
|
2800
2827
|
}
|
|
2801
2828
|
async _handleCommit(event, doBlur = true) {
|
|
2802
|
-
if (!this.showSaveCancel ||
|
|
2829
|
+
if (!this.showSaveCancel || !this._modelDirtyForCommit || this._committing) {
|
|
2803
2830
|
return true;
|
|
2804
2831
|
}
|
|
2832
|
+
this._committing = true;
|
|
2805
2833
|
this.keepFocus = true;
|
|
2806
|
-
this.shouldCommit = true;
|
|
2807
2834
|
if (this._commitButtonsComponentRef) {
|
|
2808
2835
|
this._commitButtonsComponentRef.instance.commitFinished = false;
|
|
2809
2836
|
this._commitButtonsComponentRef.instance.committing = true;
|
|
2810
2837
|
}
|
|
2811
2838
|
this._modelDirtyForCommit = false;
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2839
|
+
try {
|
|
2840
|
+
const success = await this.commit(this.model);
|
|
2841
|
+
if (success) {
|
|
2842
|
+
// keep the committed value as the new baseline, otherwise a later model re-emission
|
|
2843
|
+
// would compare against a stale _initialModel and re-open the commit guard.
|
|
2844
|
+
this._initialModel = this._model;
|
|
2845
|
+
this._modelDirtyForCommit = false;
|
|
2846
|
+
}
|
|
2847
|
+
else {
|
|
2848
|
+
this._modelDirtyForCommit = true;
|
|
2849
|
+
}
|
|
2850
|
+
this.keepFocus = false;
|
|
2851
|
+
await this._commitFinished();
|
|
2852
|
+
if (success && doBlur) {
|
|
2853
|
+
this.doBlur(event, false);
|
|
2854
|
+
}
|
|
2855
|
+
return success;
|
|
2856
|
+
}
|
|
2857
|
+
finally {
|
|
2858
|
+
this._committing = false;
|
|
2817
2859
|
}
|
|
2818
|
-
return success;
|
|
2819
2860
|
}
|
|
2820
2861
|
_commitFinished() {
|
|
2821
2862
|
return new Promise((resolve) => {
|
|
@@ -2848,6 +2889,8 @@ class BaseInputComponent {
|
|
|
2848
2889
|
this.input.disabled = disabled;
|
|
2849
2890
|
}
|
|
2850
2891
|
}
|
|
2892
|
+
// protected so numeric components can suppress the native maxlength (which, on a text input, would
|
|
2893
|
+
// wrongly count the decimal separator/sign as characters); they enforce precision/scale in keydown.
|
|
2851
2894
|
_setNativeMaxLength(maxlength) {
|
|
2852
2895
|
if (this.input && !isNaN(maxlength)) {
|
|
2853
2896
|
this.input.maxLength = maxlength;
|
|
@@ -5802,48 +5845,40 @@ class GridToolbarComponent {
|
|
|
5802
5845
|
}
|
|
5803
5846
|
}
|
|
5804
5847
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: GridToolbarComponent, deps: [{ token: IconCacheService }], target: i0.ɵɵFactoryTarget.Component });
|
|
5805
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: GridToolbarComponent, isStandalone: false, selector: "co-grid-toolbar", inputs: { showEdit: "showEdit", showAdd: "showAdd", showDelete: "showDelete", deleteEnabled: "deleteEnabled" }, outputs: { editClick: "editClick", cancelClick: "cancelClick", saveClick: "saveClick", addClick: "addClick", deleteClick: "deleteClick" }, host: { properties: { "class.co-grid-toolbar": "this.showClass" } }, ngImport: i0, template: `
|
|
5806
|
-
<div class="grid-toolbar-wrapper">
|
|
5807
|
-
@if (showEdit) {
|
|
5808
|
-
<co-icon [iconData]="iconsService.getIcon(icons.PenToSquareSolid)" [title]="'edit'" (click)="editClick.emit($event)"></co-icon>
|
|
5809
|
-
|
|
5810
|
-
|
|
5811
|
-
|
|
5812
|
-
|
|
5813
|
-
|
|
5814
|
-
|
|
5815
|
-
|
|
5816
|
-
|
|
5817
|
-
|
|
5818
|
-
|
|
5819
|
-
@if (showDelete) {
|
|
5820
|
-
<co-icon [iconData]="iconsService.getIcon(icons.TrashCanSolid)" [title]="'delete'" [class.disabled]="!deleteEnabled" (click)="handleDeleteClick()"></co-icon>
|
|
5821
|
-
}
|
|
5822
|
-
</div>
|
|
5848
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: GridToolbarComponent, isStandalone: false, selector: "co-grid-toolbar", inputs: { showEdit: "showEdit", showAdd: "showAdd", showDelete: "showDelete", deleteEnabled: "deleteEnabled" }, outputs: { editClick: "editClick", cancelClick: "cancelClick", saveClick: "saveClick", addClick: "addClick", deleteClick: "deleteClick" }, host: { properties: { "class.co-grid-toolbar": "this.showClass" } }, ngImport: i0, template: `
|
|
5849
|
+
<div class="grid-toolbar-wrapper">
|
|
5850
|
+
@if (showEdit) {
|
|
5851
|
+
<co-icon [iconData]="iconsService.getIcon(icons.PenToSquareSolid)" [title]="'edit'" (click)="editClick.emit($event)"></co-icon>
|
|
5852
|
+
<co-icon [iconData]="iconsService.getIcon(icons.RotateLeftSolid)" [title]="'cancel'" (click)="cancelClick.emit()"></co-icon>
|
|
5853
|
+
<co-icon [iconData]="iconsService.getIcon(icons.FloppyDiskSolid)" [title]="'save'" (click)="saveClick.emit()"></co-icon>
|
|
5854
|
+
}
|
|
5855
|
+
@if (showAdd || showEdit) {
|
|
5856
|
+
<co-icon [iconData]="iconsService.getIcon(icons.PlusSolid)" [title]="'add'" (click)="addClick.emit()"></co-icon>
|
|
5857
|
+
}
|
|
5858
|
+
@if (showDelete) {
|
|
5859
|
+
<co-icon [iconData]="iconsService.getIcon(icons.TrashCanSolid)" [title]="'delete'" [class.disabled]="!deleteEnabled" (click)="handleDeleteClick()"></co-icon>
|
|
5860
|
+
}
|
|
5861
|
+
</div>
|
|
5823
5862
|
`, isInline: true, dependencies: [{ kind: "component", type: IconComponent, selector: "co-icon", inputs: ["icon", "iconData"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
5824
5863
|
}
|
|
5825
5864
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: GridToolbarComponent, decorators: [{
|
|
5826
5865
|
type: Component,
|
|
5827
5866
|
args: [{
|
|
5828
5867
|
selector: "co-grid-toolbar",
|
|
5829
|
-
template: `
|
|
5830
|
-
<div class="grid-toolbar-wrapper">
|
|
5831
|
-
@if (showEdit) {
|
|
5832
|
-
<co-icon [iconData]="iconsService.getIcon(icons.PenToSquareSolid)" [title]="'edit'" (click)="editClick.emit($event)"></co-icon>
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
|
|
5837
|
-
|
|
5838
|
-
|
|
5839
|
-
|
|
5840
|
-
|
|
5841
|
-
|
|
5842
|
-
|
|
5843
|
-
@if (showDelete) {
|
|
5844
|
-
<co-icon [iconData]="iconsService.getIcon(icons.TrashCanSolid)" [title]="'delete'" [class.disabled]="!deleteEnabled" (click)="handleDeleteClick()"></co-icon>
|
|
5845
|
-
}
|
|
5846
|
-
</div>
|
|
5868
|
+
template: `
|
|
5869
|
+
<div class="grid-toolbar-wrapper">
|
|
5870
|
+
@if (showEdit) {
|
|
5871
|
+
<co-icon [iconData]="iconsService.getIcon(icons.PenToSquareSolid)" [title]="'edit'" (click)="editClick.emit($event)"></co-icon>
|
|
5872
|
+
<co-icon [iconData]="iconsService.getIcon(icons.RotateLeftSolid)" [title]="'cancel'" (click)="cancelClick.emit()"></co-icon>
|
|
5873
|
+
<co-icon [iconData]="iconsService.getIcon(icons.FloppyDiskSolid)" [title]="'save'" (click)="saveClick.emit()"></co-icon>
|
|
5874
|
+
}
|
|
5875
|
+
@if (showAdd || showEdit) {
|
|
5876
|
+
<co-icon [iconData]="iconsService.getIcon(icons.PlusSolid)" [title]="'add'" (click)="addClick.emit()"></co-icon>
|
|
5877
|
+
}
|
|
5878
|
+
@if (showDelete) {
|
|
5879
|
+
<co-icon [iconData]="iconsService.getIcon(icons.TrashCanSolid)" [title]="'delete'" [class.disabled]="!deleteEnabled" (click)="handleDeleteClick()"></co-icon>
|
|
5880
|
+
}
|
|
5881
|
+
</div>
|
|
5847
5882
|
`,
|
|
5848
5883
|
encapsulation: ViewEncapsulation.None,
|
|
5849
5884
|
standalone: false
|
|
@@ -7164,10 +7199,71 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
7164
7199
|
args: ["class.co-calendar"]
|
|
7165
7200
|
}] } });
|
|
7166
7201
|
|
|
7202
|
+
/**
|
|
7203
|
+
* Resolves the locale-specific decimal separator (e.g. ',' for nl-NL) from the app-wide LOCALE_ID and
|
|
7204
|
+
* converts between a numeric model value and its user-facing display string. Injected app-wide, so no
|
|
7205
|
+
* component has to be given a locale explicitly.
|
|
7206
|
+
*
|
|
7207
|
+
* The model always stays a real number (dot-based / JSON-safe); the separator only affects the display
|
|
7208
|
+
* string shown in the input, never the stored value.
|
|
7209
|
+
*/
|
|
7210
|
+
class NumberLocaleService {
|
|
7211
|
+
_decimalSeparator;
|
|
7212
|
+
constructor(localeId) {
|
|
7213
|
+
// Intl uses the locale string directly, so this works without registerLocaleData().
|
|
7214
|
+
const parts = new Intl.NumberFormat(localeId).formatToParts(1.1);
|
|
7215
|
+
const decimalPart = parts.find((part) => part.type === 'decimal');
|
|
7216
|
+
this._decimalSeparator = decimalPart ? decimalPart.value : '.';
|
|
7217
|
+
}
|
|
7218
|
+
get decimalSeparator() {
|
|
7219
|
+
return this._decimalSeparator;
|
|
7220
|
+
}
|
|
7221
|
+
// Parses a user-typed display string to a number. Accepts both ',' and '.' as decimal separator so the
|
|
7222
|
+
// field is forgiving. Returns NaN when the text is not a parsable number.
|
|
7223
|
+
parse(text) {
|
|
7224
|
+
if (text === null || text === undefined) {
|
|
7225
|
+
return NaN;
|
|
7226
|
+
}
|
|
7227
|
+
const normalized = ('' + text).trim().replace(',', '.');
|
|
7228
|
+
if (normalized === '') {
|
|
7229
|
+
return NaN;
|
|
7230
|
+
}
|
|
7231
|
+
return Number(normalized);
|
|
7232
|
+
}
|
|
7233
|
+
// Formats a numeric model value to a display string using the locale decimal separator. Returns '' for
|
|
7234
|
+
// null/undefined/NaN. No grouping (thousands) separators are added, as this targets an editable field.
|
|
7235
|
+
format(value) {
|
|
7236
|
+
if (value === null || value === undefined || isNaN(value)) {
|
|
7237
|
+
return '';
|
|
7238
|
+
}
|
|
7239
|
+
return ('' + value).replace('.', this._decimalSeparator);
|
|
7240
|
+
}
|
|
7241
|
+
// Inserts the locale decimal separator at the input's caret and notifies Angular via an 'input' event.
|
|
7242
|
+
// Used to normalize a typed '.' to the locale separator (e.g. numpad '.' -> ',' for nl-NL).
|
|
7243
|
+
insertDecimalSeparator(input) {
|
|
7244
|
+
const start = input.selectionStart ?? input.value.length;
|
|
7245
|
+
const end = input.selectionEnd ?? input.value.length;
|
|
7246
|
+
input.value = input.value.slice(0, start) + this._decimalSeparator + input.value.slice(end);
|
|
7247
|
+
const caret = start + this._decimalSeparator.length;
|
|
7248
|
+
input.setSelectionRange(caret, caret);
|
|
7249
|
+
input.dispatchEvent(new Event('input', { bubbles: true }));
|
|
7250
|
+
}
|
|
7251
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: NumberLocaleService, deps: [{ token: LOCALE_ID }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
7252
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: NumberLocaleService, providedIn: 'root' });
|
|
7253
|
+
}
|
|
7254
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: NumberLocaleService, decorators: [{
|
|
7255
|
+
type: Injectable,
|
|
7256
|
+
args: [{ providedIn: 'root' }]
|
|
7257
|
+
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
7258
|
+
type: Inject,
|
|
7259
|
+
args: [LOCALE_ID]
|
|
7260
|
+
}] }] });
|
|
7261
|
+
|
|
7167
7262
|
class InputTextComponent extends BaseInputComponent {
|
|
7168
7263
|
formComponent;
|
|
7169
7264
|
changeDetector;
|
|
7170
7265
|
overlayService;
|
|
7266
|
+
_numberLocale;
|
|
7171
7267
|
formUserChangeListener;
|
|
7172
7268
|
ngZoneWrapper;
|
|
7173
7269
|
elementRef;
|
|
@@ -7196,6 +7292,9 @@ class InputTextComponent extends BaseInputComponent {
|
|
|
7196
7292
|
get isDate() {
|
|
7197
7293
|
return this.type === "date";
|
|
7198
7294
|
}
|
|
7295
|
+
get hasValue() {
|
|
7296
|
+
return super.hasValue || (this.placeholder !== '' && this.placeholder !== null && this.placeholder !== undefined);
|
|
7297
|
+
}
|
|
7199
7298
|
leftIconClick = new EventEmitter();
|
|
7200
7299
|
leftIconMouseDown = new EventEmitter();
|
|
7201
7300
|
leftIconMouseUp = new EventEmitter();
|
|
@@ -7240,6 +7339,26 @@ class InputTextComponent extends BaseInputComponent {
|
|
|
7240
7339
|
get model() {
|
|
7241
7340
|
return super.model;
|
|
7242
7341
|
}
|
|
7342
|
+
// keep the display string in sync when the model changes from outside typing (init / programmatic)
|
|
7343
|
+
modelSet() {
|
|
7344
|
+
if (this.digitsOnly && !this._userTyping) {
|
|
7345
|
+
this._displayValue = this._numberLocale.format(this.model);
|
|
7346
|
+
}
|
|
7347
|
+
}
|
|
7348
|
+
// For digitsOnly the input is a text field showing a locale-formatted string; parse it back to a number
|
|
7349
|
+
// before emitting so the model (and thus what is stored) stays numeric. Other types emit the raw value.
|
|
7350
|
+
handleInputModelChange(value) {
|
|
7351
|
+
if (this.digitsOnly) {
|
|
7352
|
+
this._userTyping = true;
|
|
7353
|
+
this._displayValue = value === null || value === undefined ? '' : '' + value;
|
|
7354
|
+
const parsed = this._numberLocale.parse(value);
|
|
7355
|
+
this.modelChange.emit(isNaN(parsed) ? null : parsed);
|
|
7356
|
+
this._userTyping = false;
|
|
7357
|
+
}
|
|
7358
|
+
else {
|
|
7359
|
+
this.modelChange.emit(value);
|
|
7360
|
+
}
|
|
7361
|
+
}
|
|
7243
7362
|
get pipedModel() {
|
|
7244
7363
|
if (this.formatPipe) {
|
|
7245
7364
|
try {
|
|
@@ -7251,21 +7370,37 @@ class InputTextComponent extends BaseInputComponent {
|
|
|
7251
7370
|
}
|
|
7252
7371
|
return this.model;
|
|
7253
7372
|
}
|
|
7373
|
+
// Locale-formatted string bound to the input when digitsOnly (comma for nl-NL); the model stays numeric.
|
|
7374
|
+
get displayValue() {
|
|
7375
|
+
return this._displayValue;
|
|
7376
|
+
}
|
|
7254
7377
|
isFocusedOnDate = false;
|
|
7255
7378
|
weekInputBuffer = '';
|
|
7256
7379
|
isWeekInputMode = false;
|
|
7257
7380
|
_isLeftIconMouseDown = false;
|
|
7258
7381
|
_isRightIconMouseDown = false;
|
|
7259
|
-
|
|
7382
|
+
_userTyping = false;
|
|
7383
|
+
_displayValue = '';
|
|
7384
|
+
constructor(formComponent, changeDetector, overlayService, _numberLocale, formUserChangeListener, ngZoneWrapper, elementRef) {
|
|
7260
7385
|
super(changeDetector, overlayService, formUserChangeListener, ngZoneWrapper, elementRef);
|
|
7261
7386
|
this.formComponent = formComponent;
|
|
7262
7387
|
this.changeDetector = changeDetector;
|
|
7263
7388
|
this.overlayService = overlayService;
|
|
7389
|
+
this._numberLocale = _numberLocale;
|
|
7264
7390
|
this.formUserChangeListener = formUserChangeListener;
|
|
7265
7391
|
this.ngZoneWrapper = ngZoneWrapper;
|
|
7266
7392
|
this.elementRef = elementRef;
|
|
7267
7393
|
super._markAsOnPush();
|
|
7268
7394
|
}
|
|
7395
|
+
ngAfterViewInit() {
|
|
7396
|
+
// label was not correctly being used, so this is a legacy issue fix
|
|
7397
|
+
// if you want to use a placeholder (as a placeholder is meant to be used) then you need to set the label as well
|
|
7398
|
+
if (!this.label) {
|
|
7399
|
+
this.label = this.placeholder;
|
|
7400
|
+
this.placeholder = '';
|
|
7401
|
+
}
|
|
7402
|
+
super.ngAfterViewInit();
|
|
7403
|
+
}
|
|
7269
7404
|
handleLeftIconClick(event) {
|
|
7270
7405
|
event.preventDefault();
|
|
7271
7406
|
event.stopPropagation();
|
|
@@ -7331,6 +7466,10 @@ class InputTextComponent extends BaseInputComponent {
|
|
|
7331
7466
|
if (this.type === 'date') {
|
|
7332
7467
|
this.isFocusedOnDate = false;
|
|
7333
7468
|
}
|
|
7469
|
+
if (this.digitsOnly) {
|
|
7470
|
+
// normalize the display once editing stops (e.g. "12," -> "12")
|
|
7471
|
+
this._displayValue = this._numberLocale.format(this.model);
|
|
7472
|
+
}
|
|
7334
7473
|
this.isFocused.emit(false);
|
|
7335
7474
|
}
|
|
7336
7475
|
handleDoFocus(event) {
|
|
@@ -7338,10 +7477,17 @@ class InputTextComponent extends BaseInputComponent {
|
|
|
7338
7477
|
this.doFocus(event);
|
|
7339
7478
|
}
|
|
7340
7479
|
}
|
|
7480
|
+
// For digitsOnly the field is a text input and precision/scale is enforced in keydown; the native
|
|
7481
|
+
// maxlength would wrongly count the decimal separator as a character. Plain text keeps native maxlength.
|
|
7482
|
+
_setNativeMaxLength(maxlength) {
|
|
7483
|
+
if (this.digitsOnly) {
|
|
7484
|
+
return;
|
|
7485
|
+
}
|
|
7486
|
+
super._setNativeMaxLength(maxlength);
|
|
7487
|
+
}
|
|
7341
7488
|
clearInput(event) {
|
|
7342
7489
|
this.setModel(null);
|
|
7343
7490
|
this.keepFocus = true;
|
|
7344
|
-
this.shouldCommit = false;
|
|
7345
7491
|
this.clearIconClick.emit(event);
|
|
7346
7492
|
}
|
|
7347
7493
|
handleKeyDownInput(event) {
|
|
@@ -7377,16 +7523,39 @@ class InputTextComponent extends BaseInputComponent {
|
|
|
7377
7523
|
}
|
|
7378
7524
|
}
|
|
7379
7525
|
if (this.digitsOnly && !this.isWeekInputMode) {
|
|
7380
|
-
|
|
7381
|
-
if (
|
|
7382
|
-
event.
|
|
7526
|
+
// the field is a text input (so a locale comma is allowed), so actively permit only numeric characters
|
|
7527
|
+
if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) {
|
|
7528
|
+
const isDigit = /\d/.test(event.key);
|
|
7529
|
+
const isSeparator = event.key === '.' || event.key === ',';
|
|
7530
|
+
const isSign = !this.excludePlusMinus && (event.key === '-' || event.key === '+');
|
|
7531
|
+
if (!isDigit && !isSeparator && !isSign) {
|
|
7532
|
+
event.preventDefault();
|
|
7533
|
+
return;
|
|
7534
|
+
}
|
|
7535
|
+
if (isSeparator) {
|
|
7536
|
+
// only one decimal separator, and only the locale one: normalize a foreign '.'/',' to it
|
|
7537
|
+
if (/[.,]/.test(this.input?.value ?? '')) {
|
|
7538
|
+
event.preventDefault();
|
|
7539
|
+
return;
|
|
7540
|
+
}
|
|
7541
|
+
if (event.key !== this._numberLocale.decimalSeparator) {
|
|
7542
|
+
event.preventDefault();
|
|
7543
|
+
if (this.input) {
|
|
7544
|
+
this._numberLocale.insertDecimalSeparator(this.input);
|
|
7545
|
+
}
|
|
7546
|
+
return;
|
|
7547
|
+
}
|
|
7548
|
+
}
|
|
7383
7549
|
}
|
|
7384
7550
|
}
|
|
7385
|
-
|
|
7386
|
-
|
|
7387
|
-
|
|
7388
|
-
|
|
7389
|
-
|
|
7551
|
+
// Native <input> ignores maxlength on numeric inputs, so enforce maxLength (as precision) and
|
|
7552
|
+
// decimals (as scale) ourselves for digit keys. Non-numeric text inputs keep the native maxlength.
|
|
7553
|
+
// Read the live element value (not this.model): a numeric input reports "" for an in-progress value
|
|
7554
|
+
// like "1234567.", so this.model would still hold "1234567" and wrongly block the first decimal digit.
|
|
7555
|
+
const currentText = this.input ? this.input.value : String(this.model ?? "");
|
|
7556
|
+
if ((this.digitsOnly || this.type === "number") &&
|
|
7557
|
+
/^\d$/.test(key) &&
|
|
7558
|
+
NumberUtils.WouldExceedDigitLimits(currentText, this.maxLength, this.decimals)) {
|
|
7390
7559
|
event.preventDefault();
|
|
7391
7560
|
}
|
|
7392
7561
|
}
|
|
@@ -7436,7 +7605,7 @@ class InputTextComponent extends BaseInputComponent {
|
|
|
7436
7605
|
const day = String(date.getDate()).padStart(2, '0');
|
|
7437
7606
|
return `${year}-${month}-${day}`;
|
|
7438
7607
|
}
|
|
7439
|
-
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 });
|
|
7608
|
+
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: NumberLocaleService }, { token: FormInputUserModelChangeListenerService }, { token: NgZoneWrapperService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
7440
7609
|
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: [
|
|
7441
7610
|
OverlayService, {
|
|
7442
7611
|
provide: SCREEN_CONFIG_ADAPTER_COMPONENT_INTERFACE_NAME,
|
|
@@ -7458,7 +7627,7 @@ class InputTextComponent extends BaseInputComponent {
|
|
|
7458
7627
|
<div class="input-wrapper">
|
|
7459
7628
|
@if (showPlaceholderOnFocus || (!showPlaceholderOnFocus && !hasValue && !focused)) {
|
|
7460
7629
|
<label
|
|
7461
|
-
[textContent]="
|
|
7630
|
+
[textContent]="label"></label>
|
|
7462
7631
|
}
|
|
7463
7632
|
@if (!focused && !useContent && formatPipe) {
|
|
7464
7633
|
<span class="input-text-formatted"
|
|
@@ -7471,15 +7640,16 @@ class InputTextComponent extends BaseInputComponent {
|
|
|
7471
7640
|
<input [class.show]="focused || !formatPipe" #input
|
|
7472
7641
|
[class.input-input-hidden]="useContent"
|
|
7473
7642
|
[ngClass]="align"
|
|
7474
|
-
[type]="isWeekInputMode ? 'text' : (isFocusedOnDate || (hasValue && emptyPlace)) ? 'date' : (digitsOnly ? '
|
|
7475
|
-
[
|
|
7643
|
+
[type]="isWeekInputMode ? 'text' : (isFocusedOnDate || (hasValue && emptyPlace)) ? 'date' : (digitsOnly ? 'text' : (type === 'date' ? 'text' : type))"
|
|
7644
|
+
[attr.inputmode]="digitsOnly ? 'decimal' : null"
|
|
7645
|
+
[placeholder]="type === 'date' && !isFocusedOnDate ? '' : placeholder"
|
|
7476
7646
|
[pattern]="type === 'date' ? pattern : undefined"
|
|
7477
|
-
[ngModel]="model"
|
|
7647
|
+
[ngModel]="digitsOnly ? displayValue : model"
|
|
7478
7648
|
[min]="(type === 'number' || type === 'date') && this.min ? this.min : undefined"
|
|
7479
7649
|
[max]="(type === 'number' || type === 'date') && this.max ? this.max : undefined"
|
|
7480
7650
|
[readonly]="readonly"
|
|
7481
7651
|
[required]="required"
|
|
7482
|
-
(ngModelChange)="
|
|
7652
|
+
(ngModelChange)="handleInputModelChange($event)"
|
|
7483
7653
|
(keydown)="handleKeyDownInput($event)"
|
|
7484
7654
|
(keyup)="keyUp.emit($event)"
|
|
7485
7655
|
(focusin)="handleInputFocus($event)"
|
|
@@ -7534,7 +7704,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
7534
7704
|
<div class="input-wrapper">
|
|
7535
7705
|
@if (showPlaceholderOnFocus || (!showPlaceholderOnFocus && !hasValue && !focused)) {
|
|
7536
7706
|
<label
|
|
7537
|
-
[textContent]="
|
|
7707
|
+
[textContent]="label"></label>
|
|
7538
7708
|
}
|
|
7539
7709
|
@if (!focused && !useContent && formatPipe) {
|
|
7540
7710
|
<span class="input-text-formatted"
|
|
@@ -7547,15 +7717,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
7547
7717
|
<input [class.show]="focused || !formatPipe" #input
|
|
7548
7718
|
[class.input-input-hidden]="useContent"
|
|
7549
7719
|
[ngClass]="align"
|
|
7550
|
-
[type]="isWeekInputMode ? 'text' : (isFocusedOnDate || (hasValue && emptyPlace)) ? 'date' : (digitsOnly ? '
|
|
7551
|
-
[
|
|
7720
|
+
[type]="isWeekInputMode ? 'text' : (isFocusedOnDate || (hasValue && emptyPlace)) ? 'date' : (digitsOnly ? 'text' : (type === 'date' ? 'text' : type))"
|
|
7721
|
+
[attr.inputmode]="digitsOnly ? 'decimal' : null"
|
|
7722
|
+
[placeholder]="type === 'date' && !isFocusedOnDate ? '' : placeholder"
|
|
7552
7723
|
[pattern]="type === 'date' ? pattern : undefined"
|
|
7553
|
-
[ngModel]="model"
|
|
7724
|
+
[ngModel]="digitsOnly ? displayValue : model"
|
|
7554
7725
|
[min]="(type === 'number' || type === 'date') && this.min ? this.min : undefined"
|
|
7555
7726
|
[max]="(type === 'number' || type === 'date') && this.max ? this.max : undefined"
|
|
7556
7727
|
[readonly]="readonly"
|
|
7557
7728
|
[required]="required"
|
|
7558
|
-
(ngModelChange)="
|
|
7729
|
+
(ngModelChange)="handleInputModelChange($event)"
|
|
7559
7730
|
(keydown)="handleKeyDownInput($event)"
|
|
7560
7731
|
(keyup)="keyUp.emit($event)"
|
|
7561
7732
|
(focusin)="handleInputFocus($event)"
|
|
@@ -7606,7 +7777,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
7606
7777
|
}]
|
|
7607
7778
|
}], ctorParameters: () => [{ type: FormComponent, decorators: [{
|
|
7608
7779
|
type: Optional
|
|
7609
|
-
}] }, { type: i0.ChangeDetectorRef }, { type: OverlayService }, { type: FormInputUserModelChangeListenerService }, { type: NgZoneWrapperService }, { type: i0.ElementRef }], propDecorators: { useContent: [{
|
|
7780
|
+
}] }, { type: i0.ChangeDetectorRef }, { type: OverlayService }, { type: NumberLocaleService }, { type: FormInputUserModelChangeListenerService }, { type: NgZoneWrapperService }, { type: i0.ElementRef }], propDecorators: { useContent: [{
|
|
7610
7781
|
type: Input
|
|
7611
7782
|
}], placeholder: [{
|
|
7612
7783
|
type: Input
|
|
@@ -9035,16 +9206,25 @@ class InputNumberPickerComponent extends BaseInputComponent {
|
|
|
9035
9206
|
iconCacheService;
|
|
9036
9207
|
overlayService;
|
|
9037
9208
|
_ngZone;
|
|
9209
|
+
_numberLocale;
|
|
9038
9210
|
ngZoneWrapper;
|
|
9039
9211
|
elementRef;
|
|
9040
9212
|
// @override
|
|
9041
9213
|
set model(model) {
|
|
9042
9214
|
this.setValue(model, true);
|
|
9043
9215
|
super.model = model;
|
|
9216
|
+
// keep the display string in sync, unless the user is mid-typing (then their raw text is preserved)
|
|
9217
|
+
if (!this._userTyping) {
|
|
9218
|
+
this._displayValue = this._numberLocale.format(model);
|
|
9219
|
+
}
|
|
9044
9220
|
}
|
|
9045
9221
|
get model() {
|
|
9046
9222
|
return super.model;
|
|
9047
9223
|
}
|
|
9224
|
+
// Locale-formatted string bound to the native text input (comma for nl-NL); the model stays numeric.
|
|
9225
|
+
get displayValue() {
|
|
9226
|
+
return this._displayValue;
|
|
9227
|
+
}
|
|
9048
9228
|
modelChangeOnEnter = true;
|
|
9049
9229
|
showPermanentLabel = false;
|
|
9050
9230
|
leftIconData;
|
|
@@ -9065,8 +9245,14 @@ class InputNumberPickerComponent extends BaseInputComponent {
|
|
|
9065
9245
|
// @override Default true for us.
|
|
9066
9246
|
noValidation = true;
|
|
9067
9247
|
set decimals(decimals) {
|
|
9248
|
+
// Also store on the base so its precision/scale validator picks it up; a setter-only override
|
|
9249
|
+
// would otherwise shadow the inherited getter and make this.decimals read as undefined.
|
|
9250
|
+
super.decimals = decimals;
|
|
9068
9251
|
this.numberLogic.decimals = decimals;
|
|
9069
9252
|
}
|
|
9253
|
+
get decimals() {
|
|
9254
|
+
return super.decimals;
|
|
9255
|
+
}
|
|
9070
9256
|
// @override
|
|
9071
9257
|
modelChange = new EventEmitter();
|
|
9072
9258
|
iconClick = new EventEmitter();
|
|
@@ -9086,6 +9272,8 @@ class InputNumberPickerComponent extends BaseInputComponent {
|
|
|
9086
9272
|
plusSelected = false;
|
|
9087
9273
|
_numberInputHasFocus = false;
|
|
9088
9274
|
_changeFromButton = false;
|
|
9275
|
+
_userTyping = false;
|
|
9276
|
+
_displayValue = '';
|
|
9089
9277
|
_numberLogicValueChangeSub;
|
|
9090
9278
|
_delayBeforeStartAutoCountMs = 666;
|
|
9091
9279
|
// the 'speed gears' for auto counting
|
|
@@ -9100,12 +9288,13 @@ class InputNumberPickerComponent extends BaseInputComponent {
|
|
|
9100
9288
|
_autoCountTimeout;
|
|
9101
9289
|
_stepIncrementTimeout;
|
|
9102
9290
|
_startAutocountTimeout;
|
|
9103
|
-
constructor(formComponent, iconCacheService, overlayService, _ngZone, changeDetector, formUserChangeListener, ngZoneWrapper, elementRef) {
|
|
9291
|
+
constructor(formComponent, iconCacheService, overlayService, _ngZone, changeDetector, formUserChangeListener, _numberLocale, ngZoneWrapper, elementRef) {
|
|
9104
9292
|
super(changeDetector, overlayService, formUserChangeListener, ngZoneWrapper, elementRef);
|
|
9105
9293
|
this.formComponent = formComponent;
|
|
9106
9294
|
this.iconCacheService = iconCacheService;
|
|
9107
9295
|
this.overlayService = overlayService;
|
|
9108
9296
|
this._ngZone = _ngZone;
|
|
9297
|
+
this._numberLocale = _numberLocale;
|
|
9109
9298
|
this.ngZoneWrapper = ngZoneWrapper;
|
|
9110
9299
|
this.elementRef = elementRef;
|
|
9111
9300
|
this._numberLogicValueChangeSub = this.numberLogic.valueChange.subscribe((value) => {
|
|
@@ -9155,13 +9344,40 @@ class InputNumberPickerComponent extends BaseInputComponent {
|
|
|
9155
9344
|
if (this.myKeyDownWhiteList.find((k) => k === event.keyCode) === undefined) {
|
|
9156
9345
|
return false;
|
|
9157
9346
|
}
|
|
9347
|
+
const currentText = this.input ? this.input.value : String(this.model ?? '');
|
|
9348
|
+
if (event.key === '.' || event.key === ',') {
|
|
9349
|
+
// only one decimal separator, and only the locale one: normalize a foreign '.'/',' to it
|
|
9350
|
+
if (/[.,]/.test(currentText)) {
|
|
9351
|
+
return false;
|
|
9352
|
+
}
|
|
9353
|
+
if (event.key !== this._numberLocale.decimalSeparator) {
|
|
9354
|
+
if (this.input) {
|
|
9355
|
+
this._numberLocale.insertDecimalSeparator(this.input);
|
|
9356
|
+
}
|
|
9357
|
+
return false;
|
|
9358
|
+
}
|
|
9359
|
+
}
|
|
9360
|
+
// native text/number inputs ignore maxlength, so enforce maxLength (precision) and decimals (scale) here
|
|
9361
|
+
if (/^\d$/.test(event.key) && NumberUtils.WouldExceedDigitLimits(currentText, this.maxLength, this.decimals)) {
|
|
9362
|
+
return false;
|
|
9363
|
+
}
|
|
9364
|
+
}
|
|
9365
|
+
// precision/scale is enforced in keydown; the native maxlength on this text input would wrongly count
|
|
9366
|
+
// the decimal separator as a character (e.g. blocking "1234567,89" at maxLength 9), so don't set it.
|
|
9367
|
+
_setNativeMaxLength() {
|
|
9158
9368
|
}
|
|
9159
9369
|
handleBlur() {
|
|
9370
|
+
// normalize the display once editing stops (e.g. "12," -> "12", trailing zeros dropped)
|
|
9371
|
+
this._displayValue = this._numberLocale.format(this.model);
|
|
9160
9372
|
this.modelChange.next(this.model);
|
|
9161
9373
|
}
|
|
9162
|
-
handleChangeModel(
|
|
9374
|
+
handleChangeModel(text) {
|
|
9163
9375
|
this._changeFromButton = false;
|
|
9164
|
-
|
|
9376
|
+
// preserve exactly what the user typed while they are typing (avoids caret jumps / eating the separator)
|
|
9377
|
+
this._userTyping = true;
|
|
9378
|
+
this._displayValue = text === null || text === undefined ? '' : '' + text;
|
|
9379
|
+
this.numberLogic.setValue(this._numberLocale.parse(text));
|
|
9380
|
+
this._userTyping = false;
|
|
9165
9381
|
}
|
|
9166
9382
|
// Note: recursive through setTimeout().
|
|
9167
9383
|
doDecrementAuto() {
|
|
@@ -9263,7 +9479,7 @@ class InputNumberPickerComponent extends BaseInputComponent {
|
|
|
9263
9479
|
break;
|
|
9264
9480
|
}
|
|
9265
9481
|
}
|
|
9266
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: InputNumberPickerComponent, deps: [{ token: FormComponent, optional: true }, { token: IconCacheService }, { token: OverlayService }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }, { token: FormInputUserModelChangeListenerService }, { token: NgZoneWrapperService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
9482
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: InputNumberPickerComponent, deps: [{ token: FormComponent, optional: true }, { token: IconCacheService }, { token: OverlayService }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }, { token: FormInputUserModelChangeListenerService }, { token: NumberLocaleService }, { token: NgZoneWrapperService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
9267
9483
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: InputNumberPickerComponent, isStandalone: false, selector: "co-input-number-picker", inputs: { model: "model", modelChangeOnEnter: "modelChangeOnEnter", showPermanentLabel: "showPermanentLabel", leftIconData: "leftIconData", min: "min", step: "step", max: "max", ngModelOptions: "ngModelOptions", minusIcon: "minusIcon", plusIcon: "plusIcon", buttonShowMode: "buttonShowMode", noValidation: "noValidation", decimals: "decimals" }, outputs: { modelChange: "modelChange", iconClick: "iconClick" }, host: { properties: { "class.has-icon": "this.leftIconData", "class.show-buttons-on-focus-only": "this.showButtonsOnFocusOnly", "class.has-label": "this.hasLabel", "class.co-input-number-picker": "this.showClass" } }, providers: [
|
|
9268
9484
|
OverlayService, {
|
|
9269
9485
|
provide: SCREEN_CONFIG_ADAPTER_COMPONENT_INTERFACE_NAME, useExisting: forwardRef(() => InputNumberPickerComponent)
|
|
@@ -9289,15 +9505,15 @@ class InputNumberPickerComponent extends BaseInputComponent {
|
|
|
9289
9505
|
</div>
|
|
9290
9506
|
<div class="input-wrapper">
|
|
9291
9507
|
@if (showPermanentLabel) {
|
|
9292
|
-
<span class='permanent-label' [textContent]="label"></span>
|
|
9508
|
+
<span class='permanent-label' [textContent]="label ?? ''"></span>
|
|
9293
9509
|
}
|
|
9294
|
-
<input type="
|
|
9510
|
+
<input type="text" inputmode="decimal"
|
|
9295
9511
|
[tabIndex]="readonly ? -1 : 0"
|
|
9296
|
-
[ngModel]="
|
|
9512
|
+
[ngModel]="displayValue"
|
|
9297
9513
|
[readonly]="readonly"
|
|
9298
9514
|
[disabled]="disabled"
|
|
9299
9515
|
[required]="required"
|
|
9300
|
-
[placeholder]="label"
|
|
9516
|
+
[placeholder]="label ?? ''"
|
|
9301
9517
|
(ngModelChange)="handleChangeModel($event)"
|
|
9302
9518
|
(keydown)="handleInputKeyDown($event)"
|
|
9303
9519
|
(blur)="handleBlur()"/>
|
|
@@ -9311,7 +9527,7 @@ class InputNumberPickerComponent extends BaseInputComponent {
|
|
|
9311
9527
|
(mouseup)="stopAutoCounting()" (mouseleave)="stopAutoCounting()"></co-button>
|
|
9312
9528
|
}
|
|
9313
9529
|
</div>
|
|
9314
|
-
`, isInline: true, dependencies: [{ kind: "directive", type: i5.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: i5.
|
|
9530
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: i5.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: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ButtonComponent, selector: "co-button", inputs: ["label", "iconData", "iconDataRight", "isToggleButton", "isToggled", "hidden", "disabled"], outputs: ["onClick", "clickedWhileDisabled", "isToggledChange"] }, { kind: "component", type: IconComponent, selector: "co-icon", inputs: ["icon", "iconData"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
9315
9531
|
}
|
|
9316
9532
|
__decorate([
|
|
9317
9533
|
InputBoolean()
|
|
@@ -9338,15 +9554,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
9338
9554
|
</div>
|
|
9339
9555
|
<div class="input-wrapper">
|
|
9340
9556
|
@if (showPermanentLabel) {
|
|
9341
|
-
<span class='permanent-label' [textContent]="label"></span>
|
|
9557
|
+
<span class='permanent-label' [textContent]="label ?? ''"></span>
|
|
9342
9558
|
}
|
|
9343
|
-
<input type="
|
|
9559
|
+
<input type="text" inputmode="decimal"
|
|
9344
9560
|
[tabIndex]="readonly ? -1 : 0"
|
|
9345
|
-
[ngModel]="
|
|
9561
|
+
[ngModel]="displayValue"
|
|
9346
9562
|
[readonly]="readonly"
|
|
9347
9563
|
[disabled]="disabled"
|
|
9348
9564
|
[required]="required"
|
|
9349
|
-
[placeholder]="label"
|
|
9565
|
+
[placeholder]="label ?? ''"
|
|
9350
9566
|
(ngModelChange)="handleChangeModel($event)"
|
|
9351
9567
|
(keydown)="handleInputKeyDown($event)"
|
|
9352
9568
|
(blur)="handleBlur()"/>
|
|
@@ -9378,7 +9594,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
9378
9594
|
}] }, { type: IconCacheService, decorators: [{
|
|
9379
9595
|
type: Inject,
|
|
9380
9596
|
args: [IconCacheService]
|
|
9381
|
-
}] }, { type: OverlayService }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: FormInputUserModelChangeListenerService }, { type: NgZoneWrapperService }, { type: i0.ElementRef }], propDecorators: { model: [{
|
|
9597
|
+
}] }, { type: OverlayService }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: FormInputUserModelChangeListenerService }, { type: NumberLocaleService }, { type: NgZoneWrapperService }, { type: i0.ElementRef }], propDecorators: { model: [{
|
|
9382
9598
|
type: Input
|
|
9383
9599
|
}], modelChangeOnEnter: [{
|
|
9384
9600
|
type: Input
|
|
@@ -13527,6 +13743,46 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
13527
13743
|
}]
|
|
13528
13744
|
}] });
|
|
13529
13745
|
|
|
13746
|
+
class LovUtils {
|
|
13747
|
+
static getDisplayValue(model, displayField) {
|
|
13748
|
+
if (!model || !displayField) {
|
|
13749
|
+
return '';
|
|
13750
|
+
}
|
|
13751
|
+
return displayField
|
|
13752
|
+
.split('|')
|
|
13753
|
+
.map(field => model[field.trim()])
|
|
13754
|
+
.filter(val => val != null && val !== '')
|
|
13755
|
+
.join(' - ');
|
|
13756
|
+
}
|
|
13757
|
+
static getHighlightParts(value, term) {
|
|
13758
|
+
const text = value ?? '';
|
|
13759
|
+
if (!text || !term) {
|
|
13760
|
+
return [{ text: text, match: false }];
|
|
13761
|
+
}
|
|
13762
|
+
const regex = new RegExp(LovUtils._escapeRegExp(term), 'gi');
|
|
13763
|
+
const parts = [];
|
|
13764
|
+
let lastIndex = 0;
|
|
13765
|
+
let match;
|
|
13766
|
+
while ((match = regex.exec(text)) !== null) {
|
|
13767
|
+
if (match.index > lastIndex) {
|
|
13768
|
+
parts.push({ text: text.slice(lastIndex, match.index), match: false });
|
|
13769
|
+
}
|
|
13770
|
+
parts.push({ text: match[0], match: true });
|
|
13771
|
+
lastIndex = match.index + match[0].length;
|
|
13772
|
+
if (match.index === regex.lastIndex) {
|
|
13773
|
+
regex.lastIndex++;
|
|
13774
|
+
}
|
|
13775
|
+
}
|
|
13776
|
+
if (lastIndex < text.length) {
|
|
13777
|
+
parts.push({ text: text.slice(lastIndex), match: false });
|
|
13778
|
+
}
|
|
13779
|
+
return parts;
|
|
13780
|
+
}
|
|
13781
|
+
static _escapeRegExp(value) {
|
|
13782
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
13783
|
+
}
|
|
13784
|
+
}
|
|
13785
|
+
|
|
13530
13786
|
class ListOfValuesPopupComponent {
|
|
13531
13787
|
iconCacheService;
|
|
13532
13788
|
_elementRef;
|
|
@@ -13647,7 +13903,11 @@ class ListOfValuesPopupComponent {
|
|
|
13647
13903
|
}
|
|
13648
13904
|
}
|
|
13649
13905
|
selectModelByViewModel(viewModel, closePopup = true) {
|
|
13650
|
-
|
|
13906
|
+
const found = this.viewModelsMain.find(vm => vm === viewModel);
|
|
13907
|
+
if (!found) {
|
|
13908
|
+
return;
|
|
13909
|
+
}
|
|
13910
|
+
this.model = found.model;
|
|
13651
13911
|
this.modelChange.emit(this.model);
|
|
13652
13912
|
this._scrollIntoView();
|
|
13653
13913
|
if (closePopup) {
|
|
@@ -13660,7 +13920,7 @@ class ListOfValuesPopupComponent {
|
|
|
13660
13920
|
this.selectNextOption();
|
|
13661
13921
|
}
|
|
13662
13922
|
if (!this.model && this.searchTerm) {
|
|
13663
|
-
const wishModel = this.viewModelsMain.find(vmm => vmm.model
|
|
13923
|
+
const wishModel = this.viewModelsMain.find(vmm => LovUtils.getDisplayValue(vmm.model, this.displayField) === this.searchTerm);
|
|
13664
13924
|
if (wishModel) {
|
|
13665
13925
|
this.selectViewModel(wishModel);
|
|
13666
13926
|
}
|
|
@@ -13680,6 +13940,9 @@ class ListOfValuesPopupComponent {
|
|
|
13680
13940
|
this.modelChange.emit(this.model);
|
|
13681
13941
|
}
|
|
13682
13942
|
selectNextOption(back = false) {
|
|
13943
|
+
if (this.viewModels.length === 0) {
|
|
13944
|
+
return;
|
|
13945
|
+
}
|
|
13683
13946
|
let nextModel;
|
|
13684
13947
|
if (!this.highLightModel) {
|
|
13685
13948
|
nextModel = this.viewModels[back ? this.viewModels.length - 1 : 0];
|
|
@@ -13733,8 +13996,8 @@ class ListOfValuesPopupComponent {
|
|
|
13733
13996
|
}
|
|
13734
13997
|
if (!this.model)
|
|
13735
13998
|
return false;
|
|
13736
|
-
const selected = this.model
|
|
13737
|
-
const current = vm.model
|
|
13999
|
+
const selected = LovUtils.getDisplayValue(this.model, this.displayField);
|
|
14000
|
+
const current = LovUtils.getDisplayValue(vm.model, this.displayField);
|
|
13738
14001
|
return selected != null && current != null && selected === current;
|
|
13739
14002
|
}
|
|
13740
14003
|
_prepareViewModelsMain() {
|
|
@@ -13755,6 +14018,9 @@ class ListOfValuesPopupComponent {
|
|
|
13755
14018
|
}
|
|
13756
14019
|
});
|
|
13757
14020
|
});
|
|
14021
|
+
this.viewModels.forEach((vm) => {
|
|
14022
|
+
vm.highlightParts = LovUtils.getHighlightParts(LovUtils.getDisplayValue(vm.model, this.displayField), this.searchTerm);
|
|
14023
|
+
});
|
|
13758
14024
|
}
|
|
13759
14025
|
_scrollIntoView() {
|
|
13760
14026
|
const activeIndex = this.viewModels.findIndex(vmm => vmm === this.highLightModel);
|
|
@@ -13783,102 +14049,126 @@ class ListOfValuesPopupComponent {
|
|
|
13783
14049
|
}
|
|
13784
14050
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ListOfValuesPopupComponent, deps: [{ token: IconCacheService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
13785
14051
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: ListOfValuesPopupComponent, isStandalone: false, selector: "co-list-of-values-popup", inputs: { model: "model", multiselect: "multiselect", showToggleAll: "showToggleAll", displayField: "displayField", searchPlaceholder: "searchPlaceholder", customCssClass: "customCssClass", searchDisabled: "searchDisabled", parentForOverlay: "parentForOverlay", optionIcon: "optionIcon", collection: "collection" }, outputs: { modelChange: "modelChange", closePopup: "closePopup", keyDown: "keyDown" }, host: { properties: { "class.co-list-of-values-popup": "this.showClass", "class.lov-anim": "this.animBase", "class.lov-anim--open": "this.isOpen" } }, viewQueries: [{ propertyName: "dropDownList", first: true, predicate: ["dropDownList"], descendants: true, read: ElementRef }, { propertyName: "inputSearch", first: true, predicate: InputSearchComponent, descendants: true }, { propertyName: "lovItems", predicate: ["lovItem"], descendants: true, read: ElementRef }], ngImport: i0, template: `
|
|
13786
|
-
|
|
13787
|
-
|
|
13788
|
-
|
|
13789
|
-
|
|
13790
|
-
|
|
13791
|
-
|
|
13792
|
-
|
|
13793
|
-
|
|
13794
|
-
|
|
13795
|
-
|
|
13796
|
-
|
|
13797
|
-
|
|
13798
|
-
|
|
13799
|
-
|
|
13800
|
-
|
|
13801
|
-
|
|
13802
|
-
|
|
13803
|
-
|
|
13804
|
-
|
|
13805
|
-
|
|
13806
|
-
|
|
13807
|
-
|
|
13808
|
-
|
|
13809
|
-
|
|
13810
|
-
|
|
13811
|
-
|
|
13812
|
-
|
|
13813
|
-
|
|
13814
|
-
|
|
13815
|
-
|
|
13816
|
-
|
|
13817
|
-
|
|
14052
|
+
<div class="lov-options" [overlay]="parentForOverlay" [inheritWidth]="true" [ngClass]="customCssClass"
|
|
14053
|
+
id="lov-popup"
|
|
14054
|
+
role="listbox" [tabindex]="-1"
|
|
14055
|
+
(clickOutside)="closePopup.emit($event)">
|
|
14056
|
+
@if (multiselect) {
|
|
14057
|
+
<co-input-search
|
|
14058
|
+
tabindex="-1"
|
|
14059
|
+
[(model)]="searchTerm"
|
|
14060
|
+
[placeholder]="searchPlaceholder"
|
|
14061
|
+
(keydown)="handleInputKeyDown($event)"
|
|
14062
|
+
(modelChange)="filterViewModels()"></co-input-search>
|
|
14063
|
+
}
|
|
14064
|
+
@if (showToggleAll && multiselect) {
|
|
14065
|
+
<div class="row gap">
|
|
14066
|
+
<co-input-checkbox [model]="allSelected" (modelChange)="toggleAll()"></co-input-checkbox>
|
|
14067
|
+
<span [textContent]="'DESELECT_ALL' | coreLocalize" (click)="toggleAll()"></span>
|
|
14068
|
+
</div>
|
|
14069
|
+
}
|
|
14070
|
+
<ul class="dropdown-list" #dropDownList>
|
|
14071
|
+
@for (viewModel of viewModels; track viewModel; let index = $index) {
|
|
14072
|
+
<li
|
|
14073
|
+
#lovItem
|
|
14074
|
+
[class.selected]="viewModel === highLightModel || viewModels.length === 1"
|
|
14075
|
+
[class.active]="isActive(viewModel)"
|
|
14076
|
+
[class.highlighted]="viewModel === highLightModel"
|
|
14077
|
+
[attr.aria-selected]="isActive(viewModel)"
|
|
14078
|
+
(click)="selectViewModel(viewModel, !multiselect)"
|
|
14079
|
+
role="option">
|
|
14080
|
+
@if (!multiselect) {
|
|
14081
|
+
@if (viewModel.model[optionIcon]) {
|
|
14082
|
+
<co-icon class="input-text-left-icon" [iconData]="iconCacheService.getIcon(viewModel.model[optionIcon])">
|
|
14083
|
+
</co-icon>
|
|
14084
|
+
}
|
|
14085
|
+
<ng-container [ngTemplateOutlet]="optionText" [ngTemplateOutletContext]="{parts: viewModel.highlightParts}"></ng-container>
|
|
14086
|
+
}
|
|
14087
|
+
@if (multiselect) {
|
|
14088
|
+
<co-input-checkbox [model]="viewModel.checked"
|
|
14089
|
+
(modelChange)="selectViewModel(viewModel, false)"></co-input-checkbox>
|
|
14090
|
+
<ng-container [ngTemplateOutlet]="optionText" [ngTemplateOutletContext]="{parts: viewModel.highlightParts}"></ng-container>
|
|
14091
|
+
}
|
|
14092
|
+
</li>
|
|
13818
14093
|
}
|
|
13819
|
-
|
|
13820
|
-
|
|
13821
|
-
|
|
13822
|
-
|
|
13823
|
-
|
|
13824
|
-
|
|
13825
|
-
|
|
13826
|
-
|
|
13827
|
-
|
|
13828
|
-
|
|
13829
|
-
|
|
13830
|
-
|
|
14094
|
+
</ul>
|
|
14095
|
+
</div>
|
|
14096
|
+
|
|
14097
|
+
<ng-template #optionText let-parts="parts">
|
|
14098
|
+
<span class="lov-options-text">
|
|
14099
|
+
@for (part of parts; track $index) {
|
|
14100
|
+
@if (part.match) {
|
|
14101
|
+
<mark class="lov-highlight" [textContent]="part.text"></mark>
|
|
14102
|
+
} @else {
|
|
14103
|
+
<span [textContent]="part.text"></span>
|
|
14104
|
+
}
|
|
14105
|
+
}
|
|
14106
|
+
</span>
|
|
14107
|
+
</ng-template>
|
|
14108
|
+
`, 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 });
|
|
13831
14109
|
}
|
|
13832
14110
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ListOfValuesPopupComponent, decorators: [{
|
|
13833
14111
|
type: Component,
|
|
13834
14112
|
args: [{
|
|
13835
14113
|
selector: 'co-list-of-values-popup',
|
|
13836
14114
|
template: `
|
|
13837
|
-
|
|
13838
|
-
|
|
13839
|
-
|
|
13840
|
-
|
|
13841
|
-
|
|
13842
|
-
|
|
13843
|
-
|
|
13844
|
-
|
|
13845
|
-
|
|
13846
|
-
|
|
13847
|
-
|
|
13848
|
-
|
|
13849
|
-
|
|
13850
|
-
|
|
13851
|
-
|
|
13852
|
-
|
|
13853
|
-
|
|
13854
|
-
|
|
13855
|
-
|
|
13856
|
-
|
|
13857
|
-
|
|
13858
|
-
|
|
13859
|
-
|
|
13860
|
-
|
|
13861
|
-
|
|
13862
|
-
|
|
13863
|
-
|
|
13864
|
-
|
|
13865
|
-
|
|
13866
|
-
|
|
13867
|
-
|
|
13868
|
-
|
|
14115
|
+
<div class="lov-options" [overlay]="parentForOverlay" [inheritWidth]="true" [ngClass]="customCssClass"
|
|
14116
|
+
id="lov-popup"
|
|
14117
|
+
role="listbox" [tabindex]="-1"
|
|
14118
|
+
(clickOutside)="closePopup.emit($event)">
|
|
14119
|
+
@if (multiselect) {
|
|
14120
|
+
<co-input-search
|
|
14121
|
+
tabindex="-1"
|
|
14122
|
+
[(model)]="searchTerm"
|
|
14123
|
+
[placeholder]="searchPlaceholder"
|
|
14124
|
+
(keydown)="handleInputKeyDown($event)"
|
|
14125
|
+
(modelChange)="filterViewModels()"></co-input-search>
|
|
14126
|
+
}
|
|
14127
|
+
@if (showToggleAll && multiselect) {
|
|
14128
|
+
<div class="row gap">
|
|
14129
|
+
<co-input-checkbox [model]="allSelected" (modelChange)="toggleAll()"></co-input-checkbox>
|
|
14130
|
+
<span [textContent]="'DESELECT_ALL' | coreLocalize" (click)="toggleAll()"></span>
|
|
14131
|
+
</div>
|
|
14132
|
+
}
|
|
14133
|
+
<ul class="dropdown-list" #dropDownList>
|
|
14134
|
+
@for (viewModel of viewModels; track viewModel; let index = $index) {
|
|
14135
|
+
<li
|
|
14136
|
+
#lovItem
|
|
14137
|
+
[class.selected]="viewModel === highLightModel || viewModels.length === 1"
|
|
14138
|
+
[class.active]="isActive(viewModel)"
|
|
14139
|
+
[class.highlighted]="viewModel === highLightModel"
|
|
14140
|
+
[attr.aria-selected]="isActive(viewModel)"
|
|
14141
|
+
(click)="selectViewModel(viewModel, !multiselect)"
|
|
14142
|
+
role="option">
|
|
14143
|
+
@if (!multiselect) {
|
|
14144
|
+
@if (viewModel.model[optionIcon]) {
|
|
14145
|
+
<co-icon class="input-text-left-icon" [iconData]="iconCacheService.getIcon(viewModel.model[optionIcon])">
|
|
14146
|
+
</co-icon>
|
|
14147
|
+
}
|
|
14148
|
+
<ng-container [ngTemplateOutlet]="optionText" [ngTemplateOutletContext]="{parts: viewModel.highlightParts}"></ng-container>
|
|
14149
|
+
}
|
|
14150
|
+
@if (multiselect) {
|
|
14151
|
+
<co-input-checkbox [model]="viewModel.checked"
|
|
14152
|
+
(modelChange)="selectViewModel(viewModel, false)"></co-input-checkbox>
|
|
14153
|
+
<ng-container [ngTemplateOutlet]="optionText" [ngTemplateOutletContext]="{parts: viewModel.highlightParts}"></ng-container>
|
|
14154
|
+
}
|
|
14155
|
+
</li>
|
|
13869
14156
|
}
|
|
13870
|
-
|
|
13871
|
-
|
|
13872
|
-
|
|
13873
|
-
|
|
13874
|
-
|
|
13875
|
-
|
|
13876
|
-
|
|
13877
|
-
|
|
13878
|
-
|
|
13879
|
-
|
|
13880
|
-
|
|
13881
|
-
|
|
14157
|
+
</ul>
|
|
14158
|
+
</div>
|
|
14159
|
+
|
|
14160
|
+
<ng-template #optionText let-parts="parts">
|
|
14161
|
+
<span class="lov-options-text">
|
|
14162
|
+
@for (part of parts; track $index) {
|
|
14163
|
+
@if (part.match) {
|
|
14164
|
+
<mark class="lov-highlight" [textContent]="part.text"></mark>
|
|
14165
|
+
} @else {
|
|
14166
|
+
<span [textContent]="part.text"></span>
|
|
14167
|
+
}
|
|
14168
|
+
}
|
|
14169
|
+
</span>
|
|
14170
|
+
</ng-template>
|
|
14171
|
+
`,
|
|
13882
14172
|
encapsulation: ViewEncapsulation.None,
|
|
13883
14173
|
standalone: false
|
|
13884
14174
|
}]
|
|
@@ -13937,6 +14227,7 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
13937
14227
|
ngZoneWrapper;
|
|
13938
14228
|
elementRef;
|
|
13939
14229
|
icons = CoreComponentsIcon;
|
|
14230
|
+
lovUtils = LovUtils;
|
|
13940
14231
|
set model(value) {
|
|
13941
14232
|
super.model = value;
|
|
13942
14233
|
this._setSelectedModel();
|
|
@@ -13959,7 +14250,7 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
13959
14250
|
collectionLoadFn;
|
|
13960
14251
|
collectionLoadFnProp;
|
|
13961
14252
|
leftIconData;
|
|
13962
|
-
searchPlaceholder;
|
|
14253
|
+
searchPlaceholder = '';
|
|
13963
14254
|
searchDisabled = false;
|
|
13964
14255
|
showChips = true;
|
|
13965
14256
|
showClass() {
|
|
@@ -13974,6 +14265,7 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
13974
14265
|
isLoading = false;
|
|
13975
14266
|
_collection = [];
|
|
13976
14267
|
debounceTimeout;
|
|
14268
|
+
_filterRequestId = 0;
|
|
13977
14269
|
_lovPopupComponentRef;
|
|
13978
14270
|
constructor(formComponent, iconCacheService, changeDetector, overlayService, formUserChangeListener, ngZoneWrapper, elementRef) {
|
|
13979
14271
|
super(changeDetector, overlayService, formUserChangeListener, ngZoneWrapper, elementRef);
|
|
@@ -13990,6 +14282,25 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
13990
14282
|
super.ngOnInit();
|
|
13991
14283
|
this._setSelectedModel();
|
|
13992
14284
|
}
|
|
14285
|
+
// Value shown in the input: the search text while fetching (largeCollection), otherwise the
|
|
14286
|
+
// selected model(s). Lets a single <co-input-text> serve both modes without a template split.
|
|
14287
|
+
get inputModel() {
|
|
14288
|
+
if (this.largeCollection) {
|
|
14289
|
+
return this.filterText;
|
|
14290
|
+
}
|
|
14291
|
+
if (this.multiselect) {
|
|
14292
|
+
return (!this.selectedModels || this.selectedModels.length === 0) ? null : this.selectedModels;
|
|
14293
|
+
}
|
|
14294
|
+
return this.selectedModel;
|
|
14295
|
+
}
|
|
14296
|
+
handleModelChange(model) {
|
|
14297
|
+
if (this.largeCollection) {
|
|
14298
|
+
this.onModelChange(model);
|
|
14299
|
+
}
|
|
14300
|
+
else {
|
|
14301
|
+
this.handleInputModelChange(model);
|
|
14302
|
+
}
|
|
14303
|
+
}
|
|
13993
14304
|
handleInputModelChange(model) {
|
|
13994
14305
|
if (this._lovPopupComponentRef) {
|
|
13995
14306
|
this._lovPopupComponentRef.instance.searchTerm = model;
|
|
@@ -14004,26 +14315,33 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
14004
14315
|
}
|
|
14005
14316
|
onModelChange(model) {
|
|
14006
14317
|
this.isLoading = true;
|
|
14318
|
+
// Mark this keystroke as the latest request immediately, so an older in-flight
|
|
14319
|
+
// request that resolves within the debounce window is still discarded.
|
|
14320
|
+
const requestId = ++this._filterRequestId;
|
|
14007
14321
|
clearTimeout(this.debounceTimeout);
|
|
14008
14322
|
this.debounceTimeout = setTimeout(() => {
|
|
14009
|
-
this.applyFilter(model);
|
|
14323
|
+
this.applyFilter(model, requestId);
|
|
14010
14324
|
}, 300);
|
|
14011
14325
|
}
|
|
14012
|
-
async applyFilter(text) {
|
|
14326
|
+
async applyFilter(text, requestId = ++this._filterRequestId) {
|
|
14327
|
+
await new Promise(resolve => setTimeout(resolve, 300));
|
|
14328
|
+
if (requestId !== this._filterRequestId) {
|
|
14329
|
+
return;
|
|
14330
|
+
}
|
|
14013
14331
|
if (text?.length < 3) {
|
|
14014
|
-
await new Promise(resolve => setTimeout(resolve, 300));
|
|
14015
14332
|
this.collection = undefined;
|
|
14333
|
+
this.filterText = text;
|
|
14334
|
+
this.closePopup();
|
|
14335
|
+
this.isLoading = false;
|
|
14336
|
+
this.changeDetector.detectChanges();
|
|
14337
|
+
return;
|
|
14016
14338
|
}
|
|
14017
|
-
|
|
14018
|
-
|
|
14019
|
-
|
|
14339
|
+
const loaded = await this.collectionLoadFn(text);
|
|
14340
|
+
if (requestId !== this._filterRequestId) {
|
|
14341
|
+
return;
|
|
14020
14342
|
}
|
|
14343
|
+
this.collection = loaded;
|
|
14021
14344
|
this.filterText = text;
|
|
14022
|
-
if (!this.collection) {
|
|
14023
|
-
this.changeDetector.detectChanges();
|
|
14024
|
-
this.isLoading = false;
|
|
14025
|
-
return [];
|
|
14026
|
-
}
|
|
14027
14345
|
this.filteredCollection = this.collection?.filter((item) => {
|
|
14028
14346
|
if (this.collectionLoadFnProp && this.collectionLoadFnProp.length > 0) {
|
|
14029
14347
|
return item[this.collectionLoadFnProp] && item[this.collectionLoadFnProp].toLowerCase().includes(text.toLowerCase());
|
|
@@ -14032,12 +14350,19 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
14032
14350
|
return true;
|
|
14033
14351
|
}
|
|
14034
14352
|
});
|
|
14035
|
-
(this.filteredCollection?.length > 0 && this.filterText?.length > 2)
|
|
14353
|
+
if (this.filteredCollection?.length > 0 && this.filterText?.length > 2) {
|
|
14354
|
+
this.openPopup(); // no-op when already open
|
|
14355
|
+
if (this._lovPopupComponentRef) {
|
|
14356
|
+
// Refresh the open popup in place; no re-create, so no flicker.
|
|
14357
|
+
this._lovPopupComponentRef.instance.collection = this.collection;
|
|
14358
|
+
this._lovPopupComponentRef.instance.searchTerm = text;
|
|
14359
|
+
}
|
|
14360
|
+
}
|
|
14361
|
+
else {
|
|
14362
|
+
this.closePopup();
|
|
14363
|
+
}
|
|
14036
14364
|
this.isLoading = false;
|
|
14037
14365
|
this.changeDetector.detectChanges();
|
|
14038
|
-
if (this._lovPopupComponentRef) {
|
|
14039
|
-
this._lovPopupComponentRef.instance.searchTerm = text;
|
|
14040
|
-
}
|
|
14041
14366
|
}
|
|
14042
14367
|
handleInputKeyDown(event) {
|
|
14043
14368
|
if (event) {
|
|
@@ -14082,6 +14407,11 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
14082
14407
|
if (this.readonly) {
|
|
14083
14408
|
return;
|
|
14084
14409
|
}
|
|
14410
|
+
// Idempotent: keep the existing popup so continued typing refreshes it in place
|
|
14411
|
+
// instead of re-creating it (which would replay the open animation / flicker).
|
|
14412
|
+
if (this._lovPopupComponentRef) {
|
|
14413
|
+
return;
|
|
14414
|
+
}
|
|
14085
14415
|
this.isSelectOpen = true;
|
|
14086
14416
|
this._lovPopupComponentRef = this.overlayService.createComponent(ListOfValuesPopupComponent, {
|
|
14087
14417
|
parentForOverlay: this.elementRef,
|
|
@@ -14111,12 +14441,12 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
14111
14441
|
optionChosen(option) {
|
|
14112
14442
|
if (option) {
|
|
14113
14443
|
if (this.multiselect) {
|
|
14114
|
-
this.selectedModels = option.map(o => o
|
|
14444
|
+
this.selectedModels = option.map(o => LovUtils.getDisplayValue(o, this.displayField));
|
|
14115
14445
|
}
|
|
14116
14446
|
else {
|
|
14117
|
-
this.selectedModel = option
|
|
14447
|
+
this.selectedModel = LovUtils.getDisplayValue(option, this.displayField);
|
|
14118
14448
|
if (this.largeCollection) {
|
|
14119
|
-
this.filterText = option
|
|
14449
|
+
this.filterText = LovUtils.getDisplayValue(option, this.displayField);
|
|
14120
14450
|
}
|
|
14121
14451
|
}
|
|
14122
14452
|
}
|
|
@@ -14140,8 +14470,13 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
14140
14470
|
this.focused = false;
|
|
14141
14471
|
}
|
|
14142
14472
|
checkModel() {
|
|
14473
|
+
if (this.largeCollection) {
|
|
14474
|
+
// The input holds the search text (not a to-be-resolved value) and selection happens via the
|
|
14475
|
+
// popup, so blur must not try to match/clear the model here.
|
|
14476
|
+
return;
|
|
14477
|
+
}
|
|
14143
14478
|
if (!this.multiselect && this.selectedModel && this.collection) {
|
|
14144
|
-
const model = this.collection.find(c => c
|
|
14479
|
+
const model = this.collection.find(c => LovUtils.getDisplayValue(c, this.displayField) === this.selectedModel);
|
|
14145
14480
|
if (model) {
|
|
14146
14481
|
this.model = model;
|
|
14147
14482
|
}
|
|
@@ -14156,7 +14491,7 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
14156
14491
|
if (this.model) {
|
|
14157
14492
|
this.selectedModels.length = 0;
|
|
14158
14493
|
this.model.forEach(m => {
|
|
14159
|
-
this.selectedModels.push(m
|
|
14494
|
+
this.selectedModels.push(LovUtils.getDisplayValue(m, this.displayField));
|
|
14160
14495
|
});
|
|
14161
14496
|
}
|
|
14162
14497
|
else {
|
|
@@ -14165,13 +14500,14 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
14165
14500
|
}
|
|
14166
14501
|
else {
|
|
14167
14502
|
if (this.model) {
|
|
14168
|
-
this.selectedModel = this.model
|
|
14503
|
+
this.selectedModel = LovUtils.getDisplayValue(this.model, this.displayField);
|
|
14169
14504
|
if (this.largeCollection) {
|
|
14170
|
-
this.filterText = this.model
|
|
14505
|
+
this.filterText = LovUtils.getDisplayValue(this.model, this.displayField);
|
|
14171
14506
|
}
|
|
14172
14507
|
}
|
|
14173
14508
|
else {
|
|
14174
14509
|
this.selectedModel = '';
|
|
14510
|
+
this.filterText = '';
|
|
14175
14511
|
}
|
|
14176
14512
|
}
|
|
14177
14513
|
}
|
|
@@ -14183,59 +14519,47 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
14183
14519
|
useExisting: forwardRef(() => ListOfValuesComponent)
|
|
14184
14520
|
}
|
|
14185
14521
|
], viewQueries: [{ propertyName: "parentForOverlay", first: true, predicate: ["parentForOverlay"], descendants: true, read: ElementRef }], usesInheritance: true, ngImport: i0, template: `
|
|
14186
|
-
|
|
14187
|
-
|
|
14188
|
-
|
|
14189
|
-
|
|
14190
|
-
|
|
14191
|
-
|
|
14192
|
-
|
|
14193
|
-
|
|
14194
|
-
|
|
14195
|
-
|
|
14196
|
-
|
|
14197
|
-
|
|
14198
|
-
|
|
14199
|
-
|
|
14200
|
-
|
|
14201
|
-
|
|
14202
|
-
|
|
14203
|
-
|
|
14204
|
-
|
|
14205
|
-
|
|
14206
|
-
|
|
14207
|
-
|
|
14208
|
-
|
|
14209
|
-
|
|
14210
|
-
|
|
14211
|
-
|
|
14212
|
-
|
|
14213
|
-
|
|
14214
|
-
|
|
14215
|
-
|
|
14216
|
-
|
|
14217
|
-
|
|
14218
|
-
|
|
14219
|
-
|
|
14220
|
-
<span class="chips-description" [textContent]="chip
|
|
14522
|
+
<co-input-text
|
|
14523
|
+
aria-haspopup="listbox"
|
|
14524
|
+
[attr.aria-expanded]="isSelectOpen"
|
|
14525
|
+
aria-controls="lov-popup"
|
|
14526
|
+
role="combobox"
|
|
14527
|
+
class="no-focus-line"
|
|
14528
|
+
overlayParent
|
|
14529
|
+
#parentForOverlay="overlayParent"
|
|
14530
|
+
type="text"
|
|
14531
|
+
[id]="label"
|
|
14532
|
+
[model]="inputModel"
|
|
14533
|
+
[label]="label"
|
|
14534
|
+
[placeholder]="searchPlaceholder"
|
|
14535
|
+
[myFormInputInstance]="this"
|
|
14536
|
+
[readonly]="readonly"
|
|
14537
|
+
[disabled]="disabled"
|
|
14538
|
+
[required]="required"
|
|
14539
|
+
[noClickFocus]="false"
|
|
14540
|
+
[leftIconData]=" model && model[optionIcon] ? iconCacheService.getIcon(model[optionIcon]) : leftIconData"
|
|
14541
|
+
[rightIcon]="isSelectOpen ? icons.ChevronUpRegular : icons.ChevronDownRegular"
|
|
14542
|
+
[showClearButton]="true"
|
|
14543
|
+
[useContent]="multiselect"
|
|
14544
|
+
[customHeight]="multiselect"
|
|
14545
|
+
[keepFocussed]="keepFocussed"
|
|
14546
|
+
(modelChange)="handleModelChange($event)"
|
|
14547
|
+
(click)="openPopup()"
|
|
14548
|
+
(rightIconClick)="toggleSelect()"
|
|
14549
|
+
(keydown)="handleInputKeyDown($event)"
|
|
14550
|
+
(clearIconClick)="clearModel($event)"
|
|
14551
|
+
(blur)="checkModel()">
|
|
14552
|
+
@if (multiselect && showChips) {
|
|
14553
|
+
<div class="multiselect-chips-wrapper">
|
|
14554
|
+
@for (chip of model; track chip) {
|
|
14555
|
+
<div class="chips">
|
|
14556
|
+
<span class="chips-description" [textContent]="lovUtils.getDisplayValue(chip, displayField)"></span>
|
|
14221
14557
|
<co-icon class="remove-chip-icon" [icon]="icons.CrossSkinny" (click)="removeOptionFromModel(chip)"></co-icon>
|
|
14222
|
-
|
|
14223
|
-
|
|
14224
|
-
|
|
14225
|
-
|
|
14226
|
-
|
|
14227
|
-
}
|
|
14228
|
-
|
|
14229
|
-
@if (largeCollection) {
|
|
14230
|
-
<co-input-text
|
|
14231
|
-
[model]="filterText"
|
|
14232
|
-
[placeholder]="label"
|
|
14233
|
-
[required]="required"
|
|
14234
|
-
[disabled]="disabled"
|
|
14235
|
-
[readonly]="readonly"
|
|
14236
|
-
(modelChange)="onModelChange($event)">
|
|
14237
|
-
</co-input-text>
|
|
14238
|
-
}
|
|
14558
|
+
</div>
|
|
14559
|
+
}
|
|
14560
|
+
</div>
|
|
14561
|
+
}
|
|
14562
|
+
</co-input-text>
|
|
14239
14563
|
@if (isLoading) {
|
|
14240
14564
|
<div class="filter-loader"><span></span></div>
|
|
14241
14565
|
}
|
|
@@ -14247,59 +14571,47 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
14247
14571
|
args: [{
|
|
14248
14572
|
selector: 'co-list-of-values',
|
|
14249
14573
|
template: `
|
|
14250
|
-
|
|
14251
|
-
|
|
14252
|
-
|
|
14253
|
-
|
|
14254
|
-
|
|
14255
|
-
|
|
14256
|
-
|
|
14257
|
-
|
|
14258
|
-
|
|
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
|
-
<span class="chips-description" [textContent]="chip
|
|
14574
|
+
<co-input-text
|
|
14575
|
+
aria-haspopup="listbox"
|
|
14576
|
+
[attr.aria-expanded]="isSelectOpen"
|
|
14577
|
+
aria-controls="lov-popup"
|
|
14578
|
+
role="combobox"
|
|
14579
|
+
class="no-focus-line"
|
|
14580
|
+
overlayParent
|
|
14581
|
+
#parentForOverlay="overlayParent"
|
|
14582
|
+
type="text"
|
|
14583
|
+
[id]="label"
|
|
14584
|
+
[model]="inputModel"
|
|
14585
|
+
[label]="label"
|
|
14586
|
+
[placeholder]="searchPlaceholder"
|
|
14587
|
+
[myFormInputInstance]="this"
|
|
14588
|
+
[readonly]="readonly"
|
|
14589
|
+
[disabled]="disabled"
|
|
14590
|
+
[required]="required"
|
|
14591
|
+
[noClickFocus]="false"
|
|
14592
|
+
[leftIconData]=" model && model[optionIcon] ? iconCacheService.getIcon(model[optionIcon]) : leftIconData"
|
|
14593
|
+
[rightIcon]="isSelectOpen ? icons.ChevronUpRegular : icons.ChevronDownRegular"
|
|
14594
|
+
[showClearButton]="true"
|
|
14595
|
+
[useContent]="multiselect"
|
|
14596
|
+
[customHeight]="multiselect"
|
|
14597
|
+
[keepFocussed]="keepFocussed"
|
|
14598
|
+
(modelChange)="handleModelChange($event)"
|
|
14599
|
+
(click)="openPopup()"
|
|
14600
|
+
(rightIconClick)="toggleSelect()"
|
|
14601
|
+
(keydown)="handleInputKeyDown($event)"
|
|
14602
|
+
(clearIconClick)="clearModel($event)"
|
|
14603
|
+
(blur)="checkModel()">
|
|
14604
|
+
@if (multiselect && showChips) {
|
|
14605
|
+
<div class="multiselect-chips-wrapper">
|
|
14606
|
+
@for (chip of model; track chip) {
|
|
14607
|
+
<div class="chips">
|
|
14608
|
+
<span class="chips-description" [textContent]="lovUtils.getDisplayValue(chip, displayField)"></span>
|
|
14285
14609
|
<co-icon class="remove-chip-icon" [icon]="icons.CrossSkinny" (click)="removeOptionFromModel(chip)"></co-icon>
|
|
14286
|
-
|
|
14287
|
-
|
|
14288
|
-
|
|
14289
|
-
|
|
14290
|
-
|
|
14291
|
-
}
|
|
14292
|
-
|
|
14293
|
-
@if (largeCollection) {
|
|
14294
|
-
<co-input-text
|
|
14295
|
-
[model]="filterText"
|
|
14296
|
-
[placeholder]="label"
|
|
14297
|
-
[required]="required"
|
|
14298
|
-
[disabled]="disabled"
|
|
14299
|
-
[readonly]="readonly"
|
|
14300
|
-
(modelChange)="onModelChange($event)">
|
|
14301
|
-
</co-input-text>
|
|
14302
|
-
}
|
|
14610
|
+
</div>
|
|
14611
|
+
}
|
|
14612
|
+
</div>
|
|
14613
|
+
}
|
|
14614
|
+
</co-input-text>
|
|
14303
14615
|
@if (isLoading) {
|
|
14304
14616
|
<div class="filter-loader"><span></span></div>
|
|
14305
14617
|
}
|
|
@@ -16556,9 +16868,7 @@ class FilterItemModule {
|
|
|
16556
16868
|
ScrollingModule,
|
|
16557
16869
|
AppendPipeModule,
|
|
16558
16870
|
PrependPipeModule,
|
|
16559
|
-
InputTextModule,
|
|
16560
16871
|
InputRadioButtonModule,
|
|
16561
|
-
InputTextModule,
|
|
16562
16872
|
CoreComponentsTranslationModule,
|
|
16563
16873
|
InputDatePickerModule,
|
|
16564
16874
|
InputDateRangePickerModule], exports: [FilterItemComponent] });
|
|
@@ -16570,9 +16880,7 @@ class FilterItemModule {
|
|
|
16570
16880
|
ScrollingModule,
|
|
16571
16881
|
AppendPipeModule,
|
|
16572
16882
|
PrependPipeModule,
|
|
16573
|
-
InputTextModule,
|
|
16574
16883
|
InputRadioButtonModule,
|
|
16575
|
-
InputTextModule,
|
|
16576
16884
|
CoreComponentsTranslationModule,
|
|
16577
16885
|
InputDatePickerModule,
|
|
16578
16886
|
InputDateRangePickerModule] });
|
|
@@ -16589,9 +16897,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
16589
16897
|
ScrollingModule,
|
|
16590
16898
|
AppendPipeModule,
|
|
16591
16899
|
PrependPipeModule,
|
|
16592
|
-
InputTextModule,
|
|
16593
16900
|
InputRadioButtonModule,
|
|
16594
|
-
InputTextModule,
|
|
16595
16901
|
CoreComponentsTranslationModule,
|
|
16596
16902
|
InputDatePickerModule,
|
|
16597
16903
|
InputDateRangePickerModule
|