@colijnit/corecomponents_v12 261.20.17 → 261.20.19
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 +663 -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) => {
|
|
@@ -9148,6 +9337,9 @@ class InputNumberPickerComponent extends BaseInputComponent {
|
|
|
9148
9337
|
}
|
|
9149
9338
|
handleInputKeyDown(event) {
|
|
9150
9339
|
// event.preventDefault();
|
|
9340
|
+
if (this.readonly) {
|
|
9341
|
+
return false;
|
|
9342
|
+
}
|
|
9151
9343
|
if (event.code === 'Enter' || event.code === 'NumpadEnter') {
|
|
9152
9344
|
this.modelChange.next(this.model);
|
|
9153
9345
|
return false;
|
|
@@ -9155,13 +9347,40 @@ class InputNumberPickerComponent extends BaseInputComponent {
|
|
|
9155
9347
|
if (this.myKeyDownWhiteList.find((k) => k === event.keyCode) === undefined) {
|
|
9156
9348
|
return false;
|
|
9157
9349
|
}
|
|
9350
|
+
const currentText = this.input ? this.input.value : String(this.model ?? '');
|
|
9351
|
+
if (event.key === '.' || event.key === ',') {
|
|
9352
|
+
// only one decimal separator, and only the locale one: normalize a foreign '.'/',' to it
|
|
9353
|
+
if (/[.,]/.test(currentText)) {
|
|
9354
|
+
return false;
|
|
9355
|
+
}
|
|
9356
|
+
if (event.key !== this._numberLocale.decimalSeparator) {
|
|
9357
|
+
if (this.input) {
|
|
9358
|
+
this._numberLocale.insertDecimalSeparator(this.input);
|
|
9359
|
+
}
|
|
9360
|
+
return false;
|
|
9361
|
+
}
|
|
9362
|
+
}
|
|
9363
|
+
// native text/number inputs ignore maxlength, so enforce maxLength (precision) and decimals (scale) here
|
|
9364
|
+
if (/^\d$/.test(event.key) && NumberUtils.WouldExceedDigitLimits(currentText, this.maxLength, this.decimals)) {
|
|
9365
|
+
return false;
|
|
9366
|
+
}
|
|
9367
|
+
}
|
|
9368
|
+
// precision/scale is enforced in keydown; the native maxlength on this text input would wrongly count
|
|
9369
|
+
// the decimal separator as a character (e.g. blocking "1234567,89" at maxLength 9), so don't set it.
|
|
9370
|
+
_setNativeMaxLength() {
|
|
9158
9371
|
}
|
|
9159
9372
|
handleBlur() {
|
|
9373
|
+
// normalize the display once editing stops (e.g. "12," -> "12", trailing zeros dropped)
|
|
9374
|
+
this._displayValue = this._numberLocale.format(this.model);
|
|
9160
9375
|
this.modelChange.next(this.model);
|
|
9161
9376
|
}
|
|
9162
|
-
handleChangeModel(
|
|
9377
|
+
handleChangeModel(text) {
|
|
9163
9378
|
this._changeFromButton = false;
|
|
9164
|
-
|
|
9379
|
+
// preserve exactly what the user typed while they are typing (avoids caret jumps / eating the separator)
|
|
9380
|
+
this._userTyping = true;
|
|
9381
|
+
this._displayValue = text === null || text === undefined ? '' : '' + text;
|
|
9382
|
+
this.numberLogic.setValue(this._numberLocale.parse(text));
|
|
9383
|
+
this._userTyping = false;
|
|
9165
9384
|
}
|
|
9166
9385
|
// Note: recursive through setTimeout().
|
|
9167
9386
|
doDecrementAuto() {
|
|
@@ -9263,7 +9482,7 @@ class InputNumberPickerComponent extends BaseInputComponent {
|
|
|
9263
9482
|
break;
|
|
9264
9483
|
}
|
|
9265
9484
|
}
|
|
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 });
|
|
9485
|
+
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
9486
|
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
9487
|
OverlayService, {
|
|
9269
9488
|
provide: SCREEN_CONFIG_ADAPTER_COMPONENT_INTERFACE_NAME, useExisting: forwardRef(() => InputNumberPickerComponent)
|
|
@@ -9289,15 +9508,15 @@ class InputNumberPickerComponent extends BaseInputComponent {
|
|
|
9289
9508
|
</div>
|
|
9290
9509
|
<div class="input-wrapper">
|
|
9291
9510
|
@if (showPermanentLabel) {
|
|
9292
|
-
<span class='permanent-label' [textContent]="label"></span>
|
|
9511
|
+
<span class='permanent-label' [textContent]="label ?? ''"></span>
|
|
9293
9512
|
}
|
|
9294
|
-
<input type="
|
|
9513
|
+
<input type="text" inputmode="decimal"
|
|
9295
9514
|
[tabIndex]="readonly ? -1 : 0"
|
|
9296
|
-
[ngModel]="
|
|
9515
|
+
[ngModel]="displayValue"
|
|
9297
9516
|
[readonly]="readonly"
|
|
9298
9517
|
[disabled]="disabled"
|
|
9299
9518
|
[required]="required"
|
|
9300
|
-
[placeholder]="label"
|
|
9519
|
+
[placeholder]="label ?? ''"
|
|
9301
9520
|
(ngModelChange)="handleChangeModel($event)"
|
|
9302
9521
|
(keydown)="handleInputKeyDown($event)"
|
|
9303
9522
|
(blur)="handleBlur()"/>
|
|
@@ -9311,7 +9530,7 @@ class InputNumberPickerComponent extends BaseInputComponent {
|
|
|
9311
9530
|
(mouseup)="stopAutoCounting()" (mouseleave)="stopAutoCounting()"></co-button>
|
|
9312
9531
|
}
|
|
9313
9532
|
</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.
|
|
9533
|
+
`, 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
9534
|
}
|
|
9316
9535
|
__decorate([
|
|
9317
9536
|
InputBoolean()
|
|
@@ -9338,15 +9557,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
9338
9557
|
</div>
|
|
9339
9558
|
<div class="input-wrapper">
|
|
9340
9559
|
@if (showPermanentLabel) {
|
|
9341
|
-
<span class='permanent-label' [textContent]="label"></span>
|
|
9560
|
+
<span class='permanent-label' [textContent]="label ?? ''"></span>
|
|
9342
9561
|
}
|
|
9343
|
-
<input type="
|
|
9562
|
+
<input type="text" inputmode="decimal"
|
|
9344
9563
|
[tabIndex]="readonly ? -1 : 0"
|
|
9345
|
-
[ngModel]="
|
|
9564
|
+
[ngModel]="displayValue"
|
|
9346
9565
|
[readonly]="readonly"
|
|
9347
9566
|
[disabled]="disabled"
|
|
9348
9567
|
[required]="required"
|
|
9349
|
-
[placeholder]="label"
|
|
9568
|
+
[placeholder]="label ?? ''"
|
|
9350
9569
|
(ngModelChange)="handleChangeModel($event)"
|
|
9351
9570
|
(keydown)="handleInputKeyDown($event)"
|
|
9352
9571
|
(blur)="handleBlur()"/>
|
|
@@ -9378,7 +9597,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
9378
9597
|
}] }, { type: IconCacheService, decorators: [{
|
|
9379
9598
|
type: Inject,
|
|
9380
9599
|
args: [IconCacheService]
|
|
9381
|
-
}] }, { type: OverlayService }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: FormInputUserModelChangeListenerService }, { type: NgZoneWrapperService }, { type: i0.ElementRef }], propDecorators: { model: [{
|
|
9600
|
+
}] }, { type: OverlayService }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: FormInputUserModelChangeListenerService }, { type: NumberLocaleService }, { type: NgZoneWrapperService }, { type: i0.ElementRef }], propDecorators: { model: [{
|
|
9382
9601
|
type: Input
|
|
9383
9602
|
}], modelChangeOnEnter: [{
|
|
9384
9603
|
type: Input
|
|
@@ -13527,6 +13746,46 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
13527
13746
|
}]
|
|
13528
13747
|
}] });
|
|
13529
13748
|
|
|
13749
|
+
class LovUtils {
|
|
13750
|
+
static getDisplayValue(model, displayField) {
|
|
13751
|
+
if (!model || !displayField) {
|
|
13752
|
+
return '';
|
|
13753
|
+
}
|
|
13754
|
+
return displayField
|
|
13755
|
+
.split('|')
|
|
13756
|
+
.map(field => model[field.trim()])
|
|
13757
|
+
.filter(val => val != null && val !== '')
|
|
13758
|
+
.join(' - ');
|
|
13759
|
+
}
|
|
13760
|
+
static getHighlightParts(value, term) {
|
|
13761
|
+
const text = value ?? '';
|
|
13762
|
+
if (!text || !term) {
|
|
13763
|
+
return [{ text: text, match: false }];
|
|
13764
|
+
}
|
|
13765
|
+
const regex = new RegExp(LovUtils._escapeRegExp(term), 'gi');
|
|
13766
|
+
const parts = [];
|
|
13767
|
+
let lastIndex = 0;
|
|
13768
|
+
let match;
|
|
13769
|
+
while ((match = regex.exec(text)) !== null) {
|
|
13770
|
+
if (match.index > lastIndex) {
|
|
13771
|
+
parts.push({ text: text.slice(lastIndex, match.index), match: false });
|
|
13772
|
+
}
|
|
13773
|
+
parts.push({ text: match[0], match: true });
|
|
13774
|
+
lastIndex = match.index + match[0].length;
|
|
13775
|
+
if (match.index === regex.lastIndex) {
|
|
13776
|
+
regex.lastIndex++;
|
|
13777
|
+
}
|
|
13778
|
+
}
|
|
13779
|
+
if (lastIndex < text.length) {
|
|
13780
|
+
parts.push({ text: text.slice(lastIndex), match: false });
|
|
13781
|
+
}
|
|
13782
|
+
return parts;
|
|
13783
|
+
}
|
|
13784
|
+
static _escapeRegExp(value) {
|
|
13785
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
13786
|
+
}
|
|
13787
|
+
}
|
|
13788
|
+
|
|
13530
13789
|
class ListOfValuesPopupComponent {
|
|
13531
13790
|
iconCacheService;
|
|
13532
13791
|
_elementRef;
|
|
@@ -13647,7 +13906,11 @@ class ListOfValuesPopupComponent {
|
|
|
13647
13906
|
}
|
|
13648
13907
|
}
|
|
13649
13908
|
selectModelByViewModel(viewModel, closePopup = true) {
|
|
13650
|
-
|
|
13909
|
+
const found = this.viewModelsMain.find(vm => vm === viewModel);
|
|
13910
|
+
if (!found) {
|
|
13911
|
+
return;
|
|
13912
|
+
}
|
|
13913
|
+
this.model = found.model;
|
|
13651
13914
|
this.modelChange.emit(this.model);
|
|
13652
13915
|
this._scrollIntoView();
|
|
13653
13916
|
if (closePopup) {
|
|
@@ -13660,7 +13923,7 @@ class ListOfValuesPopupComponent {
|
|
|
13660
13923
|
this.selectNextOption();
|
|
13661
13924
|
}
|
|
13662
13925
|
if (!this.model && this.searchTerm) {
|
|
13663
|
-
const wishModel = this.viewModelsMain.find(vmm => vmm.model
|
|
13926
|
+
const wishModel = this.viewModelsMain.find(vmm => LovUtils.getDisplayValue(vmm.model, this.displayField) === this.searchTerm);
|
|
13664
13927
|
if (wishModel) {
|
|
13665
13928
|
this.selectViewModel(wishModel);
|
|
13666
13929
|
}
|
|
@@ -13680,6 +13943,9 @@ class ListOfValuesPopupComponent {
|
|
|
13680
13943
|
this.modelChange.emit(this.model);
|
|
13681
13944
|
}
|
|
13682
13945
|
selectNextOption(back = false) {
|
|
13946
|
+
if (this.viewModels.length === 0) {
|
|
13947
|
+
return;
|
|
13948
|
+
}
|
|
13683
13949
|
let nextModel;
|
|
13684
13950
|
if (!this.highLightModel) {
|
|
13685
13951
|
nextModel = this.viewModels[back ? this.viewModels.length - 1 : 0];
|
|
@@ -13733,8 +13999,8 @@ class ListOfValuesPopupComponent {
|
|
|
13733
13999
|
}
|
|
13734
14000
|
if (!this.model)
|
|
13735
14001
|
return false;
|
|
13736
|
-
const selected = this.model
|
|
13737
|
-
const current = vm.model
|
|
14002
|
+
const selected = LovUtils.getDisplayValue(this.model, this.displayField);
|
|
14003
|
+
const current = LovUtils.getDisplayValue(vm.model, this.displayField);
|
|
13738
14004
|
return selected != null && current != null && selected === current;
|
|
13739
14005
|
}
|
|
13740
14006
|
_prepareViewModelsMain() {
|
|
@@ -13755,6 +14021,9 @@ class ListOfValuesPopupComponent {
|
|
|
13755
14021
|
}
|
|
13756
14022
|
});
|
|
13757
14023
|
});
|
|
14024
|
+
this.viewModels.forEach((vm) => {
|
|
14025
|
+
vm.highlightParts = LovUtils.getHighlightParts(LovUtils.getDisplayValue(vm.model, this.displayField), this.searchTerm);
|
|
14026
|
+
});
|
|
13758
14027
|
}
|
|
13759
14028
|
_scrollIntoView() {
|
|
13760
14029
|
const activeIndex = this.viewModels.findIndex(vmm => vmm === this.highLightModel);
|
|
@@ -13783,102 +14052,126 @@ class ListOfValuesPopupComponent {
|
|
|
13783
14052
|
}
|
|
13784
14053
|
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
14054
|
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
|
-
|
|
14055
|
+
<div class="lov-options" [overlay]="parentForOverlay" [inheritWidth]="true" [ngClass]="customCssClass"
|
|
14056
|
+
id="lov-popup"
|
|
14057
|
+
role="listbox" [tabindex]="-1"
|
|
14058
|
+
(clickOutside)="closePopup.emit($event)">
|
|
14059
|
+
@if (multiselect) {
|
|
14060
|
+
<co-input-search
|
|
14061
|
+
tabindex="-1"
|
|
14062
|
+
[(model)]="searchTerm"
|
|
14063
|
+
[placeholder]="searchPlaceholder"
|
|
14064
|
+
(keydown)="handleInputKeyDown($event)"
|
|
14065
|
+
(modelChange)="filterViewModels()"></co-input-search>
|
|
14066
|
+
}
|
|
14067
|
+
@if (showToggleAll && multiselect) {
|
|
14068
|
+
<div class="row gap">
|
|
14069
|
+
<co-input-checkbox [model]="allSelected" (modelChange)="toggleAll()"></co-input-checkbox>
|
|
14070
|
+
<span [textContent]="'DESELECT_ALL' | coreLocalize" (click)="toggleAll()"></span>
|
|
14071
|
+
</div>
|
|
14072
|
+
}
|
|
14073
|
+
<ul class="dropdown-list" #dropDownList>
|
|
14074
|
+
@for (viewModel of viewModels; track viewModel; let index = $index) {
|
|
14075
|
+
<li
|
|
14076
|
+
#lovItem
|
|
14077
|
+
[class.selected]="viewModel === highLightModel || viewModels.length === 1"
|
|
14078
|
+
[class.active]="isActive(viewModel)"
|
|
14079
|
+
[class.highlighted]="viewModel === highLightModel"
|
|
14080
|
+
[attr.aria-selected]="isActive(viewModel)"
|
|
14081
|
+
(click)="selectViewModel(viewModel, !multiselect)"
|
|
14082
|
+
role="option">
|
|
14083
|
+
@if (!multiselect) {
|
|
14084
|
+
@if (viewModel.model[optionIcon]) {
|
|
14085
|
+
<co-icon class="input-text-left-icon" [iconData]="iconCacheService.getIcon(viewModel.model[optionIcon])">
|
|
14086
|
+
</co-icon>
|
|
14087
|
+
}
|
|
14088
|
+
<ng-container [ngTemplateOutlet]="optionText" [ngTemplateOutletContext]="{parts: viewModel.highlightParts}"></ng-container>
|
|
14089
|
+
}
|
|
14090
|
+
@if (multiselect) {
|
|
14091
|
+
<co-input-checkbox [model]="viewModel.checked"
|
|
14092
|
+
(modelChange)="selectViewModel(viewModel, false)"></co-input-checkbox>
|
|
14093
|
+
<ng-container [ngTemplateOutlet]="optionText" [ngTemplateOutletContext]="{parts: viewModel.highlightParts}"></ng-container>
|
|
14094
|
+
}
|
|
14095
|
+
</li>
|
|
13818
14096
|
}
|
|
13819
|
-
|
|
13820
|
-
|
|
13821
|
-
|
|
13822
|
-
|
|
13823
|
-
|
|
13824
|
-
|
|
13825
|
-
|
|
13826
|
-
|
|
13827
|
-
|
|
13828
|
-
|
|
13829
|
-
|
|
13830
|
-
|
|
14097
|
+
</ul>
|
|
14098
|
+
</div>
|
|
14099
|
+
|
|
14100
|
+
<ng-template #optionText let-parts="parts">
|
|
14101
|
+
<span class="lov-options-text">
|
|
14102
|
+
@for (part of parts; track $index) {
|
|
14103
|
+
@if (part.match) {
|
|
14104
|
+
<mark class="lov-highlight" [textContent]="part.text"></mark>
|
|
14105
|
+
} @else {
|
|
14106
|
+
<span [textContent]="part.text"></span>
|
|
14107
|
+
}
|
|
14108
|
+
}
|
|
14109
|
+
</span>
|
|
14110
|
+
</ng-template>
|
|
14111
|
+
`, 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
14112
|
}
|
|
13832
14113
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ListOfValuesPopupComponent, decorators: [{
|
|
13833
14114
|
type: Component,
|
|
13834
14115
|
args: [{
|
|
13835
14116
|
selector: 'co-list-of-values-popup',
|
|
13836
14117
|
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
|
-
|
|
14118
|
+
<div class="lov-options" [overlay]="parentForOverlay" [inheritWidth]="true" [ngClass]="customCssClass"
|
|
14119
|
+
id="lov-popup"
|
|
14120
|
+
role="listbox" [tabindex]="-1"
|
|
14121
|
+
(clickOutside)="closePopup.emit($event)">
|
|
14122
|
+
@if (multiselect) {
|
|
14123
|
+
<co-input-search
|
|
14124
|
+
tabindex="-1"
|
|
14125
|
+
[(model)]="searchTerm"
|
|
14126
|
+
[placeholder]="searchPlaceholder"
|
|
14127
|
+
(keydown)="handleInputKeyDown($event)"
|
|
14128
|
+
(modelChange)="filterViewModels()"></co-input-search>
|
|
14129
|
+
}
|
|
14130
|
+
@if (showToggleAll && multiselect) {
|
|
14131
|
+
<div class="row gap">
|
|
14132
|
+
<co-input-checkbox [model]="allSelected" (modelChange)="toggleAll()"></co-input-checkbox>
|
|
14133
|
+
<span [textContent]="'DESELECT_ALL' | coreLocalize" (click)="toggleAll()"></span>
|
|
14134
|
+
</div>
|
|
14135
|
+
}
|
|
14136
|
+
<ul class="dropdown-list" #dropDownList>
|
|
14137
|
+
@for (viewModel of viewModels; track viewModel; let index = $index) {
|
|
14138
|
+
<li
|
|
14139
|
+
#lovItem
|
|
14140
|
+
[class.selected]="viewModel === highLightModel || viewModels.length === 1"
|
|
14141
|
+
[class.active]="isActive(viewModel)"
|
|
14142
|
+
[class.highlighted]="viewModel === highLightModel"
|
|
14143
|
+
[attr.aria-selected]="isActive(viewModel)"
|
|
14144
|
+
(click)="selectViewModel(viewModel, !multiselect)"
|
|
14145
|
+
role="option">
|
|
14146
|
+
@if (!multiselect) {
|
|
14147
|
+
@if (viewModel.model[optionIcon]) {
|
|
14148
|
+
<co-icon class="input-text-left-icon" [iconData]="iconCacheService.getIcon(viewModel.model[optionIcon])">
|
|
14149
|
+
</co-icon>
|
|
14150
|
+
}
|
|
14151
|
+
<ng-container [ngTemplateOutlet]="optionText" [ngTemplateOutletContext]="{parts: viewModel.highlightParts}"></ng-container>
|
|
14152
|
+
}
|
|
14153
|
+
@if (multiselect) {
|
|
14154
|
+
<co-input-checkbox [model]="viewModel.checked"
|
|
14155
|
+
(modelChange)="selectViewModel(viewModel, false)"></co-input-checkbox>
|
|
14156
|
+
<ng-container [ngTemplateOutlet]="optionText" [ngTemplateOutletContext]="{parts: viewModel.highlightParts}"></ng-container>
|
|
14157
|
+
}
|
|
14158
|
+
</li>
|
|
13869
14159
|
}
|
|
13870
|
-
|
|
13871
|
-
|
|
13872
|
-
|
|
13873
|
-
|
|
13874
|
-
|
|
13875
|
-
|
|
13876
|
-
|
|
13877
|
-
|
|
13878
|
-
|
|
13879
|
-
|
|
13880
|
-
|
|
13881
|
-
|
|
14160
|
+
</ul>
|
|
14161
|
+
</div>
|
|
14162
|
+
|
|
14163
|
+
<ng-template #optionText let-parts="parts">
|
|
14164
|
+
<span class="lov-options-text">
|
|
14165
|
+
@for (part of parts; track $index) {
|
|
14166
|
+
@if (part.match) {
|
|
14167
|
+
<mark class="lov-highlight" [textContent]="part.text"></mark>
|
|
14168
|
+
} @else {
|
|
14169
|
+
<span [textContent]="part.text"></span>
|
|
14170
|
+
}
|
|
14171
|
+
}
|
|
14172
|
+
</span>
|
|
14173
|
+
</ng-template>
|
|
14174
|
+
`,
|
|
13882
14175
|
encapsulation: ViewEncapsulation.None,
|
|
13883
14176
|
standalone: false
|
|
13884
14177
|
}]
|
|
@@ -13937,6 +14230,7 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
13937
14230
|
ngZoneWrapper;
|
|
13938
14231
|
elementRef;
|
|
13939
14232
|
icons = CoreComponentsIcon;
|
|
14233
|
+
lovUtils = LovUtils;
|
|
13940
14234
|
set model(value) {
|
|
13941
14235
|
super.model = value;
|
|
13942
14236
|
this._setSelectedModel();
|
|
@@ -13959,7 +14253,7 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
13959
14253
|
collectionLoadFn;
|
|
13960
14254
|
collectionLoadFnProp;
|
|
13961
14255
|
leftIconData;
|
|
13962
|
-
searchPlaceholder;
|
|
14256
|
+
searchPlaceholder = '';
|
|
13963
14257
|
searchDisabled = false;
|
|
13964
14258
|
showChips = true;
|
|
13965
14259
|
showClass() {
|
|
@@ -13974,6 +14268,7 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
13974
14268
|
isLoading = false;
|
|
13975
14269
|
_collection = [];
|
|
13976
14270
|
debounceTimeout;
|
|
14271
|
+
_filterRequestId = 0;
|
|
13977
14272
|
_lovPopupComponentRef;
|
|
13978
14273
|
constructor(formComponent, iconCacheService, changeDetector, overlayService, formUserChangeListener, ngZoneWrapper, elementRef) {
|
|
13979
14274
|
super(changeDetector, overlayService, formUserChangeListener, ngZoneWrapper, elementRef);
|
|
@@ -13990,6 +14285,25 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
13990
14285
|
super.ngOnInit();
|
|
13991
14286
|
this._setSelectedModel();
|
|
13992
14287
|
}
|
|
14288
|
+
// Value shown in the input: the search text while fetching (largeCollection), otherwise the
|
|
14289
|
+
// selected model(s). Lets a single <co-input-text> serve both modes without a template split.
|
|
14290
|
+
get inputModel() {
|
|
14291
|
+
if (this.largeCollection) {
|
|
14292
|
+
return this.filterText;
|
|
14293
|
+
}
|
|
14294
|
+
if (this.multiselect) {
|
|
14295
|
+
return (!this.selectedModels || this.selectedModels.length === 0) ? null : this.selectedModels;
|
|
14296
|
+
}
|
|
14297
|
+
return this.selectedModel;
|
|
14298
|
+
}
|
|
14299
|
+
handleModelChange(model) {
|
|
14300
|
+
if (this.largeCollection) {
|
|
14301
|
+
this.onModelChange(model);
|
|
14302
|
+
}
|
|
14303
|
+
else {
|
|
14304
|
+
this.handleInputModelChange(model);
|
|
14305
|
+
}
|
|
14306
|
+
}
|
|
13993
14307
|
handleInputModelChange(model) {
|
|
13994
14308
|
if (this._lovPopupComponentRef) {
|
|
13995
14309
|
this._lovPopupComponentRef.instance.searchTerm = model;
|
|
@@ -14004,26 +14318,33 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
14004
14318
|
}
|
|
14005
14319
|
onModelChange(model) {
|
|
14006
14320
|
this.isLoading = true;
|
|
14321
|
+
// Mark this keystroke as the latest request immediately, so an older in-flight
|
|
14322
|
+
// request that resolves within the debounce window is still discarded.
|
|
14323
|
+
const requestId = ++this._filterRequestId;
|
|
14007
14324
|
clearTimeout(this.debounceTimeout);
|
|
14008
14325
|
this.debounceTimeout = setTimeout(() => {
|
|
14009
|
-
this.applyFilter(model);
|
|
14326
|
+
this.applyFilter(model, requestId);
|
|
14010
14327
|
}, 300);
|
|
14011
14328
|
}
|
|
14012
|
-
async applyFilter(text) {
|
|
14329
|
+
async applyFilter(text, requestId = ++this._filterRequestId) {
|
|
14330
|
+
await new Promise(resolve => setTimeout(resolve, 300));
|
|
14331
|
+
if (requestId !== this._filterRequestId) {
|
|
14332
|
+
return;
|
|
14333
|
+
}
|
|
14013
14334
|
if (text?.length < 3) {
|
|
14014
|
-
await new Promise(resolve => setTimeout(resolve, 300));
|
|
14015
14335
|
this.collection = undefined;
|
|
14336
|
+
this.filterText = text;
|
|
14337
|
+
this.closePopup();
|
|
14338
|
+
this.isLoading = false;
|
|
14339
|
+
this.changeDetector.detectChanges();
|
|
14340
|
+
return;
|
|
14016
14341
|
}
|
|
14017
|
-
|
|
14018
|
-
|
|
14019
|
-
|
|
14342
|
+
const loaded = await this.collectionLoadFn(text);
|
|
14343
|
+
if (requestId !== this._filterRequestId) {
|
|
14344
|
+
return;
|
|
14020
14345
|
}
|
|
14346
|
+
this.collection = loaded;
|
|
14021
14347
|
this.filterText = text;
|
|
14022
|
-
if (!this.collection) {
|
|
14023
|
-
this.changeDetector.detectChanges();
|
|
14024
|
-
this.isLoading = false;
|
|
14025
|
-
return [];
|
|
14026
|
-
}
|
|
14027
14348
|
this.filteredCollection = this.collection?.filter((item) => {
|
|
14028
14349
|
if (this.collectionLoadFnProp && this.collectionLoadFnProp.length > 0) {
|
|
14029
14350
|
return item[this.collectionLoadFnProp] && item[this.collectionLoadFnProp].toLowerCase().includes(text.toLowerCase());
|
|
@@ -14032,12 +14353,19 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
14032
14353
|
return true;
|
|
14033
14354
|
}
|
|
14034
14355
|
});
|
|
14035
|
-
(this.filteredCollection?.length > 0 && this.filterText?.length > 2)
|
|
14356
|
+
if (this.filteredCollection?.length > 0 && this.filterText?.length > 2) {
|
|
14357
|
+
this.openPopup(); // no-op when already open
|
|
14358
|
+
if (this._lovPopupComponentRef) {
|
|
14359
|
+
// Refresh the open popup in place; no re-create, so no flicker.
|
|
14360
|
+
this._lovPopupComponentRef.instance.collection = this.collection;
|
|
14361
|
+
this._lovPopupComponentRef.instance.searchTerm = text;
|
|
14362
|
+
}
|
|
14363
|
+
}
|
|
14364
|
+
else {
|
|
14365
|
+
this.closePopup();
|
|
14366
|
+
}
|
|
14036
14367
|
this.isLoading = false;
|
|
14037
14368
|
this.changeDetector.detectChanges();
|
|
14038
|
-
if (this._lovPopupComponentRef) {
|
|
14039
|
-
this._lovPopupComponentRef.instance.searchTerm = text;
|
|
14040
|
-
}
|
|
14041
14369
|
}
|
|
14042
14370
|
handleInputKeyDown(event) {
|
|
14043
14371
|
if (event) {
|
|
@@ -14082,6 +14410,11 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
14082
14410
|
if (this.readonly) {
|
|
14083
14411
|
return;
|
|
14084
14412
|
}
|
|
14413
|
+
// Idempotent: keep the existing popup so continued typing refreshes it in place
|
|
14414
|
+
// instead of re-creating it (which would replay the open animation / flicker).
|
|
14415
|
+
if (this._lovPopupComponentRef) {
|
|
14416
|
+
return;
|
|
14417
|
+
}
|
|
14085
14418
|
this.isSelectOpen = true;
|
|
14086
14419
|
this._lovPopupComponentRef = this.overlayService.createComponent(ListOfValuesPopupComponent, {
|
|
14087
14420
|
parentForOverlay: this.elementRef,
|
|
@@ -14111,12 +14444,12 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
14111
14444
|
optionChosen(option) {
|
|
14112
14445
|
if (option) {
|
|
14113
14446
|
if (this.multiselect) {
|
|
14114
|
-
this.selectedModels = option.map(o => o
|
|
14447
|
+
this.selectedModels = option.map(o => LovUtils.getDisplayValue(o, this.displayField));
|
|
14115
14448
|
}
|
|
14116
14449
|
else {
|
|
14117
|
-
this.selectedModel = option
|
|
14450
|
+
this.selectedModel = LovUtils.getDisplayValue(option, this.displayField);
|
|
14118
14451
|
if (this.largeCollection) {
|
|
14119
|
-
this.filterText = option
|
|
14452
|
+
this.filterText = LovUtils.getDisplayValue(option, this.displayField);
|
|
14120
14453
|
}
|
|
14121
14454
|
}
|
|
14122
14455
|
}
|
|
@@ -14140,8 +14473,13 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
14140
14473
|
this.focused = false;
|
|
14141
14474
|
}
|
|
14142
14475
|
checkModel() {
|
|
14476
|
+
if (this.largeCollection) {
|
|
14477
|
+
// The input holds the search text (not a to-be-resolved value) and selection happens via the
|
|
14478
|
+
// popup, so blur must not try to match/clear the model here.
|
|
14479
|
+
return;
|
|
14480
|
+
}
|
|
14143
14481
|
if (!this.multiselect && this.selectedModel && this.collection) {
|
|
14144
|
-
const model = this.collection.find(c => c
|
|
14482
|
+
const model = this.collection.find(c => LovUtils.getDisplayValue(c, this.displayField) === this.selectedModel);
|
|
14145
14483
|
if (model) {
|
|
14146
14484
|
this.model = model;
|
|
14147
14485
|
}
|
|
@@ -14156,7 +14494,7 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
14156
14494
|
if (this.model) {
|
|
14157
14495
|
this.selectedModels.length = 0;
|
|
14158
14496
|
this.model.forEach(m => {
|
|
14159
|
-
this.selectedModels.push(m
|
|
14497
|
+
this.selectedModels.push(LovUtils.getDisplayValue(m, this.displayField));
|
|
14160
14498
|
});
|
|
14161
14499
|
}
|
|
14162
14500
|
else {
|
|
@@ -14165,13 +14503,14 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
14165
14503
|
}
|
|
14166
14504
|
else {
|
|
14167
14505
|
if (this.model) {
|
|
14168
|
-
this.selectedModel = this.model
|
|
14506
|
+
this.selectedModel = LovUtils.getDisplayValue(this.model, this.displayField);
|
|
14169
14507
|
if (this.largeCollection) {
|
|
14170
|
-
this.filterText = this.model
|
|
14508
|
+
this.filterText = LovUtils.getDisplayValue(this.model, this.displayField);
|
|
14171
14509
|
}
|
|
14172
14510
|
}
|
|
14173
14511
|
else {
|
|
14174
14512
|
this.selectedModel = '';
|
|
14513
|
+
this.filterText = '';
|
|
14175
14514
|
}
|
|
14176
14515
|
}
|
|
14177
14516
|
}
|
|
@@ -14183,59 +14522,47 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
14183
14522
|
useExisting: forwardRef(() => ListOfValuesComponent)
|
|
14184
14523
|
}
|
|
14185
14524
|
], 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
|
|
14525
|
+
<co-input-text
|
|
14526
|
+
aria-haspopup="listbox"
|
|
14527
|
+
[attr.aria-expanded]="isSelectOpen"
|
|
14528
|
+
aria-controls="lov-popup"
|
|
14529
|
+
role="combobox"
|
|
14530
|
+
class="no-focus-line"
|
|
14531
|
+
overlayParent
|
|
14532
|
+
#parentForOverlay="overlayParent"
|
|
14533
|
+
type="text"
|
|
14534
|
+
[id]="label"
|
|
14535
|
+
[model]="inputModel"
|
|
14536
|
+
[label]="label"
|
|
14537
|
+
[placeholder]="searchPlaceholder"
|
|
14538
|
+
[myFormInputInstance]="this"
|
|
14539
|
+
[readonly]="readonly"
|
|
14540
|
+
[disabled]="disabled"
|
|
14541
|
+
[required]="required"
|
|
14542
|
+
[noClickFocus]="false"
|
|
14543
|
+
[leftIconData]=" model && model[optionIcon] ? iconCacheService.getIcon(model[optionIcon]) : leftIconData"
|
|
14544
|
+
[rightIcon]="isSelectOpen ? icons.ChevronUpRegular : icons.ChevronDownRegular"
|
|
14545
|
+
[showClearButton]="true"
|
|
14546
|
+
[useContent]="multiselect"
|
|
14547
|
+
[customHeight]="multiselect"
|
|
14548
|
+
[keepFocussed]="keepFocussed"
|
|
14549
|
+
(modelChange)="handleModelChange($event)"
|
|
14550
|
+
(click)="openPopup()"
|
|
14551
|
+
(rightIconClick)="toggleSelect()"
|
|
14552
|
+
(keydown)="handleInputKeyDown($event)"
|
|
14553
|
+
(clearIconClick)="clearModel($event)"
|
|
14554
|
+
(blur)="checkModel()">
|
|
14555
|
+
@if (multiselect && showChips) {
|
|
14556
|
+
<div class="multiselect-chips-wrapper">
|
|
14557
|
+
@for (chip of model; track chip) {
|
|
14558
|
+
<div class="chips">
|
|
14559
|
+
<span class="chips-description" [textContent]="lovUtils.getDisplayValue(chip, displayField)"></span>
|
|
14221
14560
|
<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
|
-
}
|
|
14561
|
+
</div>
|
|
14562
|
+
}
|
|
14563
|
+
</div>
|
|
14564
|
+
}
|
|
14565
|
+
</co-input-text>
|
|
14239
14566
|
@if (isLoading) {
|
|
14240
14567
|
<div class="filter-loader"><span></span></div>
|
|
14241
14568
|
}
|
|
@@ -14247,59 +14574,47 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
14247
14574
|
args: [{
|
|
14248
14575
|
selector: 'co-list-of-values',
|
|
14249
14576
|
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
|
|
14577
|
+
<co-input-text
|
|
14578
|
+
aria-haspopup="listbox"
|
|
14579
|
+
[attr.aria-expanded]="isSelectOpen"
|
|
14580
|
+
aria-controls="lov-popup"
|
|
14581
|
+
role="combobox"
|
|
14582
|
+
class="no-focus-line"
|
|
14583
|
+
overlayParent
|
|
14584
|
+
#parentForOverlay="overlayParent"
|
|
14585
|
+
type="text"
|
|
14586
|
+
[id]="label"
|
|
14587
|
+
[model]="inputModel"
|
|
14588
|
+
[label]="label"
|
|
14589
|
+
[placeholder]="searchPlaceholder"
|
|
14590
|
+
[myFormInputInstance]="this"
|
|
14591
|
+
[readonly]="readonly"
|
|
14592
|
+
[disabled]="disabled"
|
|
14593
|
+
[required]="required"
|
|
14594
|
+
[noClickFocus]="false"
|
|
14595
|
+
[leftIconData]=" model && model[optionIcon] ? iconCacheService.getIcon(model[optionIcon]) : leftIconData"
|
|
14596
|
+
[rightIcon]="isSelectOpen ? icons.ChevronUpRegular : icons.ChevronDownRegular"
|
|
14597
|
+
[showClearButton]="true"
|
|
14598
|
+
[useContent]="multiselect"
|
|
14599
|
+
[customHeight]="multiselect"
|
|
14600
|
+
[keepFocussed]="keepFocussed"
|
|
14601
|
+
(modelChange)="handleModelChange($event)"
|
|
14602
|
+
(click)="openPopup()"
|
|
14603
|
+
(rightIconClick)="toggleSelect()"
|
|
14604
|
+
(keydown)="handleInputKeyDown($event)"
|
|
14605
|
+
(clearIconClick)="clearModel($event)"
|
|
14606
|
+
(blur)="checkModel()">
|
|
14607
|
+
@if (multiselect && showChips) {
|
|
14608
|
+
<div class="multiselect-chips-wrapper">
|
|
14609
|
+
@for (chip of model; track chip) {
|
|
14610
|
+
<div class="chips">
|
|
14611
|
+
<span class="chips-description" [textContent]="lovUtils.getDisplayValue(chip, displayField)"></span>
|
|
14285
14612
|
<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
|
-
}
|
|
14613
|
+
</div>
|
|
14614
|
+
}
|
|
14615
|
+
</div>
|
|
14616
|
+
}
|
|
14617
|
+
</co-input-text>
|
|
14303
14618
|
@if (isLoading) {
|
|
14304
14619
|
<div class="filter-loader"><span></span></div>
|
|
14305
14620
|
}
|
|
@@ -16556,9 +16871,7 @@ class FilterItemModule {
|
|
|
16556
16871
|
ScrollingModule,
|
|
16557
16872
|
AppendPipeModule,
|
|
16558
16873
|
PrependPipeModule,
|
|
16559
|
-
InputTextModule,
|
|
16560
16874
|
InputRadioButtonModule,
|
|
16561
|
-
InputTextModule,
|
|
16562
16875
|
CoreComponentsTranslationModule,
|
|
16563
16876
|
InputDatePickerModule,
|
|
16564
16877
|
InputDateRangePickerModule], exports: [FilterItemComponent] });
|
|
@@ -16570,9 +16883,7 @@ class FilterItemModule {
|
|
|
16570
16883
|
ScrollingModule,
|
|
16571
16884
|
AppendPipeModule,
|
|
16572
16885
|
PrependPipeModule,
|
|
16573
|
-
InputTextModule,
|
|
16574
16886
|
InputRadioButtonModule,
|
|
16575
|
-
InputTextModule,
|
|
16576
16887
|
CoreComponentsTranslationModule,
|
|
16577
16888
|
InputDatePickerModule,
|
|
16578
16889
|
InputDateRangePickerModule] });
|
|
@@ -16589,9 +16900,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
16589
16900
|
ScrollingModule,
|
|
16590
16901
|
AppendPipeModule,
|
|
16591
16902
|
PrependPipeModule,
|
|
16592
|
-
InputTextModule,
|
|
16593
16903
|
InputRadioButtonModule,
|
|
16594
|
-
InputTextModule,
|
|
16595
16904
|
CoreComponentsTranslationModule,
|
|
16596
16905
|
InputDatePickerModule,
|
|
16597
16906
|
InputDateRangePickerModule
|