@colijnit/corecomponents_v12 261.20.16 → 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 +678 -366
- package/fesm2022/colijnit-corecomponents_v12.mjs.map +1 -1
- package/index.d.ts +60 -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
|
@@ -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;
|
|
@@ -7190,12 +7286,15 @@ class InputTextComponent extends BaseInputComponent {
|
|
|
7190
7286
|
rightIconData;
|
|
7191
7287
|
selectOnFocus = false;
|
|
7192
7288
|
emptyPlace = false;
|
|
7193
|
-
firstDayOfWeek = '1'; //
|
|
7289
|
+
firstDayOfWeek = '1'; // Monday by default
|
|
7194
7290
|
noStyle = false;
|
|
7195
7291
|
hideArrowButtons = false;
|
|
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
|
}
|
|
@@ -7402,18 +7571,19 @@ class InputTextComponent extends BaseInputComponent {
|
|
|
7402
7571
|
// Internal default first day of week
|
|
7403
7572
|
let weekdayOffset = parseInt(this.firstDayOfWeek, 10);
|
|
7404
7573
|
if (isNaN(weekdayOffset) || weekdayOffset < 1 || weekdayOffset > 7) {
|
|
7405
|
-
weekdayOffset =
|
|
7574
|
+
weekdayOffset = 1; // Monday
|
|
7406
7575
|
}
|
|
7407
|
-
|
|
7576
|
+
// 1 = Monday, 2 = Tuesday, 3 = Wednesday, ..., 7 = Sunday
|
|
7577
|
+
const jsWeekdayIndex = weekdayOffset - 1;
|
|
7408
7578
|
const jan4 = new Date(year, 0, 4);
|
|
7409
7579
|
const jan4Day = jan4.getDay();
|
|
7410
7580
|
const diffToMonday = (jan4Day + 6) % 7;
|
|
7411
7581
|
const firstWeekMonday = new Date(jan4);
|
|
7412
|
-
firstWeekMonday.setDate(jan4.getDate() - diffToMonday);
|
|
7582
|
+
firstWeekMonday.setDate(jan4.getDate() - diffToMonday);
|
|
7413
7583
|
const baseWeekStart = new Date(firstWeekMonday);
|
|
7414
|
-
baseWeekStart.setDate(
|
|
7415
|
-
|
|
7416
|
-
targetDate.setDate(
|
|
7584
|
+
baseWeekStart.setDate(firstWeekMonday.getDate() + (week - 1) * 7);
|
|
7585
|
+
let targetDate = new Date(baseWeekStart);
|
|
7586
|
+
targetDate.setDate(targetDate.getDate() + jsWeekdayIndex);
|
|
7417
7587
|
if (targetDate < today) {
|
|
7418
7588
|
year += 1;
|
|
7419
7589
|
const jan4Next = new Date(year, 0, 4);
|
|
@@ -7422,15 +7592,20 @@ class InputTextComponent extends BaseInputComponent {
|
|
|
7422
7592
|
const firstWeekMondayNext = new Date(jan4Next);
|
|
7423
7593
|
firstWeekMondayNext.setDate(jan4Next.getDate() - diffToMondayNext);
|
|
7424
7594
|
const baseWeekStartNext = new Date(firstWeekMondayNext);
|
|
7425
|
-
baseWeekStartNext.setDate(
|
|
7426
|
-
targetDate
|
|
7427
|
-
targetDate.
|
|
7428
|
-
targetDate.setDate(baseWeekStartNext.getDate() + jsWeekdayIndex);
|
|
7595
|
+
baseWeekStartNext.setDate(firstWeekMondayNext.getDate() + (week - 1) * 7);
|
|
7596
|
+
targetDate = new Date(baseWeekStartNext);
|
|
7597
|
+
targetDate.setDate(targetDate.getDate() + jsWeekdayIndex);
|
|
7429
7598
|
}
|
|
7430
|
-
this.model =
|
|
7599
|
+
this.model = this.formatDateLocal(targetDate);
|
|
7431
7600
|
this.modelChange.emit(this.model);
|
|
7432
7601
|
}
|
|
7433
|
-
|
|
7602
|
+
formatDateLocal(date) {
|
|
7603
|
+
const year = date.getFullYear();
|
|
7604
|
+
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
7605
|
+
const day = String(date.getDate()).padStart(2, '0');
|
|
7606
|
+
return `${year}-${month}-${day}`;
|
|
7607
|
+
}
|
|
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 });
|
|
7434
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: [
|
|
7435
7610
|
OverlayService, {
|
|
7436
7611
|
provide: SCREEN_CONFIG_ADAPTER_COMPONENT_INTERFACE_NAME,
|
|
@@ -7452,7 +7627,7 @@ class InputTextComponent extends BaseInputComponent {
|
|
|
7452
7627
|
<div class="input-wrapper">
|
|
7453
7628
|
@if (showPlaceholderOnFocus || (!showPlaceholderOnFocus && !hasValue && !focused)) {
|
|
7454
7629
|
<label
|
|
7455
|
-
[textContent]="
|
|
7630
|
+
[textContent]="label"></label>
|
|
7456
7631
|
}
|
|
7457
7632
|
@if (!focused && !useContent && formatPipe) {
|
|
7458
7633
|
<span class="input-text-formatted"
|
|
@@ -7465,15 +7640,16 @@ class InputTextComponent extends BaseInputComponent {
|
|
|
7465
7640
|
<input [class.show]="focused || !formatPipe" #input
|
|
7466
7641
|
[class.input-input-hidden]="useContent"
|
|
7467
7642
|
[ngClass]="align"
|
|
7468
|
-
[type]="isWeekInputMode ? 'text' : (isFocusedOnDate || (hasValue && emptyPlace)) ? 'date' : (digitsOnly ? '
|
|
7469
|
-
[
|
|
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"
|
|
7470
7646
|
[pattern]="type === 'date' ? pattern : undefined"
|
|
7471
|
-
[ngModel]="model"
|
|
7647
|
+
[ngModel]="digitsOnly ? displayValue : model"
|
|
7472
7648
|
[min]="(type === 'number' || type === 'date') && this.min ? this.min : undefined"
|
|
7473
7649
|
[max]="(type === 'number' || type === 'date') && this.max ? this.max : undefined"
|
|
7474
7650
|
[readonly]="readonly"
|
|
7475
7651
|
[required]="required"
|
|
7476
|
-
(ngModelChange)="
|
|
7652
|
+
(ngModelChange)="handleInputModelChange($event)"
|
|
7477
7653
|
(keydown)="handleKeyDownInput($event)"
|
|
7478
7654
|
(keyup)="keyUp.emit($event)"
|
|
7479
7655
|
(focusin)="handleInputFocus($event)"
|
|
@@ -7528,7 +7704,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
7528
7704
|
<div class="input-wrapper">
|
|
7529
7705
|
@if (showPlaceholderOnFocus || (!showPlaceholderOnFocus && !hasValue && !focused)) {
|
|
7530
7706
|
<label
|
|
7531
|
-
[textContent]="
|
|
7707
|
+
[textContent]="label"></label>
|
|
7532
7708
|
}
|
|
7533
7709
|
@if (!focused && !useContent && formatPipe) {
|
|
7534
7710
|
<span class="input-text-formatted"
|
|
@@ -7541,15 +7717,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
7541
7717
|
<input [class.show]="focused || !formatPipe" #input
|
|
7542
7718
|
[class.input-input-hidden]="useContent"
|
|
7543
7719
|
[ngClass]="align"
|
|
7544
|
-
[type]="isWeekInputMode ? 'text' : (isFocusedOnDate || (hasValue && emptyPlace)) ? 'date' : (digitsOnly ? '
|
|
7545
|
-
[
|
|
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"
|
|
7546
7723
|
[pattern]="type === 'date' ? pattern : undefined"
|
|
7547
|
-
[ngModel]="model"
|
|
7724
|
+
[ngModel]="digitsOnly ? displayValue : model"
|
|
7548
7725
|
[min]="(type === 'number' || type === 'date') && this.min ? this.min : undefined"
|
|
7549
7726
|
[max]="(type === 'number' || type === 'date') && this.max ? this.max : undefined"
|
|
7550
7727
|
[readonly]="readonly"
|
|
7551
7728
|
[required]="required"
|
|
7552
|
-
(ngModelChange)="
|
|
7729
|
+
(ngModelChange)="handleInputModelChange($event)"
|
|
7553
7730
|
(keydown)="handleKeyDownInput($event)"
|
|
7554
7731
|
(keyup)="keyUp.emit($event)"
|
|
7555
7732
|
(focusin)="handleInputFocus($event)"
|
|
@@ -7600,7 +7777,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
7600
7777
|
}]
|
|
7601
7778
|
}], ctorParameters: () => [{ type: FormComponent, decorators: [{
|
|
7602
7779
|
type: Optional
|
|
7603
|
-
}] }, { 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: [{
|
|
7604
7781
|
type: Input
|
|
7605
7782
|
}], placeholder: [{
|
|
7606
7783
|
type: Input
|
|
@@ -9029,16 +9206,25 @@ class InputNumberPickerComponent extends BaseInputComponent {
|
|
|
9029
9206
|
iconCacheService;
|
|
9030
9207
|
overlayService;
|
|
9031
9208
|
_ngZone;
|
|
9209
|
+
_numberLocale;
|
|
9032
9210
|
ngZoneWrapper;
|
|
9033
9211
|
elementRef;
|
|
9034
9212
|
// @override
|
|
9035
9213
|
set model(model) {
|
|
9036
9214
|
this.setValue(model, true);
|
|
9037
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
|
+
}
|
|
9038
9220
|
}
|
|
9039
9221
|
get model() {
|
|
9040
9222
|
return super.model;
|
|
9041
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
|
+
}
|
|
9042
9228
|
modelChangeOnEnter = true;
|
|
9043
9229
|
showPermanentLabel = false;
|
|
9044
9230
|
leftIconData;
|
|
@@ -9059,8 +9245,14 @@ class InputNumberPickerComponent extends BaseInputComponent {
|
|
|
9059
9245
|
// @override Default true for us.
|
|
9060
9246
|
noValidation = true;
|
|
9061
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;
|
|
9062
9251
|
this.numberLogic.decimals = decimals;
|
|
9063
9252
|
}
|
|
9253
|
+
get decimals() {
|
|
9254
|
+
return super.decimals;
|
|
9255
|
+
}
|
|
9064
9256
|
// @override
|
|
9065
9257
|
modelChange = new EventEmitter();
|
|
9066
9258
|
iconClick = new EventEmitter();
|
|
@@ -9080,6 +9272,8 @@ class InputNumberPickerComponent extends BaseInputComponent {
|
|
|
9080
9272
|
plusSelected = false;
|
|
9081
9273
|
_numberInputHasFocus = false;
|
|
9082
9274
|
_changeFromButton = false;
|
|
9275
|
+
_userTyping = false;
|
|
9276
|
+
_displayValue = '';
|
|
9083
9277
|
_numberLogicValueChangeSub;
|
|
9084
9278
|
_delayBeforeStartAutoCountMs = 666;
|
|
9085
9279
|
// the 'speed gears' for auto counting
|
|
@@ -9094,12 +9288,13 @@ class InputNumberPickerComponent extends BaseInputComponent {
|
|
|
9094
9288
|
_autoCountTimeout;
|
|
9095
9289
|
_stepIncrementTimeout;
|
|
9096
9290
|
_startAutocountTimeout;
|
|
9097
|
-
constructor(formComponent, iconCacheService, overlayService, _ngZone, changeDetector, formUserChangeListener, ngZoneWrapper, elementRef) {
|
|
9291
|
+
constructor(formComponent, iconCacheService, overlayService, _ngZone, changeDetector, formUserChangeListener, _numberLocale, ngZoneWrapper, elementRef) {
|
|
9098
9292
|
super(changeDetector, overlayService, formUserChangeListener, ngZoneWrapper, elementRef);
|
|
9099
9293
|
this.formComponent = formComponent;
|
|
9100
9294
|
this.iconCacheService = iconCacheService;
|
|
9101
9295
|
this.overlayService = overlayService;
|
|
9102
9296
|
this._ngZone = _ngZone;
|
|
9297
|
+
this._numberLocale = _numberLocale;
|
|
9103
9298
|
this.ngZoneWrapper = ngZoneWrapper;
|
|
9104
9299
|
this.elementRef = elementRef;
|
|
9105
9300
|
this._numberLogicValueChangeSub = this.numberLogic.valueChange.subscribe((value) => {
|
|
@@ -9149,13 +9344,40 @@ class InputNumberPickerComponent extends BaseInputComponent {
|
|
|
9149
9344
|
if (this.myKeyDownWhiteList.find((k) => k === event.keyCode) === undefined) {
|
|
9150
9345
|
return false;
|
|
9151
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() {
|
|
9152
9368
|
}
|
|
9153
9369
|
handleBlur() {
|
|
9370
|
+
// normalize the display once editing stops (e.g. "12," -> "12", trailing zeros dropped)
|
|
9371
|
+
this._displayValue = this._numberLocale.format(this.model);
|
|
9154
9372
|
this.modelChange.next(this.model);
|
|
9155
9373
|
}
|
|
9156
|
-
handleChangeModel(
|
|
9374
|
+
handleChangeModel(text) {
|
|
9157
9375
|
this._changeFromButton = false;
|
|
9158
|
-
|
|
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;
|
|
9159
9381
|
}
|
|
9160
9382
|
// Note: recursive through setTimeout().
|
|
9161
9383
|
doDecrementAuto() {
|
|
@@ -9257,7 +9479,7 @@ class InputNumberPickerComponent extends BaseInputComponent {
|
|
|
9257
9479
|
break;
|
|
9258
9480
|
}
|
|
9259
9481
|
}
|
|
9260
|
-
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 });
|
|
9261
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: [
|
|
9262
9484
|
OverlayService, {
|
|
9263
9485
|
provide: SCREEN_CONFIG_ADAPTER_COMPONENT_INTERFACE_NAME, useExisting: forwardRef(() => InputNumberPickerComponent)
|
|
@@ -9283,15 +9505,15 @@ class InputNumberPickerComponent extends BaseInputComponent {
|
|
|
9283
9505
|
</div>
|
|
9284
9506
|
<div class="input-wrapper">
|
|
9285
9507
|
@if (showPermanentLabel) {
|
|
9286
|
-
<span class='permanent-label' [textContent]="label"></span>
|
|
9508
|
+
<span class='permanent-label' [textContent]="label ?? ''"></span>
|
|
9287
9509
|
}
|
|
9288
|
-
<input type="
|
|
9510
|
+
<input type="text" inputmode="decimal"
|
|
9289
9511
|
[tabIndex]="readonly ? -1 : 0"
|
|
9290
|
-
[ngModel]="
|
|
9512
|
+
[ngModel]="displayValue"
|
|
9291
9513
|
[readonly]="readonly"
|
|
9292
9514
|
[disabled]="disabled"
|
|
9293
9515
|
[required]="required"
|
|
9294
|
-
[placeholder]="label"
|
|
9516
|
+
[placeholder]="label ?? ''"
|
|
9295
9517
|
(ngModelChange)="handleChangeModel($event)"
|
|
9296
9518
|
(keydown)="handleInputKeyDown($event)"
|
|
9297
9519
|
(blur)="handleBlur()"/>
|
|
@@ -9305,7 +9527,7 @@ class InputNumberPickerComponent extends BaseInputComponent {
|
|
|
9305
9527
|
(mouseup)="stopAutoCounting()" (mouseleave)="stopAutoCounting()"></co-button>
|
|
9306
9528
|
}
|
|
9307
9529
|
</div>
|
|
9308
|
-
`, 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 });
|
|
9309
9531
|
}
|
|
9310
9532
|
__decorate([
|
|
9311
9533
|
InputBoolean()
|
|
@@ -9332,15 +9554,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
9332
9554
|
</div>
|
|
9333
9555
|
<div class="input-wrapper">
|
|
9334
9556
|
@if (showPermanentLabel) {
|
|
9335
|
-
<span class='permanent-label' [textContent]="label"></span>
|
|
9557
|
+
<span class='permanent-label' [textContent]="label ?? ''"></span>
|
|
9336
9558
|
}
|
|
9337
|
-
<input type="
|
|
9559
|
+
<input type="text" inputmode="decimal"
|
|
9338
9560
|
[tabIndex]="readonly ? -1 : 0"
|
|
9339
|
-
[ngModel]="
|
|
9561
|
+
[ngModel]="displayValue"
|
|
9340
9562
|
[readonly]="readonly"
|
|
9341
9563
|
[disabled]="disabled"
|
|
9342
9564
|
[required]="required"
|
|
9343
|
-
[placeholder]="label"
|
|
9565
|
+
[placeholder]="label ?? ''"
|
|
9344
9566
|
(ngModelChange)="handleChangeModel($event)"
|
|
9345
9567
|
(keydown)="handleInputKeyDown($event)"
|
|
9346
9568
|
(blur)="handleBlur()"/>
|
|
@@ -9372,7 +9594,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
9372
9594
|
}] }, { type: IconCacheService, decorators: [{
|
|
9373
9595
|
type: Inject,
|
|
9374
9596
|
args: [IconCacheService]
|
|
9375
|
-
}] }, { 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: [{
|
|
9376
9598
|
type: Input
|
|
9377
9599
|
}], modelChangeOnEnter: [{
|
|
9378
9600
|
type: Input
|
|
@@ -13521,6 +13743,46 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
13521
13743
|
}]
|
|
13522
13744
|
}] });
|
|
13523
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
|
+
|
|
13524
13786
|
class ListOfValuesPopupComponent {
|
|
13525
13787
|
iconCacheService;
|
|
13526
13788
|
_elementRef;
|
|
@@ -13641,7 +13903,11 @@ class ListOfValuesPopupComponent {
|
|
|
13641
13903
|
}
|
|
13642
13904
|
}
|
|
13643
13905
|
selectModelByViewModel(viewModel, closePopup = true) {
|
|
13644
|
-
|
|
13906
|
+
const found = this.viewModelsMain.find(vm => vm === viewModel);
|
|
13907
|
+
if (!found) {
|
|
13908
|
+
return;
|
|
13909
|
+
}
|
|
13910
|
+
this.model = found.model;
|
|
13645
13911
|
this.modelChange.emit(this.model);
|
|
13646
13912
|
this._scrollIntoView();
|
|
13647
13913
|
if (closePopup) {
|
|
@@ -13654,7 +13920,7 @@ class ListOfValuesPopupComponent {
|
|
|
13654
13920
|
this.selectNextOption();
|
|
13655
13921
|
}
|
|
13656
13922
|
if (!this.model && this.searchTerm) {
|
|
13657
|
-
const wishModel = this.viewModelsMain.find(vmm => vmm.model
|
|
13923
|
+
const wishModel = this.viewModelsMain.find(vmm => LovUtils.getDisplayValue(vmm.model, this.displayField) === this.searchTerm);
|
|
13658
13924
|
if (wishModel) {
|
|
13659
13925
|
this.selectViewModel(wishModel);
|
|
13660
13926
|
}
|
|
@@ -13674,6 +13940,9 @@ class ListOfValuesPopupComponent {
|
|
|
13674
13940
|
this.modelChange.emit(this.model);
|
|
13675
13941
|
}
|
|
13676
13942
|
selectNextOption(back = false) {
|
|
13943
|
+
if (this.viewModels.length === 0) {
|
|
13944
|
+
return;
|
|
13945
|
+
}
|
|
13677
13946
|
let nextModel;
|
|
13678
13947
|
if (!this.highLightModel) {
|
|
13679
13948
|
nextModel = this.viewModels[back ? this.viewModels.length - 1 : 0];
|
|
@@ -13727,8 +13996,8 @@ class ListOfValuesPopupComponent {
|
|
|
13727
13996
|
}
|
|
13728
13997
|
if (!this.model)
|
|
13729
13998
|
return false;
|
|
13730
|
-
const selected = this.model
|
|
13731
|
-
const current = vm.model
|
|
13999
|
+
const selected = LovUtils.getDisplayValue(this.model, this.displayField);
|
|
14000
|
+
const current = LovUtils.getDisplayValue(vm.model, this.displayField);
|
|
13732
14001
|
return selected != null && current != null && selected === current;
|
|
13733
14002
|
}
|
|
13734
14003
|
_prepareViewModelsMain() {
|
|
@@ -13749,6 +14018,9 @@ class ListOfValuesPopupComponent {
|
|
|
13749
14018
|
}
|
|
13750
14019
|
});
|
|
13751
14020
|
});
|
|
14021
|
+
this.viewModels.forEach((vm) => {
|
|
14022
|
+
vm.highlightParts = LovUtils.getHighlightParts(LovUtils.getDisplayValue(vm.model, this.displayField), this.searchTerm);
|
|
14023
|
+
});
|
|
13752
14024
|
}
|
|
13753
14025
|
_scrollIntoView() {
|
|
13754
14026
|
const activeIndex = this.viewModels.findIndex(vmm => vmm === this.highLightModel);
|
|
@@ -13777,102 +14049,126 @@ class ListOfValuesPopupComponent {
|
|
|
13777
14049
|
}
|
|
13778
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 });
|
|
13779
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: `
|
|
13780
|
-
|
|
13781
|
-
|
|
13782
|
-
|
|
13783
|
-
|
|
13784
|
-
|
|
13785
|
-
|
|
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
|
-
|
|
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>
|
|
13812
14093
|
}
|
|
13813
|
-
|
|
13814
|
-
|
|
13815
|
-
|
|
13816
|
-
|
|
13817
|
-
|
|
13818
|
-
|
|
13819
|
-
|
|
13820
|
-
|
|
13821
|
-
|
|
13822
|
-
|
|
13823
|
-
|
|
13824
|
-
|
|
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 });
|
|
13825
14109
|
}
|
|
13826
14110
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ListOfValuesPopupComponent, decorators: [{
|
|
13827
14111
|
type: Component,
|
|
13828
14112
|
args: [{
|
|
13829
14113
|
selector: 'co-list-of-values-popup',
|
|
13830
14114
|
template: `
|
|
13831
|
-
|
|
13832
|
-
|
|
13833
|
-
|
|
13834
|
-
|
|
13835
|
-
|
|
13836
|
-
|
|
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
|
-
|
|
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>
|
|
13863
14156
|
}
|
|
13864
|
-
|
|
13865
|
-
|
|
13866
|
-
|
|
13867
|
-
|
|
13868
|
-
|
|
13869
|
-
|
|
13870
|
-
|
|
13871
|
-
|
|
13872
|
-
|
|
13873
|
-
|
|
13874
|
-
|
|
13875
|
-
|
|
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
|
+
`,
|
|
13876
14172
|
encapsulation: ViewEncapsulation.None,
|
|
13877
14173
|
standalone: false
|
|
13878
14174
|
}]
|
|
@@ -13931,6 +14227,7 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
13931
14227
|
ngZoneWrapper;
|
|
13932
14228
|
elementRef;
|
|
13933
14229
|
icons = CoreComponentsIcon;
|
|
14230
|
+
lovUtils = LovUtils;
|
|
13934
14231
|
set model(value) {
|
|
13935
14232
|
super.model = value;
|
|
13936
14233
|
this._setSelectedModel();
|
|
@@ -13953,7 +14250,7 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
13953
14250
|
collectionLoadFn;
|
|
13954
14251
|
collectionLoadFnProp;
|
|
13955
14252
|
leftIconData;
|
|
13956
|
-
searchPlaceholder;
|
|
14253
|
+
searchPlaceholder = '';
|
|
13957
14254
|
searchDisabled = false;
|
|
13958
14255
|
showChips = true;
|
|
13959
14256
|
showClass() {
|
|
@@ -13968,6 +14265,7 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
13968
14265
|
isLoading = false;
|
|
13969
14266
|
_collection = [];
|
|
13970
14267
|
debounceTimeout;
|
|
14268
|
+
_filterRequestId = 0;
|
|
13971
14269
|
_lovPopupComponentRef;
|
|
13972
14270
|
constructor(formComponent, iconCacheService, changeDetector, overlayService, formUserChangeListener, ngZoneWrapper, elementRef) {
|
|
13973
14271
|
super(changeDetector, overlayService, formUserChangeListener, ngZoneWrapper, elementRef);
|
|
@@ -13984,6 +14282,25 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
13984
14282
|
super.ngOnInit();
|
|
13985
14283
|
this._setSelectedModel();
|
|
13986
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
|
+
}
|
|
13987
14304
|
handleInputModelChange(model) {
|
|
13988
14305
|
if (this._lovPopupComponentRef) {
|
|
13989
14306
|
this._lovPopupComponentRef.instance.searchTerm = model;
|
|
@@ -13998,26 +14315,33 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
13998
14315
|
}
|
|
13999
14316
|
onModelChange(model) {
|
|
14000
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;
|
|
14001
14321
|
clearTimeout(this.debounceTimeout);
|
|
14002
14322
|
this.debounceTimeout = setTimeout(() => {
|
|
14003
|
-
this.applyFilter(model);
|
|
14323
|
+
this.applyFilter(model, requestId);
|
|
14004
14324
|
}, 300);
|
|
14005
14325
|
}
|
|
14006
|
-
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
|
+
}
|
|
14007
14331
|
if (text?.length < 3) {
|
|
14008
|
-
await new Promise(resolve => setTimeout(resolve, 300));
|
|
14009
14332
|
this.collection = undefined;
|
|
14333
|
+
this.filterText = text;
|
|
14334
|
+
this.closePopup();
|
|
14335
|
+
this.isLoading = false;
|
|
14336
|
+
this.changeDetector.detectChanges();
|
|
14337
|
+
return;
|
|
14010
14338
|
}
|
|
14011
|
-
|
|
14012
|
-
|
|
14013
|
-
|
|
14339
|
+
const loaded = await this.collectionLoadFn(text);
|
|
14340
|
+
if (requestId !== this._filterRequestId) {
|
|
14341
|
+
return;
|
|
14014
14342
|
}
|
|
14343
|
+
this.collection = loaded;
|
|
14015
14344
|
this.filterText = text;
|
|
14016
|
-
if (!this.collection) {
|
|
14017
|
-
this.changeDetector.detectChanges();
|
|
14018
|
-
this.isLoading = false;
|
|
14019
|
-
return [];
|
|
14020
|
-
}
|
|
14021
14345
|
this.filteredCollection = this.collection?.filter((item) => {
|
|
14022
14346
|
if (this.collectionLoadFnProp && this.collectionLoadFnProp.length > 0) {
|
|
14023
14347
|
return item[this.collectionLoadFnProp] && item[this.collectionLoadFnProp].toLowerCase().includes(text.toLowerCase());
|
|
@@ -14026,12 +14350,19 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
14026
14350
|
return true;
|
|
14027
14351
|
}
|
|
14028
14352
|
});
|
|
14029
|
-
(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
|
+
}
|
|
14030
14364
|
this.isLoading = false;
|
|
14031
14365
|
this.changeDetector.detectChanges();
|
|
14032
|
-
if (this._lovPopupComponentRef) {
|
|
14033
|
-
this._lovPopupComponentRef.instance.searchTerm = text;
|
|
14034
|
-
}
|
|
14035
14366
|
}
|
|
14036
14367
|
handleInputKeyDown(event) {
|
|
14037
14368
|
if (event) {
|
|
@@ -14076,6 +14407,11 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
14076
14407
|
if (this.readonly) {
|
|
14077
14408
|
return;
|
|
14078
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
|
+
}
|
|
14079
14415
|
this.isSelectOpen = true;
|
|
14080
14416
|
this._lovPopupComponentRef = this.overlayService.createComponent(ListOfValuesPopupComponent, {
|
|
14081
14417
|
parentForOverlay: this.elementRef,
|
|
@@ -14105,12 +14441,12 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
14105
14441
|
optionChosen(option) {
|
|
14106
14442
|
if (option) {
|
|
14107
14443
|
if (this.multiselect) {
|
|
14108
|
-
this.selectedModels = option.map(o => o
|
|
14444
|
+
this.selectedModels = option.map(o => LovUtils.getDisplayValue(o, this.displayField));
|
|
14109
14445
|
}
|
|
14110
14446
|
else {
|
|
14111
|
-
this.selectedModel = option
|
|
14447
|
+
this.selectedModel = LovUtils.getDisplayValue(option, this.displayField);
|
|
14112
14448
|
if (this.largeCollection) {
|
|
14113
|
-
this.filterText = option
|
|
14449
|
+
this.filterText = LovUtils.getDisplayValue(option, this.displayField);
|
|
14114
14450
|
}
|
|
14115
14451
|
}
|
|
14116
14452
|
}
|
|
@@ -14134,8 +14470,13 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
14134
14470
|
this.focused = false;
|
|
14135
14471
|
}
|
|
14136
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
|
+
}
|
|
14137
14478
|
if (!this.multiselect && this.selectedModel && this.collection) {
|
|
14138
|
-
const model = this.collection.find(c => c
|
|
14479
|
+
const model = this.collection.find(c => LovUtils.getDisplayValue(c, this.displayField) === this.selectedModel);
|
|
14139
14480
|
if (model) {
|
|
14140
14481
|
this.model = model;
|
|
14141
14482
|
}
|
|
@@ -14150,7 +14491,7 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
14150
14491
|
if (this.model) {
|
|
14151
14492
|
this.selectedModels.length = 0;
|
|
14152
14493
|
this.model.forEach(m => {
|
|
14153
|
-
this.selectedModels.push(m
|
|
14494
|
+
this.selectedModels.push(LovUtils.getDisplayValue(m, this.displayField));
|
|
14154
14495
|
});
|
|
14155
14496
|
}
|
|
14156
14497
|
else {
|
|
@@ -14159,13 +14500,14 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
14159
14500
|
}
|
|
14160
14501
|
else {
|
|
14161
14502
|
if (this.model) {
|
|
14162
|
-
this.selectedModel = this.model
|
|
14503
|
+
this.selectedModel = LovUtils.getDisplayValue(this.model, this.displayField);
|
|
14163
14504
|
if (this.largeCollection) {
|
|
14164
|
-
this.filterText = this.model
|
|
14505
|
+
this.filterText = LovUtils.getDisplayValue(this.model, this.displayField);
|
|
14165
14506
|
}
|
|
14166
14507
|
}
|
|
14167
14508
|
else {
|
|
14168
14509
|
this.selectedModel = '';
|
|
14510
|
+
this.filterText = '';
|
|
14169
14511
|
}
|
|
14170
14512
|
}
|
|
14171
14513
|
}
|
|
@@ -14177,59 +14519,47 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
14177
14519
|
useExisting: forwardRef(() => ListOfValuesComponent)
|
|
14178
14520
|
}
|
|
14179
14521
|
], viewQueries: [{ propertyName: "parentForOverlay", first: true, predicate: ["parentForOverlay"], descendants: true, read: ElementRef }], usesInheritance: true, ngImport: i0, template: `
|
|
14180
|
-
|
|
14181
|
-
|
|
14182
|
-
|
|
14183
|
-
|
|
14184
|
-
|
|
14185
|
-
|
|
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
|
-
<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>
|
|
14215
14557
|
<co-icon class="remove-chip-icon" [icon]="icons.CrossSkinny" (click)="removeOptionFromModel(chip)"></co-icon>
|
|
14216
|
-
|
|
14217
|
-
|
|
14218
|
-
|
|
14219
|
-
|
|
14220
|
-
|
|
14221
|
-
}
|
|
14222
|
-
|
|
14223
|
-
@if (largeCollection) {
|
|
14224
|
-
<co-input-text
|
|
14225
|
-
[model]="filterText"
|
|
14226
|
-
[placeholder]="label"
|
|
14227
|
-
[required]="required"
|
|
14228
|
-
[disabled]="disabled"
|
|
14229
|
-
[readonly]="readonly"
|
|
14230
|
-
(modelChange)="onModelChange($event)">
|
|
14231
|
-
</co-input-text>
|
|
14232
|
-
}
|
|
14558
|
+
</div>
|
|
14559
|
+
}
|
|
14560
|
+
</div>
|
|
14561
|
+
}
|
|
14562
|
+
</co-input-text>
|
|
14233
14563
|
@if (isLoading) {
|
|
14234
14564
|
<div class="filter-loader"><span></span></div>
|
|
14235
14565
|
}
|
|
@@ -14241,59 +14571,47 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
14241
14571
|
args: [{
|
|
14242
14572
|
selector: 'co-list-of-values',
|
|
14243
14573
|
template: `
|
|
14244
|
-
|
|
14245
|
-
|
|
14246
|
-
|
|
14247
|
-
|
|
14248
|
-
|
|
14249
|
-
|
|
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
|
-
<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>
|
|
14279
14609
|
<co-icon class="remove-chip-icon" [icon]="icons.CrossSkinny" (click)="removeOptionFromModel(chip)"></co-icon>
|
|
14280
|
-
|
|
14281
|
-
|
|
14282
|
-
|
|
14283
|
-
|
|
14284
|
-
|
|
14285
|
-
}
|
|
14286
|
-
|
|
14287
|
-
@if (largeCollection) {
|
|
14288
|
-
<co-input-text
|
|
14289
|
-
[model]="filterText"
|
|
14290
|
-
[placeholder]="label"
|
|
14291
|
-
[required]="required"
|
|
14292
|
-
[disabled]="disabled"
|
|
14293
|
-
[readonly]="readonly"
|
|
14294
|
-
(modelChange)="onModelChange($event)">
|
|
14295
|
-
</co-input-text>
|
|
14296
|
-
}
|
|
14610
|
+
</div>
|
|
14611
|
+
}
|
|
14612
|
+
</div>
|
|
14613
|
+
}
|
|
14614
|
+
</co-input-text>
|
|
14297
14615
|
@if (isLoading) {
|
|
14298
14616
|
<div class="filter-loader"><span></span></div>
|
|
14299
14617
|
}
|
|
@@ -16550,9 +16868,7 @@ class FilterItemModule {
|
|
|
16550
16868
|
ScrollingModule,
|
|
16551
16869
|
AppendPipeModule,
|
|
16552
16870
|
PrependPipeModule,
|
|
16553
|
-
InputTextModule,
|
|
16554
16871
|
InputRadioButtonModule,
|
|
16555
|
-
InputTextModule,
|
|
16556
16872
|
CoreComponentsTranslationModule,
|
|
16557
16873
|
InputDatePickerModule,
|
|
16558
16874
|
InputDateRangePickerModule], exports: [FilterItemComponent] });
|
|
@@ -16564,9 +16880,7 @@ class FilterItemModule {
|
|
|
16564
16880
|
ScrollingModule,
|
|
16565
16881
|
AppendPipeModule,
|
|
16566
16882
|
PrependPipeModule,
|
|
16567
|
-
InputTextModule,
|
|
16568
16883
|
InputRadioButtonModule,
|
|
16569
|
-
InputTextModule,
|
|
16570
16884
|
CoreComponentsTranslationModule,
|
|
16571
16885
|
InputDatePickerModule,
|
|
16572
16886
|
InputDateRangePickerModule] });
|
|
@@ -16583,9 +16897,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
16583
16897
|
ScrollingModule,
|
|
16584
16898
|
AppendPipeModule,
|
|
16585
16899
|
PrependPipeModule,
|
|
16586
|
-
InputTextModule,
|
|
16587
16900
|
InputRadioButtonModule,
|
|
16588
|
-
InputTextModule,
|
|
16589
16901
|
CoreComponentsTranslationModule,
|
|
16590
16902
|
InputDatePickerModule,
|
|
16591
16903
|
InputDateRangePickerModule
|