@sumaris-net/ngx-components 1.6.2 → 1.6.3
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/bundles/sumaris-net.ngx-components.umd.js +477 -201
- package/bundles/sumaris-net.ngx-components.umd.js.map +1 -1
- package/bundles/sumaris-net.ngx-components.umd.min.js +2 -2
- package/bundles/sumaris-net.ngx-components.umd.min.js.map +1 -1
- package/doc/changelog.md +7 -0
- package/esm2015/src/app/core/auth/modal/modal-auth.js +21 -9
- package/esm2015/src/app/shared/form/field.model.js +1 -1
- package/esm2015/src/app/shared/material/autocomplete/material.autocomplete.js +81 -88
- package/esm2015/src/app/shared/material/autocomplete/testing/autocomplete.test.js +2 -2
- package/esm2015/src/app/shared/material/chips/material.chips.js +336 -79
- package/esm2015/src/app/shared/material/chips/testing/chips.test.js +7 -4
- package/esm2015/src/app/shared/material/swipe/material.swipe.js +5 -5
- package/esm2015/src/app/shared/material/swipe/testing/swipe.test.js +2 -2
- package/fesm2015/sumaris-net.ngx-components.js +442 -179
- package/fesm2015/sumaris-net.ngx-components.js.map +1 -1
- package/package.json +1 -1
- package/src/app/core/auth/modal/modal-auth.d.ts +12 -5
- package/src/app/shared/form/field.model.d.ts +2 -1
- package/src/app/shared/material/autocomplete/material.autocomplete.d.ts +35 -35
- package/src/app/shared/material/chips/material.chips.d.ts +35 -10
- package/src/app/shared/material/swipe/material.swipe.d.ts +2 -2
- package/sumaris-net.ngx-components.metadata.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, EventEmitter,
|
|
2
|
+
import { InjectionToken, EventEmitter, Component, forwardRef, ChangeDetectionStrategy, ChangeDetectorRef, Optional, Input, Output, ViewChild, HostBinding, Pipe, Injectable, Directive, Inject, NgModule, ElementRef, ViewChildren, HostListener, ComponentFactoryResolver, ApplicationRef, Injector, Renderer2 } from '@angular/core';
|
|
3
3
|
import * as i1$3 from '@angular/common';
|
|
4
4
|
import { CommonModule, DOCUMENT, Location } from '@angular/common';
|
|
5
5
|
import { CdkTableModule } from '@angular/cdk/table';
|
|
@@ -36,7 +36,7 @@ import { MatAutocomplete, MatAutocompleteTrigger, MatAutocompleteModule, MAT_AUT
|
|
|
36
36
|
import { __awaiter, __decorate } from 'tslib';
|
|
37
37
|
import * as i1$6 from '@angular/forms';
|
|
38
38
|
import { NG_VALUE_ACCESSOR, FormGroupDirective, AbstractControl, FormGroup, FormArray, FormControl, ReactiveFormsModule, Validators, FormBuilder } from '@angular/forms';
|
|
39
|
-
import { timer, merge, fromEvent,
|
|
39
|
+
import { timer, merge, fromEvent, BehaviorSubject, Subscription, Subject, isObservable, noop as noop$8, Observable, defer, of, from, combineLatest, EMPTY } from 'rxjs';
|
|
40
40
|
import { filter, first, map, takeUntil, switchMap, startWith, debounceTime, takeWhile, tap, distinctUntilChanged, mergeMap, catchError, throttleTime, skip } from 'rxjs/operators';
|
|
41
41
|
import * as i1$1 from '@ngx-translate/core';
|
|
42
42
|
import { TranslateService, TranslateModule } from '@ngx-translate/core';
|
|
@@ -976,11 +976,10 @@ class MatAutocompleteConfigHolder {
|
|
|
976
976
|
const attributesOrFn = attributes.map((a, index) => typeof a === 'function' && options.attributes[index] || a);
|
|
977
977
|
const filter = Object.assign({ searchAttribute: attributes.length === 1 ? attributes[0] : undefined, searchAttributes: attributes.length > 1 ? attributes : undefined }, options.filter);
|
|
978
978
|
const displayWith = options.displayWith || ((obj) => obj && joinPropertiesPath(obj, attributes));
|
|
979
|
-
const compareWith = options.
|
|
979
|
+
const compareWith = options.equals || ((o1, o2) => o1 && o2 && o1.id === o2.id);
|
|
980
980
|
const config = Object.assign(Object.assign({}, options), { attributes: attributesOrFn, suggestFn,
|
|
981
981
|
filter,
|
|
982
|
-
displayWith,
|
|
983
|
-
compareWith });
|
|
982
|
+
displayWith, equals: compareWith });
|
|
984
983
|
this.fields[fieldName] = config;
|
|
985
984
|
return config;
|
|
986
985
|
}
|
|
@@ -991,11 +990,6 @@ class MatAutocompleteConfigHolder {
|
|
|
991
990
|
return this.fields[fieldName] || this.add(fieldName);
|
|
992
991
|
}
|
|
993
992
|
}
|
|
994
|
-
const DEFAULT_VALUE_ACCESSOR$6 = {
|
|
995
|
-
provide: NG_VALUE_ACCESSOR,
|
|
996
|
-
useExisting: forwardRef(() => MatAutocompleteField),
|
|
997
|
-
multi: true
|
|
998
|
-
};
|
|
999
993
|
const noop$7 = () => { };
|
|
1000
994
|
const ɵ0$a = noop$7;
|
|
1001
995
|
class MatAutocompleteField {
|
|
@@ -1004,14 +998,6 @@ class MatAutocompleteField {
|
|
|
1004
998
|
this.formGroupDir = formGroupDir;
|
|
1005
999
|
this._onChangeCallback = noop$7;
|
|
1006
1000
|
this._onTouchedCallback = noop$7;
|
|
1007
|
-
this._subscription = new Subscription();
|
|
1008
|
-
this._filter$ = new BehaviorSubject(undefined);
|
|
1009
|
-
this._reload$ = new Subject();
|
|
1010
|
-
this._readonly = false;
|
|
1011
|
-
this.$inputItems = new BehaviorSubject(undefined);
|
|
1012
|
-
this.$filteredItems = new BehaviorSubject(undefined);
|
|
1013
|
-
this.displayValue = '';
|
|
1014
|
-
this._fetchMore$ = new EventEmitter();
|
|
1015
1001
|
this.logPrefix = '[mat-autocomplete] ';
|
|
1016
1002
|
this.formControlName = null;
|
|
1017
1003
|
this.required = false;
|
|
@@ -1024,13 +1010,21 @@ class MatAutocompleteField {
|
|
|
1024
1010
|
this.fetchMoreThreshold = '15%';
|
|
1025
1011
|
this.suggestLengthThreshold = null;
|
|
1026
1012
|
this.showLoadingSpinner = true;
|
|
1013
|
+
this.clicked = new EventEmitter();
|
|
1014
|
+
this.blurred = new EventEmitter();
|
|
1015
|
+
this.focused = new EventEmitter();
|
|
1016
|
+
this.dropButtonClick = new EventEmitter(true);
|
|
1017
|
+
this.keydownEscape = new EventEmitter();
|
|
1018
|
+
this.keyupEnter = new EventEmitter();
|
|
1027
1019
|
this.animationsDisabled = true;
|
|
1028
|
-
this.
|
|
1029
|
-
this
|
|
1030
|
-
this
|
|
1031
|
-
this.
|
|
1032
|
-
this.
|
|
1033
|
-
this.
|
|
1020
|
+
this._readonly = false;
|
|
1021
|
+
this.$inputItems = new BehaviorSubject(undefined);
|
|
1022
|
+
this.$filteredItems = new BehaviorSubject(undefined);
|
|
1023
|
+
this.displayValue = '';
|
|
1024
|
+
this._fetchMore$ = new EventEmitter();
|
|
1025
|
+
this._subscription = new Subscription();
|
|
1026
|
+
this._$filter = new BehaviorSubject(undefined);
|
|
1027
|
+
this._reload$ = new Subject();
|
|
1034
1028
|
}
|
|
1035
1029
|
get itemCount() {
|
|
1036
1030
|
return this._itemCount;
|
|
@@ -1039,14 +1033,14 @@ class MatAutocompleteField {
|
|
|
1039
1033
|
return this._onFetchMoreCallback && this._moreItemsCount > 0;
|
|
1040
1034
|
}
|
|
1041
1035
|
set filter(value) {
|
|
1042
|
-
if (value !== this.
|
|
1036
|
+
if (value !== this._$filter.value) {
|
|
1043
1037
|
// DEBUG
|
|
1044
1038
|
//console.debug(this.logPrefix + " Setting filter:", value);
|
|
1045
|
-
this.
|
|
1039
|
+
this._$filter.next(value);
|
|
1046
1040
|
}
|
|
1047
1041
|
}
|
|
1048
1042
|
get filter() {
|
|
1049
|
-
return this.
|
|
1043
|
+
return this._$filter.value;
|
|
1050
1044
|
}
|
|
1051
1045
|
set readonly(value) {
|
|
1052
1046
|
this._readonly = value;
|
|
@@ -1109,6 +1103,7 @@ class MatAutocompleteField {
|
|
|
1109
1103
|
this.displayColumnSizes = this.displayColumnSizes || this.config.columnSizes;
|
|
1110
1104
|
this.displayColumnNames = this.displayColumnNames || this.config.columnNames;
|
|
1111
1105
|
this.displayWith = this.displayWith || this.config.displayWith;
|
|
1106
|
+
this.equals = this.equals || this.config.equals;
|
|
1112
1107
|
this.mobile = toBoolean(this.mobile, this.config.mobile);
|
|
1113
1108
|
this.suggestLengthThreshold = toNumber(this.suggestLengthThreshold, this.config.suggestLengthThreshold || 0);
|
|
1114
1109
|
this.showAllOnFocus = toBoolean(this.showAllOnFocus, toBoolean(this.config.showAllOnFocus, this.suggestLengthThreshold <= 0));
|
|
@@ -1123,20 +1118,18 @@ class MatAutocompleteField {
|
|
|
1123
1118
|
this.displayColumnSizes = this.displayColumnSizes
|
|
1124
1119
|
// if only column: auto size
|
|
1125
1120
|
|| (this.displayAttributes.length === 1 && [undefined])
|
|
1126
|
-
|
|
1127
|
-
//
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1121
|
+
// Computed column size:
|
|
1122
|
+
// - if label then col size = 2
|
|
1123
|
+
// - if rankOrder then col size = 1
|
|
1124
|
+
// - ese => auto size
|
|
1125
|
+
|| this.displayAttributes.map(attr => (attr && attr.endsWith('label')) ? 2
|
|
1126
|
+
: ((attr && attr.endsWith('rankOrder')) ? 1
|
|
1132
1127
|
: undefined));
|
|
1133
1128
|
this.displayColumnNames = this.displayAttributes.map((attr, index) => this.displayColumnNames && this.displayColumnNames[index] ||
|
|
1134
1129
|
(this.i18nPrefix + changeCaseToUnderscore(attr).toUpperCase()));
|
|
1135
1130
|
this.mobile = toBoolean(this.mobile, false);
|
|
1136
1131
|
this.searchable = !this.mobile && !this.multiple;
|
|
1137
|
-
|
|
1138
|
-
if (!this.searchable && !this.compareWith)
|
|
1139
|
-
this.compareWith = (o1, o2) => o1 && o2 && o1.id === o2.id;
|
|
1132
|
+
this.equals = this.equals || ((o1, o2) => o1 && o2 && o1.id === o2.id);
|
|
1140
1133
|
const classList = (_b = this.classList) === null || _b === void 0 ? void 0 : _b.split(' ');
|
|
1141
1134
|
this.panelWidth = this.panelWidth || (classList && ((classList.includes('min-width-medium') && '300px')
|
|
1142
1135
|
|| (classList.includes('min-width-large') && '400px')
|
|
@@ -1151,7 +1144,7 @@ class MatAutocompleteField {
|
|
|
1151
1144
|
if (!this.suggestFn) {
|
|
1152
1145
|
const suggestFromArrayFn = (value, filter) => __awaiter(this, void 0, void 0, function* () {
|
|
1153
1146
|
// DEBUG
|
|
1154
|
-
//console.debug(this.logPrefix +
|
|
1147
|
+
//console.debug(this.logPrefix + ' Calling suggestFromArray with value=', value);
|
|
1155
1148
|
return suggestFromArray(this.$inputItems.value, value, Object.assign({ searchAttributes: this.displayAttributes }, filter));
|
|
1156
1149
|
});
|
|
1157
1150
|
// Wait (once) that items are loaded, then call suggest from array fn
|
|
@@ -1169,7 +1162,7 @@ class MatAutocompleteField {
|
|
|
1169
1162
|
}
|
|
1170
1163
|
else if (!this.searchable) {
|
|
1171
1164
|
// Manually fill input items, from the given suggest function
|
|
1172
|
-
this._subscription.add(this.
|
|
1165
|
+
this._subscription.add(this._$filter.pipe(startWith(this.filter), debounceTime(250), takeWhile((_) => !this.searchable), // Close subscription, when enabling search (no more mat-select)
|
|
1173
1166
|
switchMap((filter) => this.suggest('*', filter)))
|
|
1174
1167
|
.subscribe(items => this.$inputItems.next(items)));
|
|
1175
1168
|
}
|
|
@@ -1180,11 +1173,7 @@ class MatAutocompleteField {
|
|
|
1180
1173
|
this.formControl.valueChanges
|
|
1181
1174
|
.pipe(filter(value => this.enabled && this.searchable && isNotNilString(value)),
|
|
1182
1175
|
// Mark as loading (to show loading spinner) - earlier as possible, so before the debounce time
|
|
1183
|
-
tap(
|
|
1184
|
-
if (this.showLoadingSpinner) {
|
|
1185
|
-
this.markAsLoading();
|
|
1186
|
-
}
|
|
1187
|
-
}),
|
|
1176
|
+
tap(_ => this.showLoadingSpinner && this.markAsLoading()),
|
|
1188
1177
|
// Filter if not enough character
|
|
1189
1178
|
filter(value => value.length >= this.suggestLengthThreshold),
|
|
1190
1179
|
// Wait a debounce time
|
|
@@ -1213,12 +1202,12 @@ class MatAutocompleteField {
|
|
|
1213
1202
|
// Merge some observables, with a common distinctUntilChanged() pipe, and NO debounceTime
|
|
1214
1203
|
merge(
|
|
1215
1204
|
// Focus or click => Load all
|
|
1216
|
-
merge(this.
|
|
1205
|
+
merge(this.focused, this.clicked)
|
|
1217
1206
|
.pipe(filter(_ => this.enabled && this.searchable), map(_ => this.showAllOnFocus ? '*' : this.formControl.value)),
|
|
1218
1207
|
// On dropdown button click
|
|
1219
|
-
this.
|
|
1220
|
-
.pipe(filter(event => this.
|
|
1221
|
-
.pipe(filter(
|
|
1208
|
+
this.dropButtonClick
|
|
1209
|
+
.pipe(filter(event => this.searchable && this.enabled && (!event || !event.defaultPrevented)), map(_ => this.showAllOnFocus ? '*' : this.formControl.value)), merge(this.$inputItems, this._$filter)
|
|
1210
|
+
.pipe(filter(_ => this.searchable && this.enabled), map(_ => this.formControl.value)))
|
|
1222
1211
|
.pipe(
|
|
1223
1212
|
// Start to suggest when :
|
|
1224
1213
|
// - '*'
|
|
@@ -1257,7 +1246,7 @@ class MatAutocompleteField {
|
|
|
1257
1246
|
// Make sure control value is inside (mat-select)
|
|
1258
1247
|
if (items && !this.searchable) {
|
|
1259
1248
|
const value = this.formControl.value;
|
|
1260
|
-
if (isNotNil(value) && typeof value === 'object' && items.findIndex(item => this.
|
|
1249
|
+
if (isNotNil(value) && typeof value === 'object' && items.findIndex(item => this.equals(item, value)) === -1) {
|
|
1261
1250
|
// If form value is missing: add it to the list
|
|
1262
1251
|
items = items.concat(value);
|
|
1263
1252
|
}
|
|
@@ -1266,7 +1255,7 @@ class MatAutocompleteField {
|
|
|
1266
1255
|
this.$filteredItems.next(items);
|
|
1267
1256
|
}));
|
|
1268
1257
|
// Applying implicit value, on blur
|
|
1269
|
-
this._subscription.add(this.
|
|
1258
|
+
this._subscription.add(this.blurred
|
|
1270
1259
|
.pipe(
|
|
1271
1260
|
// Skip if not searchable
|
|
1272
1261
|
filter(_ => this.searchable), map(_ => this.formControl.value))
|
|
@@ -1296,7 +1285,7 @@ class MatAutocompleteField {
|
|
|
1296
1285
|
distinctUntilChanged())
|
|
1297
1286
|
// Update component state
|
|
1298
1287
|
.subscribe(() => this.checkIfTouched()));
|
|
1299
|
-
this._subscription.add(this.
|
|
1288
|
+
this._subscription.add(this.keydownEscape.subscribe(event => {
|
|
1300
1289
|
if (this.isOpen) {
|
|
1301
1290
|
event === null || event === void 0 ? void 0 : event.stopPropagation();
|
|
1302
1291
|
event === null || event === void 0 ? void 0 : event.preventDefault();
|
|
@@ -1317,18 +1306,18 @@ class MatAutocompleteField {
|
|
|
1317
1306
|
this.$inputItems.complete();
|
|
1318
1307
|
this.$filteredItems.complete();
|
|
1319
1308
|
this._reload$.complete();
|
|
1320
|
-
this.
|
|
1321
|
-
this.
|
|
1322
|
-
this.
|
|
1323
|
-
this.
|
|
1324
|
-
this.
|
|
1325
|
-
this.
|
|
1326
|
-
this.
|
|
1309
|
+
this._$filter.complete();
|
|
1310
|
+
this.dropButtonClick.complete();
|
|
1311
|
+
this.clicked.complete();
|
|
1312
|
+
this.blurred.complete();
|
|
1313
|
+
this.focused.complete();
|
|
1314
|
+
this.keydownEscape.complete();
|
|
1315
|
+
this.keyupEnter.complete();
|
|
1327
1316
|
this._fetchMore$.complete();
|
|
1328
1317
|
this._implicitValue = undefined;
|
|
1329
1318
|
this.formControl = null;
|
|
1330
1319
|
this.displayWith = null;
|
|
1331
|
-
this.
|
|
1320
|
+
this.equals = null;
|
|
1332
1321
|
this.suggestFn = null;
|
|
1333
1322
|
this.$filteredItems = null;
|
|
1334
1323
|
this.matSelectItems$ = null;
|
|
@@ -1338,8 +1327,8 @@ class MatAutocompleteField {
|
|
|
1338
1327
|
this._onTouchedCallback = null;
|
|
1339
1328
|
this._onFetchMoreCallback = null;
|
|
1340
1329
|
// Destroy the 'autocomplete' instance, to avoid memory leak
|
|
1341
|
-
if (this.
|
|
1342
|
-
this.
|
|
1330
|
+
if (this.autocomplete) {
|
|
1331
|
+
this.autocomplete.ngOnDestroy();
|
|
1343
1332
|
}
|
|
1344
1333
|
}
|
|
1345
1334
|
/**
|
|
@@ -1365,7 +1354,7 @@ class MatAutocompleteField {
|
|
|
1365
1354
|
}
|
|
1366
1355
|
setDisabledState(isDisabled) {
|
|
1367
1356
|
var _a;
|
|
1368
|
-
if (isDisabled && ((_a = this.
|
|
1357
|
+
if (isDisabled && ((_a = this.autocomplete) === null || _a === void 0 ? void 0 : _a.isOpen)) {
|
|
1369
1358
|
this.closePanel();
|
|
1370
1359
|
}
|
|
1371
1360
|
this.cd.markForCheck();
|
|
@@ -1379,7 +1368,7 @@ class MatAutocompleteField {
|
|
|
1379
1368
|
(_a = this.matSelect) === null || _a === void 0 ? void 0 : _a.focus();
|
|
1380
1369
|
}
|
|
1381
1370
|
}
|
|
1382
|
-
|
|
1371
|
+
filterInputTextFocusEvent(event) {
|
|
1383
1372
|
if (!event || event.defaultPrevented)
|
|
1384
1373
|
return;
|
|
1385
1374
|
// Ignore event from mat-option
|
|
@@ -1388,7 +1377,7 @@ class MatAutocompleteField {
|
|
|
1388
1377
|
if (event.stopPropagation)
|
|
1389
1378
|
event.stopPropagation();
|
|
1390
1379
|
event.returnValue = false;
|
|
1391
|
-
//DEBUG console.debug(this.logPrefix +
|
|
1380
|
+
//DEBUG console.debug(this.logPrefix + ' Cancelling focus event');
|
|
1392
1381
|
return false;
|
|
1393
1382
|
}
|
|
1394
1383
|
const hasContent = selectInputContent(event);
|
|
@@ -1396,7 +1385,7 @@ class MatAutocompleteField {
|
|
|
1396
1385
|
if (!hasContent || (this.showPanelOnFocus && this.showAllOnFocus)) {
|
|
1397
1386
|
// DEBUG
|
|
1398
1387
|
//console.debug(this.logPrefix + ' Emit focus event');
|
|
1399
|
-
this.
|
|
1388
|
+
this.focused.emit(event);
|
|
1400
1389
|
return true;
|
|
1401
1390
|
}
|
|
1402
1391
|
return false;
|
|
@@ -1417,7 +1406,7 @@ class MatAutocompleteField {
|
|
|
1417
1406
|
//console.debug(this.logPrefix + ' Blur: move caret to the beginning');
|
|
1418
1407
|
// Move caret to the beginning (fix issue IMAGINE-469)
|
|
1419
1408
|
selectInputRange(event.target, 0, 0);
|
|
1420
|
-
this.
|
|
1409
|
+
this.blurred.emit(event);
|
|
1421
1410
|
return true;
|
|
1422
1411
|
}
|
|
1423
1412
|
filterMatSelectFocusEvent(event) {
|
|
@@ -1425,7 +1414,7 @@ class MatAutocompleteField {
|
|
|
1425
1414
|
return;
|
|
1426
1415
|
// DEBUG
|
|
1427
1416
|
// console.debug(this.logPrefix + " Received <mat-select> focus event", event);
|
|
1428
|
-
this.
|
|
1417
|
+
this.focused.emit(event);
|
|
1429
1418
|
}
|
|
1430
1419
|
filterMatSelectBlurEvent(event) {
|
|
1431
1420
|
if (!event || event.defaultPrevented)
|
|
@@ -1442,7 +1431,7 @@ class MatAutocompleteField {
|
|
|
1442
1431
|
// console.debug(this.logPrefix + " Cancelling <mat-select> blur event");
|
|
1443
1432
|
return false;
|
|
1444
1433
|
}
|
|
1445
|
-
this.
|
|
1434
|
+
this.blurred.emit(event);
|
|
1446
1435
|
return true;
|
|
1447
1436
|
}
|
|
1448
1437
|
toggleSearch(event) {
|
|
@@ -1464,7 +1453,7 @@ class MatAutocompleteField {
|
|
|
1464
1453
|
event.stopPropagation();
|
|
1465
1454
|
}
|
|
1466
1455
|
_initAutocompleteInfiniteScroll(threshold) {
|
|
1467
|
-
if (!this.
|
|
1456
|
+
if (!this.autocomplete)
|
|
1468
1457
|
return; // Skip
|
|
1469
1458
|
// DEBUG
|
|
1470
1459
|
//console.debug(this.logPrefix + ' Init autocomplete scroll listener');
|
|
@@ -1472,12 +1461,12 @@ class MatAutocompleteField {
|
|
|
1472
1461
|
this._openedSubscription.unsubscribe();
|
|
1473
1462
|
this._subscription.remove(this._openedSubscription);
|
|
1474
1463
|
}
|
|
1475
|
-
const opened$ = this.
|
|
1464
|
+
const opened$ = this.autocomplete._isOpen
|
|
1476
1465
|
? timer(0)
|
|
1477
|
-
: this.
|
|
1466
|
+
: this.autocomplete.opened.pipe(debounceTime(200));
|
|
1478
1467
|
const scrollEnd$ = opened$
|
|
1479
1468
|
.pipe(map((_) => this.getAutocompletePanel()), filter(isNotNil), switchMap((panel) => fromScrollEndEvent(panel, threshold)
|
|
1480
|
-
.pipe(takeUntil(this.
|
|
1469
|
+
.pipe(takeUntil(this.autocomplete.closed))));
|
|
1481
1470
|
// Trigger fetch more, end end scroll reached
|
|
1482
1471
|
this._openedSubscription = scrollEnd$
|
|
1483
1472
|
.subscribe(() => this._fetchMore$.emit());
|
|
@@ -1508,14 +1497,14 @@ class MatAutocompleteField {
|
|
|
1508
1497
|
}
|
|
1509
1498
|
get isOpen() {
|
|
1510
1499
|
var _a, _b;
|
|
1511
|
-
return (this.searchable && ((_a = this.
|
|
1500
|
+
return (this.searchable && ((_a = this.autocomplete) === null || _a === void 0 ? void 0 : _a.isOpen))
|
|
1512
1501
|
|| ((_b = this.matSelect) === null || _b === void 0 ? void 0 : _b.panelOpen)
|
|
1513
1502
|
|| false;
|
|
1514
1503
|
}
|
|
1515
1504
|
closePanel() {
|
|
1516
1505
|
var _a, _b, _c, _d;
|
|
1517
|
-
if ((_a = this.
|
|
1518
|
-
(_b = this.
|
|
1506
|
+
if ((_a = this.autocomplete) === null || _a === void 0 ? void 0 : _a.isOpen) {
|
|
1507
|
+
(_b = this.autocompleteTrigger) === null || _b === void 0 ? void 0 : _b.closePanel();
|
|
1519
1508
|
return;
|
|
1520
1509
|
}
|
|
1521
1510
|
if ((_c = this.matSelect) === null || _c === void 0 ? void 0 : _c.panelOpen) {
|
|
@@ -1582,7 +1571,7 @@ class MatAutocompleteField {
|
|
|
1582
1571
|
}
|
|
1583
1572
|
getAutocompletePanel() {
|
|
1584
1573
|
var _a, _b;
|
|
1585
|
-
const ele = (_b = (_a = this.
|
|
1574
|
+
const ele = (_b = (_a = this.autocomplete) === null || _a === void 0 ? void 0 : _a.options.last) === null || _b === void 0 ? void 0 : _b._getHostElement().parentElement;
|
|
1586
1575
|
if (!ele) {
|
|
1587
1576
|
// DEBUG
|
|
1588
1577
|
console.warn(this.logPrefix + ' Unable to find the autocomplete div...');
|
|
@@ -1616,8 +1605,12 @@ MatAutocompleteField.decorators = [
|
|
|
1616
1605
|
{ type: Component, args: [{
|
|
1617
1606
|
// eslint-disable-next-line @angular-eslint/component-selector
|
|
1618
1607
|
selector: 'mat-autocomplete-field',
|
|
1619
|
-
template: "<ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col class=\"ion-no-padding\">\n <mat-form-field *ngIf=\"_readonly; else writable\"\n [floatLabel]=\"floatLabel\"\n [title]=\"displayValue\"\n class=\"mat-form-field-disabled\">\n\n <div matPrefix>\n <ng-container *ngTemplateOutlet=\"matPrefixTemplate\"></ng-container>\n </div>\n\n <!-- readonly -->\n <ng-container>\n <input matInput hidden type=\"text\"\n [placeholder]=\"placeholder\"\n [formControl]=\"formControl\" readonly>\n <ion-text>{{displayWith(value)}}</ion-text>\n </ng-container>\n\n <div matSuffix>\n <ng-container *ngTemplateOutlet=\"matSuffixTemplate\"></ng-container>\n </div>\n\n </mat-form-field>\n\n <ng-template #writable>\n <mat-form-field [floatLabel]=\"floatLabel\"\n [class.mat-form-field-disabled]=\"disabled\"\n [title]=\"displayValue\">\n\n <div matPrefix>\n <ng-container *ngTemplateOutlet=\"matPrefixTemplate\"></ng-container>\n </div>\n\n <!-- Basic select -->\n <mat-select #matSelect\n *ngIf=\"!searchable; else searchableTemplate\"\n [placeholder]=\"placeholder\"\n [formControl]=\"formControl\"\n [tabindex]=\"_tabindex\"\n [panelClass]=\"classList\"\n [style.width]=\"panelWidth\"\n (focus)=\"filterMatSelectFocusEvent($event)\"\n (blur)=\"filterMatSelectBlurEvent($event)\"\n (keydown.escape)=\"
|
|
1620
|
-
providers: [
|
|
1608
|
+
template: "<ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col class=\"ion-no-padding\">\n <mat-form-field *ngIf=\"_readonly; else writable\"\n [floatLabel]=\"floatLabel\"\n [title]=\"displayValue\"\n class=\"mat-form-field-disabled\">\n\n <div matPrefix>\n <ng-container *ngTemplateOutlet=\"matPrefixTemplate\"></ng-container>\n </div>\n\n <!-- readonly -->\n <ng-container>\n <input matInput hidden type=\"text\"\n [placeholder]=\"placeholder\"\n [formControl]=\"formControl\" readonly>\n <ion-text>{{displayWith(value)}}</ion-text>\n </ng-container>\n\n <div matSuffix>\n <ng-container *ngTemplateOutlet=\"matSuffixTemplate\"></ng-container>\n </div>\n\n </mat-form-field>\n\n <ng-template #writable>\n <mat-form-field [floatLabel]=\"floatLabel\"\n [class.mat-form-field-disabled]=\"disabled\"\n [title]=\"displayValue\">\n\n <div matPrefix>\n <ng-container *ngTemplateOutlet=\"matPrefixTemplate\"></ng-container>\n </div>\n\n <!-- Basic select -->\n <mat-select #matSelect\n *ngIf=\"!searchable; else searchableTemplate\"\n [placeholder]=\"placeholder\"\n [formControl]=\"formControl\"\n [tabindex]=\"_tabindex\"\n [panelClass]=\"classList\"\n [style.width]=\"panelWidth\"\n (focus)=\"filterMatSelectFocusEvent($event)\"\n (blur)=\"filterMatSelectBlurEvent($event)\"\n (keydown.escape)=\"keydownEscape.emit($event)\"\n (keyup.enter)=\"keyupEnter.emit($event)\"\n [compareWith]=\"equals\"\n [multiple]=\"multiple\"\n [required]=\"required\">\n <mat-select-trigger>{{ displayWith(value) }}</mat-select-trigger>\n\n <!-- header -->\n <ion-row class=\"mat-autocomplete-header ion-no-padding\">\n <ion-col *ngFor=\"let attr of displayAttributes; index as i; last as isLast\" [size]=\"displayColumnSizes[i]\">\n <ion-label [innerHTML]=\"displayColumnNames[i] | translate\"></ion-label>\n </ion-col>\n </ion-row>\n\n <!-- None option -->\n <mat-option *ngIf=\"!required\" class=\"ion-no-padding\">\n <ion-row class=\"ion-no-padding\">\n <ion-col class=\"ion-no-padding\">\n <ion-label><i translate>COMMON.EMPTY_OPTION</i></ion-label>\n </ion-col>\n </ion-row>\n </mat-option>\n\n <ng-container *ngIf=\"$filteredItems | async; let items\">\n <!-- No item option -->\n <mat-option *ngIf=\"items | isEmptyArray\" class=\"ion-padding text-italic\" disabled>\n <ion-label>{{noResultMessage | translate}}</ion-label>\n </mat-option>\n\n <!-- options -->\n <mat-option *ngFor=\"let item of items\" [value]=\"item\" class=\"ion-no-padding\">\n <ion-row [classList]=\"item.classList\">\n <ion-col *ngFor=\"let path of displayAttributes; index as i;\"\n [size]=\"displayColumnSizes[i]\">\n <ion-text>{{item | propertyGet: path }}</ion-text>\n </ion-col>\n </ion-row>\n </mat-option>\n\n <!-- More item -->\n <mat-option *ngIf=\"_moreItemsCount\" (ngInit)=\"_initMatSelectInfiniteScroll()\"\n class=\"ion-padding\" disabled>\n <ion-skeleton-text [animated]=\"true\" style=\"width: 100%\"></ion-skeleton-text>\n </mat-option>\n </ng-container>\n </mat-select>\n\n\n <!--\n NOTE :\n - \"selectInputContent($event) || onFocus.emit($event)\" : call onFocus only when to the input is empty (nothing to select)\n -->\n <ng-template #searchableTemplate>\n <input matInput #matInputText type=\"text\"\n [matAutocomplete]=\"autocomplete\"\n [matAutocompletePosition]=\"matAutocompletePosition\"\n [formControl]=\"formControl\"\n [placeholder]=\"placeholder\"\n [appAutofocus]=\"autofocus\"\n [tabindex]=\"_tabindex\"\n [required]=\"required\"\n (click)=\"clicked.emit($event)\"\n (focus)=\"filterInputTextFocusEvent($event)\"\n (blur)=\"filterInputTextBlurEvent($event)\"\n (keydown.escape)=\"keydownEscape.emit($event)\"\n (keyup.enter)=\"keyupEnter.emit($event)\"\n (keyup.arrowdown)=\"!autocomplete.opened && dropButtonClick.emit($event)\">\n\n <!-- autocomplete -->\n <mat-autocomplete #autocomplete=\"matAutocomplete\"\n autoActiveFirstOption\n [displayWith]=\"displayWith\"\n [class]=\"classList\"\n [class.cdk-visually-hidden]=\"!searchable\"\n [panelWidth]=\"panelWidth\">\n\n <ion-row class=\"mat-autocomplete-header ion-no-padding\">\n <ion-col *ngFor=\"let attr of displayAttributes; index as i; last as last\" [size]=\"displayColumnSizes[i]\">\n <ion-label [innerHTML]=\"displayColumnNames[i] | translate\"></ion-label>\n <ion-text color=\"light\" *ngIf=\"last && itemCount; let count\" class=\"ion-float-end ion-padding-end\"><i>{{'COMMON.RESULT_COUNT'|translate: {count: count} }}</i></ion-text>\n </ion-col>\n </ion-row>\n\n <ng-container *ngIf=\"$filteredItems | async; else loadingTemplate; let items\">\n <!-- No item option -->\n <mat-option *ngIf=\"items | isEmptyArray\" class=\"ion-padding text-italic\" disabled>\n <ion-label><i>{{noResultMessage | translate}}</i></ion-label>\n </mat-option>\n\n <mat-option *ngFor=\"let item of items\" [value]=\"item\" class=\"ion-no-padding\">\n <ion-row [classList]=\"item.classList\">\n <ion-col *ngFor=\"let path of displayAttributes; index as i;\"\n [size]=\"displayColumnSizes[i]\">\n <ion-text [innerHTML]=\"item | propertyGet: path | highlight: { search: formControl.value, withAccent: highlightAccent }\"></ion-text>\n </ion-col>\n </ion-row>\n </mat-option>\n\n <!-- More item -->\n <mat-option *ngIf=\"_moreItemsCount\" (ngInit)=\"_initAutocompleteInfiniteScroll()\"\n class=\"ion-padding\" disabled>\n <ion-skeleton-text [animated]=\"true\" style=\"width: 100%\"></ion-skeleton-text>\n </mat-option>\n </ng-container>\n\n <!-- Loading spinner -->\n <ng-template #loadingTemplate>\n <mat-option *ngIf=\"(matInputText.value | strLength) >= suggestLengthThreshold; else waitMoreCharacterTemplate\"\n class=\"ion-padding\" disabled>\n <ion-skeleton-text [animated]=\"true\" style=\"width: 100%\"></ion-skeleton-text>\n </mat-option>\n </ng-template>\n\n <!-- Need more characters -->\n <ng-template #waitMoreCharacterTemplate>\n <mat-option class=\"ion-padding text-italic\" disabled>\n <ion-label>\n {{'INFO.PLEASE_TYPE_MORE_CHARACTERS'|translate:{minLength: suggestLengthThreshold} }}\n </ion-label>\n </mat-option>\n </ng-template>\n </mat-autocomplete>\n\n </ng-template>\n\n <div matSuffix>\n <ng-container *ngTemplateOutlet=\"matSuffixTemplate\"></ng-container>\n </div>\n\n <mat-error *ngIf=\"formControl.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"formControl.hasError('entity')\" translate>ERROR.FIELD_INVALID</mat-error>\n <ng-content select=\"[matError]\"></ng-content>\n\n </mat-form-field>\n </ng-template>\n </ion-col>\n <ion-col size=\"auto\" class=\"ion-align-self-center\">\n <ng-content select=\"[matAfter]\"></ng-content>\n </ion-col>\n </ion-row>\n</ion-grid>\n\n<ng-template #matPrefixTemplate>\n <ng-content select=\"[matPrefix]\"></ng-content>\n</ng-template>\n\n\n<ng-template #matSuffixTemplate>\n <button matSuffix mat-icon-button tabindex=\"-1\"\n type=\"button\"\n *ngIf=\"searchable\"\n (click)=\"dropButtonClick.emit($event)\"\n [hidden]=\"disabled\">\n <mat-icon class=\"large select-arrow\">arrow_drop_down</mat-icon>\n </button>\n <button matSuffix type=\"button\" mat-icon-button tabindex=\"-1\"\n *ngIf=\"enabled && mobile && !searchable && !multiple\"\n [title]=\"'COMMON.BTN_SEARCH'|translate\"\n (click)=\"toggleSearch($event)\">\n <mat-icon>search</mat-icon>\n </button>\n <button matSuffix mat-icon-button tabindex=\"-1\"\n type=\"button\"\n *ngIf=\"clearable\"\n (click)=\"clearValue($event)\"\n [hidden]=\"disabled || !formControl.value\">\n <mat-icon>close</mat-icon>\n </button>\n\n <ng-content select=\"[matSuffix]\"></ng-content>\n</ng-template>\n",
|
|
1609
|
+
providers: [{
|
|
1610
|
+
provide: NG_VALUE_ACCESSOR,
|
|
1611
|
+
multi: true,
|
|
1612
|
+
useExisting: forwardRef(() => MatAutocompleteField)
|
|
1613
|
+
}],
|
|
1621
1614
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1622
1615
|
styles: [":host{display:inline-block;position:relative}:host.ion-text-wrap ion-label{white-space:normal!important}button[hidden]{display:none}mat-icon.select-arrow{color:rgba(0,0,0,.47);font-size:150%}.fact-scroll-viewport{height:100%;width:100%}.fact-item{height:54px;display:flex}.fact-item .fact-date{min-width:100px;text-align:center;font-size:24pt}.fact-item .fact-date,.fact-item .fact-text{height:100%;align-items:center;justify-content:center;display:flex}.fact-item .fact-text{border-radius:10px}cdk-virtual-scroll-viewport{border:1px solid #000}cdk-virtual-scroll-viewport li{list-style:none}"]
|
|
1623
1616
|
},] }
|
|
@@ -1627,7 +1620,7 @@ MatAutocompleteField.ctorParameters = () => [
|
|
|
1627
1620
|
{ type: FormGroupDirective, decorators: [{ type: Optional }] }
|
|
1628
1621
|
];
|
|
1629
1622
|
MatAutocompleteField.propDecorators = {
|
|
1630
|
-
|
|
1623
|
+
equals: [{ type: Input }],
|
|
1631
1624
|
logPrefix: [{ type: Input }],
|
|
1632
1625
|
formControl: [{ type: Input }],
|
|
1633
1626
|
formControlName: [{ type: Input }],
|
|
@@ -1657,21 +1650,21 @@ MatAutocompleteField.propDecorators = {
|
|
|
1657
1650
|
fetchMoreThreshold: [{ type: Input }],
|
|
1658
1651
|
suggestLengthThreshold: [{ type: Input }],
|
|
1659
1652
|
showLoadingSpinner: [{ type: Input }],
|
|
1653
|
+
clicked: [{ type: Output, args: ['click',] }],
|
|
1654
|
+
blurred: [{ type: Output, args: ['blur',] }],
|
|
1655
|
+
focused: [{ type: Output, args: ['focus',] }],
|
|
1656
|
+
dropButtonClick: [{ type: Output }],
|
|
1657
|
+
keydownEscape: [{ type: Output, args: ['keydown.escape',] }],
|
|
1658
|
+
keyupEnter: [{ type: Output, args: ['keyup.enter',] }],
|
|
1659
|
+
matSelect: [{ type: ViewChild, args: ['matSelect',] }],
|
|
1660
|
+
matInputText: [{ type: ViewChild, args: ['matInputText',] }],
|
|
1661
|
+
autocomplete: [{ type: ViewChild, args: [MatAutocomplete,] }],
|
|
1662
|
+
autocompleteTrigger: [{ type: ViewChild, args: [MatAutocompleteTrigger,] }],
|
|
1660
1663
|
animationsDisabled: [{ type: HostBinding, args: ['@.disabled',] }],
|
|
1661
1664
|
filter: [{ type: Input }],
|
|
1662
1665
|
readonly: [{ type: Input }],
|
|
1663
1666
|
tabindex: [{ type: Input }],
|
|
1664
|
-
items: [{ type: Input }]
|
|
1665
|
-
onClick: [{ type: Output, args: ['click',] }],
|
|
1666
|
-
onBlur: [{ type: Output, args: ['blur',] }],
|
|
1667
|
-
onFocus: [{ type: Output, args: ['focus',] }],
|
|
1668
|
-
onDropButtonClick: [{ type: Output, args: ['dropButtonClick',] }],
|
|
1669
|
-
onKeydownEscape: [{ type: Output, args: ['keydown.escape',] }],
|
|
1670
|
-
onKeyupEnter: [{ type: Output, args: ['keyup.enter',] }],
|
|
1671
|
-
matSelect: [{ type: ViewChild, args: ['matSelect',] }],
|
|
1672
|
-
matInputText: [{ type: ViewChild, args: ['matInputText',] }],
|
|
1673
|
-
matAutocomplete: [{ type: ViewChild, args: [MatAutocomplete,] }],
|
|
1674
|
-
matAutocompleteTrigger: [{ type: ViewChild, args: [MatAutocompleteTrigger,] }]
|
|
1667
|
+
items: [{ type: Input }]
|
|
1675
1668
|
};
|
|
1676
1669
|
|
|
1677
1670
|
class DateFormatPipe {
|
|
@@ -6552,7 +6545,7 @@ class MatSwipeField {
|
|
|
6552
6545
|
// Default values
|
|
6553
6546
|
this.displayAttributes = this.displayAttributes || ['label', 'name'];
|
|
6554
6547
|
this.displayWith = this.displayWith || ((obj) => obj && joinPropertiesPath(obj, this.displayAttributes));
|
|
6555
|
-
this.
|
|
6548
|
+
this.equals = this.equals || ((o1, o2) => o1 && o2 && o1.id === o2.id);
|
|
6556
6549
|
this.mobile = toBoolean(this.mobile, false);
|
|
6557
6550
|
}
|
|
6558
6551
|
ngOnDestroy() {
|
|
@@ -6612,7 +6605,7 @@ class MatSwipeField {
|
|
|
6612
6605
|
if (this._writing)
|
|
6613
6606
|
return;
|
|
6614
6607
|
this._writing = true;
|
|
6615
|
-
if (!this.
|
|
6608
|
+
if (!this.equals(value, this._value)) {
|
|
6616
6609
|
this._value = value;
|
|
6617
6610
|
this.showSlides = isNotNil(this._value);
|
|
6618
6611
|
this.updateSlides();
|
|
@@ -6696,7 +6689,7 @@ class MatSwipeField {
|
|
|
6696
6689
|
}
|
|
6697
6690
|
updateSlides() {
|
|
6698
6691
|
if (this.showSlides) {
|
|
6699
|
-
const itemIndex = (this.$items.getValue() || []).findIndex(value => this.
|
|
6692
|
+
const itemIndex = (this.$items.getValue() || []).findIndex(value => this.equals(value, this._value));
|
|
6700
6693
|
if (itemIndex >= 0) {
|
|
6701
6694
|
this.slideTo(itemIndex);
|
|
6702
6695
|
}
|
|
@@ -6760,7 +6753,7 @@ MatSwipeField.propDecorators = {
|
|
|
6760
6753
|
required: [{ type: Input }],
|
|
6761
6754
|
mobile: [{ type: Input }],
|
|
6762
6755
|
clearable: [{ type: Input }],
|
|
6763
|
-
|
|
6756
|
+
equals: [{ type: Input }],
|
|
6764
6757
|
displayWith: [{ type: Input }],
|
|
6765
6758
|
displayAttributes: [{ type: Input }],
|
|
6766
6759
|
appAutofocus: [{ type: Input }],
|
|
@@ -6809,33 +6802,43 @@ class MatChipsField {
|
|
|
6809
6802
|
this.required = false;
|
|
6810
6803
|
this.readonly = false;
|
|
6811
6804
|
this.clearable = false;
|
|
6812
|
-
this.debounceTime =
|
|
6813
|
-
this.highlightAccent = false;
|
|
6805
|
+
this.debounceTime = null;
|
|
6814
6806
|
this.i18nPrefix = 'REFERENTIAL.';
|
|
6815
6807
|
this.noResultMessage = 'COMMON.NO_RESULT';
|
|
6816
6808
|
this.debug = false;
|
|
6809
|
+
this.itemSize = '48px';
|
|
6810
|
+
this.fetchMoreThreshold = '15%';
|
|
6811
|
+
this.suggestLengthThreshold = null;
|
|
6812
|
+
this.showLoadingSpinner = true;
|
|
6817
6813
|
this.clicked = new EventEmitter();
|
|
6818
6814
|
this.blurred = new EventEmitter();
|
|
6819
6815
|
this.focused = new EventEmitter();
|
|
6816
|
+
this.dropButtonClick = new EventEmitter(true);
|
|
6817
|
+
this.keydownEscape = new EventEmitter();
|
|
6818
|
+
this.keyupEnter = new EventEmitter();
|
|
6820
6819
|
this.$inputItems = new BehaviorSubject(undefined);
|
|
6821
|
-
this
|
|
6820
|
+
this.$filteredItems = new BehaviorSubject(undefined);
|
|
6822
6821
|
this.inputControl = new FormControl();
|
|
6823
|
-
this.
|
|
6822
|
+
this._fetchMore$ = new EventEmitter();
|
|
6824
6823
|
this._subscription = new Subscription();
|
|
6825
6824
|
this._$filter = new BehaviorSubject(undefined);
|
|
6825
|
+
this._reload$ = new Subject();
|
|
6826
6826
|
}
|
|
6827
6827
|
get itemCount() {
|
|
6828
6828
|
return this._itemCount;
|
|
6829
6829
|
}
|
|
6830
|
+
get canFetchMore() {
|
|
6831
|
+
return this._onFetchMoreCallback && this._moreItemsCount > 0;
|
|
6832
|
+
}
|
|
6830
6833
|
set filter(value) {
|
|
6831
|
-
if (this.
|
|
6832
|
-
|
|
6833
|
-
|
|
6834
|
+
if (value !== this._$filter.value) {
|
|
6835
|
+
// DEBUG
|
|
6836
|
+
//console.debug(this.logPrefix + " Setting filter:", value);
|
|
6834
6837
|
this._$filter.next(value);
|
|
6835
6838
|
}
|
|
6836
6839
|
}
|
|
6837
6840
|
get filter() {
|
|
6838
|
-
return this._$filter.
|
|
6841
|
+
return this._$filter.value;
|
|
6839
6842
|
}
|
|
6840
6843
|
set tabindex(value) {
|
|
6841
6844
|
this._tabindex = value;
|
|
@@ -6847,19 +6850,25 @@ class MatChipsField {
|
|
|
6847
6850
|
set items(value) {
|
|
6848
6851
|
// Remove previous subscription on items, (if exits)
|
|
6849
6852
|
if (this._itemsSubscription) {
|
|
6850
|
-
console.warn('Items received twice !');
|
|
6853
|
+
console.warn(this.logPrefix + ' Items received twice !');
|
|
6851
6854
|
this._subscription.remove(this._itemsSubscription);
|
|
6852
6855
|
this._itemsSubscription.unsubscribe();
|
|
6853
6856
|
}
|
|
6854
6857
|
if (isObservable(value)) {
|
|
6855
|
-
this._itemsSubscription = this._subscription.add(value.subscribe(v =>
|
|
6858
|
+
this._itemsSubscription = this._subscription.add(value.subscribe(v => {
|
|
6859
|
+
//console.warn(this.logPrefix + " Received items: ", v);
|
|
6860
|
+
this.$inputItems.next(v);
|
|
6861
|
+
}));
|
|
6856
6862
|
}
|
|
6857
6863
|
else {
|
|
6858
|
-
if (value !== this.$inputItems.
|
|
6864
|
+
if (value !== this.$inputItems.value) {
|
|
6859
6865
|
this.$inputItems.next(value);
|
|
6860
6866
|
}
|
|
6861
6867
|
}
|
|
6862
6868
|
}
|
|
6869
|
+
get items() {
|
|
6870
|
+
return this.$inputItems;
|
|
6871
|
+
}
|
|
6863
6872
|
get value() {
|
|
6864
6873
|
return this.formControl.value || [];
|
|
6865
6874
|
}
|
|
@@ -6870,6 +6879,7 @@ class MatChipsField {
|
|
|
6870
6879
|
return !this.readonly && this.formControl.enabled;
|
|
6871
6880
|
}
|
|
6872
6881
|
ngOnInit() {
|
|
6882
|
+
var _a, _b;
|
|
6873
6883
|
this.formControl = this.formControl || this.formControlName && this.formGroupDir && this.formGroupDir.form.get(this.formControlName);
|
|
6874
6884
|
if (!this.formControl)
|
|
6875
6885
|
throw new Error('Missing mandatory attribute \'formControl\' or \'formControlName\' in <mat-chips-field>.');
|
|
@@ -6884,85 +6894,201 @@ class MatChipsField {
|
|
|
6884
6894
|
this.displayColumnSizes = this.displayColumnSizes || this.config.columnSizes;
|
|
6885
6895
|
this.displayColumnNames = this.displayColumnNames || this.config.columnNames;
|
|
6886
6896
|
this.displayWith = this.displayWith || this.config.displayWith;
|
|
6887
|
-
this.
|
|
6897
|
+
this.equals = this.equals || this.config.equals;
|
|
6888
6898
|
this.mobile = toBoolean(this.mobile, this.config.mobile);
|
|
6889
|
-
this.
|
|
6899
|
+
this.suggestLengthThreshold = toNumber(this.suggestLengthThreshold, this.config.suggestLengthThreshold || 0);
|
|
6900
|
+
this.showAllOnFocus = toBoolean(this.showAllOnFocus, toBoolean(this.config.showAllOnFocus, this.suggestLengthThreshold <= 0));
|
|
6890
6901
|
this.showPanelOnFocus = toBoolean(this.showPanelOnFocus, toBoolean(this.config.showPanelOnFocus, true));
|
|
6891
|
-
this.
|
|
6902
|
+
this.classList = this.classList || this.config.class;
|
|
6903
|
+
this.debounceTime = toNumber(this.debounceTime, this.config.debounceTime);
|
|
6904
|
+
this.highlightAccent = toBoolean(this.highlightAccent, toBoolean(this.config.highlightAccent));
|
|
6892
6905
|
}
|
|
6893
6906
|
// Default values
|
|
6894
|
-
this.displayAttributes = this.displayAttributes || (this.filter
|
|
6907
|
+
this.displayAttributes = this.displayAttributes || ((_a = this.filter) === null || _a === void 0 ? void 0 : _a.attributes) || ['label', 'name'];
|
|
6895
6908
|
this.displayWith = this.displayWith || ((obj) => obj && joinPropertiesPath(obj, this.displayAttributes));
|
|
6896
|
-
this.
|
|
6897
|
-
|
|
6898
|
-
|
|
6899
|
-
|
|
6900
|
-
//
|
|
6901
|
-
|
|
6902
|
-
|
|
6903
|
-
|
|
6909
|
+
this.displayColumnSizes = this.displayColumnSizes
|
|
6910
|
+
// if only column: auto size
|
|
6911
|
+
|| (this.displayAttributes.length === 1 && [undefined])
|
|
6912
|
+
// Computed column size:
|
|
6913
|
+
// - if label then col size = 2
|
|
6914
|
+
// - if rankOrder then col size = 1
|
|
6915
|
+
// - ese => auto size
|
|
6916
|
+
|| this.displayAttributes.map(attr => (attr && attr.endsWith('label')) ? 2
|
|
6917
|
+
: ((attr && attr.endsWith('rankOrder')) ? 1
|
|
6918
|
+
: undefined));
|
|
6904
6919
|
this.displayColumnNames = this.displayAttributes.map((attr, index) => this.displayColumnNames && this.displayColumnNames[index] ||
|
|
6905
6920
|
(this.i18nPrefix + changeCaseToUnderscore(attr).toUpperCase()));
|
|
6906
6921
|
this.mobile = toBoolean(this.mobile, false);
|
|
6922
|
+
this.equals = this.equals || ((o1, o2) => o1 && o2 && o1.id === o2.id);
|
|
6923
|
+
const classList = (_b = this.classList) === null || _b === void 0 ? void 0 : _b.split(' ');
|
|
6924
|
+
this.panelWidth = this.panelWidth || (classList && ((classList.includes('min-width-medium') && '300px')
|
|
6925
|
+
|| (classList.includes('min-width-large') && '400px')
|
|
6926
|
+
|| (classList.includes('min-width-xlarge') && '450px')
|
|
6927
|
+
|| (classList.includes('mat-autocomplete-panel-full-size') && '100vw')));
|
|
6928
|
+
this.showPanelOnFocus = toBoolean(this.showPanelOnFocus, true);
|
|
6929
|
+
this.debounceTime = toNumber(this.debounceTime, 250);
|
|
6930
|
+
this.highlightAccent = toBoolean(this.highlightAccent, false);
|
|
6931
|
+
this.suggestLengthThreshold = this.suggestLengthThreshold || 0;
|
|
6932
|
+
this.matAutocompletePosition = this.matAutocompletePosition || (this.mobile ? 'above' : 'auto'); // On mobile, set position to above (because of bottom keyboard)
|
|
6907
6933
|
// No suggestFn: filter on the given items
|
|
6908
6934
|
if (!this.suggestFn) {
|
|
6909
6935
|
const suggestFromArrayFn = (value, filter) => __awaiter(this, void 0, void 0, function* () {
|
|
6910
6936
|
if (this.debug)
|
|
6911
6937
|
console.debug(this.logPrefix + ' Calling suggestFromArray with value=', value);
|
|
6912
|
-
|
|
6913
|
-
this._itemCount = toNumber(total, data && data.length || 0);
|
|
6914
|
-
return { data, total };
|
|
6938
|
+
return suggestFromArray(this.$inputItems.value, value, Object.assign({ searchAttributes: this.displayAttributes }, filter));
|
|
6915
6939
|
});
|
|
6916
6940
|
// Wait (once) that items are loaded, then call suggest from array fn
|
|
6917
6941
|
this.suggestFn = (value, filter) => __awaiter(this, void 0, void 0, function* () {
|
|
6918
|
-
if (isNil(this.$inputItems.
|
|
6942
|
+
if (isNil(this.$inputItems.value)) {
|
|
6919
6943
|
if (this.debug)
|
|
6920
6944
|
console.debug('[mat-chips] Waiting items to be set...');
|
|
6921
6945
|
yield firstNotNilPromise(this.$inputItems);
|
|
6922
6946
|
if (this.debug)
|
|
6923
|
-
console.debug('[mat-chips] Received items:', this.$inputItems.
|
|
6947
|
+
console.debug('[mat-chips] Received items:', this.$inputItems.value);
|
|
6924
6948
|
}
|
|
6925
6949
|
this.suggestFn = suggestFromArrayFn;
|
|
6926
|
-
return this.
|
|
6950
|
+
return this.suggestFn(value, filter); // Loop
|
|
6927
6951
|
});
|
|
6928
6952
|
}
|
|
6929
|
-
|
|
6930
|
-
//
|
|
6931
|
-
|
|
6932
|
-
|
|
6933
|
-
//
|
|
6934
|
-
|
|
6935
|
-
//
|
|
6936
|
-
|
|
6937
|
-
//
|
|
6938
|
-
|
|
6939
|
-
//
|
|
6940
|
-
//
|
|
6941
|
-
|
|
6942
|
-
//
|
|
6943
|
-
this.
|
|
6944
|
-
.pipe(filter(
|
|
6945
|
-
|
|
6946
|
-
this.
|
|
6947
|
-
|
|
6948
|
-
|
|
6953
|
+
const filteredItemsChanges = merge(
|
|
6954
|
+
// Reload event (no distinctUntilChanged() pipe, to force reload even if same value)
|
|
6955
|
+
this._reload$, this.inputControl.valueChanges
|
|
6956
|
+
.pipe(filter(value => this.enabled && isNotNilString(value)),
|
|
6957
|
+
// Mark as loading (to show loading spinner) - earlier as possible, so before the debounce time
|
|
6958
|
+
tap(_ => this.showLoadingSpinner && this.markAsLoading()),
|
|
6959
|
+
// Filter if not enough character
|
|
6960
|
+
filter(value => value.length >= this.suggestLengthThreshold),
|
|
6961
|
+
// Wait a debounce time
|
|
6962
|
+
debounceTime(this.debounceTime)
|
|
6963
|
+
// DEBUG
|
|
6964
|
+
//tap((value) => console.debug(this.logPrefix + ' Search text changes:', value))
|
|
6965
|
+
),
|
|
6966
|
+
// Object set: use it (no distinctUntilChanged() pipe need)
|
|
6967
|
+
this.inputControl.valueChanges
|
|
6968
|
+
.pipe(startWith(this.inputControl.value), filter(value => isNotNil(value) && typeof value === 'object'), tap(value => {
|
|
6969
|
+
// DEBUG
|
|
6970
|
+
//console.debug(this.logPrefix + ' object changes:', value)
|
|
6971
|
+
// Update the display value (if need)
|
|
6972
|
+
const displayValue = this.displayWith(value) || '';
|
|
6973
|
+
// Apply to the input[type=text] field
|
|
6974
|
+
if (this.matInputText && this.matInputText.nativeElement) {
|
|
6975
|
+
this.matInputText.nativeElement.value = displayValue;
|
|
6976
|
+
}
|
|
6977
|
+
})
|
|
6978
|
+
// DEBUG
|
|
6979
|
+
//tap(value => console.debug(this.logPrefix + ' Received an object value: ', value))
|
|
6980
|
+
),
|
|
6981
|
+
// Merge some observables, with a common distinctUntilChanged() pipe, and NO debounceTime
|
|
6982
|
+
merge(
|
|
6949
6983
|
// Focus or click => Load all
|
|
6950
6984
|
merge(this.focused, this.clicked)
|
|
6951
|
-
.pipe(filter(_ => this.enabled), map((_) => this.showAllOnFocus ? '*' : this.inputControl.value)),
|
|
6952
|
-
|
|
6953
|
-
|
|
6954
|
-
|
|
6955
|
-
|
|
6956
|
-
.pipe(
|
|
6957
|
-
|
|
6958
|
-
|
|
6959
|
-
|
|
6960
|
-
//
|
|
6961
|
-
|
|
6985
|
+
.pipe(filter(_ => this.enabled), map((_) => this.showAllOnFocus ? '*' : this.inputControl.value)),
|
|
6986
|
+
// On dropdown button click
|
|
6987
|
+
this.dropButtonClick
|
|
6988
|
+
.pipe(filter(event => this.enabled && (!event || !event.defaultPrevented)), map(_ => this.showAllOnFocus ? '*' : this.inputControl.value)), merge(this.$inputItems, this._$filter)
|
|
6989
|
+
.pipe(filter(_ => this.enabled), map(_ => this.inputControl.value)))
|
|
6990
|
+
.pipe(
|
|
6991
|
+
// Start to suggest when :
|
|
6992
|
+
// - '*'
|
|
6993
|
+
// - is nil, and there is no min length threshold
|
|
6994
|
+
// - is not nil and not a string type (e.g. object)
|
|
6995
|
+
// - is not nil and is a string, and has enough character
|
|
6996
|
+
filter(value => value === '*'
|
|
6997
|
+
|| (isNil(value)
|
|
6998
|
+
? (this.suggestLengthThreshold <= 0)
|
|
6999
|
+
: (!(typeof value === 'string')
|
|
7000
|
+
|| value.length >= this.suggestLengthThreshold))),
|
|
7001
|
+
// Distinguish changes
|
|
7002
|
+
distinctUntilChanged()))
|
|
7003
|
+
.pipe(
|
|
7004
|
+
// Suggest values
|
|
7005
|
+
mergeMap(value => this.suggest(value, this.filter)),
|
|
7006
|
+
// DEBUG
|
|
7007
|
+
//tap(items => console.debug(this.logPrefix + ' Received from suggest: ', items)),
|
|
7008
|
+
// Store implicit value (will use it onBlur if not other value selected)
|
|
7009
|
+
tap(items => this.updateImplicitValue(items)));
|
|
7010
|
+
// Fetch more events
|
|
7011
|
+
const fetchMoreItemsChanges = this._fetchMore$
|
|
7012
|
+
.pipe(tap(event => event === null || event === void 0 ? void 0 : event.preventDefault()), // Avoid to close the mat-select
|
|
7013
|
+
filter(() => this.canFetchMore), mergeMap(() => this.fetchMore()),
|
|
7014
|
+
// DEBUG
|
|
7015
|
+
//tap(moreItems => console.debug(this.logPrefix + ' Received from fetch More: ', moreItems)),
|
|
7016
|
+
// Concat to existing items
|
|
7017
|
+
map(moreItems => (this.$filteredItems.value || []).concat(moreItems)));
|
|
7018
|
+
// Update filtered items
|
|
7019
|
+
this._subscription.add(merge(this.$inputItems,
|
|
7020
|
+
// Update items events
|
|
7021
|
+
filteredItemsChanges,
|
|
7022
|
+
// Fetch more events
|
|
7023
|
+
fetchMoreItemsChanges)
|
|
7024
|
+
// Emit items
|
|
7025
|
+
.subscribe(items => this.$filteredItems.next(items)));
|
|
7026
|
+
// Applying implicit value, on blur
|
|
7027
|
+
this._subscription.add(this.blurred
|
|
7028
|
+
.pipe(map(_ => this.formControl.value))
|
|
7029
|
+
.subscribe(value => {
|
|
7030
|
+
// When leave component without object, use implicit value if :
|
|
7031
|
+
// - an explicit value
|
|
7032
|
+
// - field is not empty (user fill something)
|
|
7033
|
+
// - OR field empty but is required
|
|
7034
|
+
if (this._implicitValue && ((this.required && isNilOrBlank(value)) || (isNotNilOrBlank(value) && typeof value !== 'object'))) {
|
|
7035
|
+
this.writeValue(this._implicitValue);
|
|
7036
|
+
this.formControl.markAsPending({ emitEvent: false, onlySelf: true });
|
|
7037
|
+
this.formControl.updateValueAndValidity({ emitEvent: false, onlySelf: true });
|
|
7038
|
+
this.checkIfTouched();
|
|
7039
|
+
}
|
|
7040
|
+
else if (isNilOrBlank(value)) {
|
|
7041
|
+
this.writeValue(null);
|
|
7042
|
+
this.formControl.markAsPending({ emitEvent: false, onlySelf: true });
|
|
7043
|
+
this.formControl.updateValueAndValidity({ emitEvent: false, onlySelf: true });
|
|
7044
|
+
this.checkIfTouched();
|
|
7045
|
+
}
|
|
7046
|
+
this._implicitValue = null; // reset the implicit value
|
|
7047
|
+
}));
|
|
7048
|
+
this._subscription.add(this.keydownEscape.subscribe(event => {
|
|
7049
|
+
if (this.isOpen) {
|
|
7050
|
+
event === null || event === void 0 ? void 0 : event.stopPropagation();
|
|
7051
|
+
event === null || event === void 0 ? void 0 : event.preventDefault();
|
|
7052
|
+
// DEBUG
|
|
7053
|
+
//console.debug(this.logPrefix + " Closing the panel (keydown.escape)");
|
|
7054
|
+
this.closePanel();
|
|
7055
|
+
}
|
|
7056
|
+
}));
|
|
6962
7057
|
}
|
|
6963
7058
|
ngOnDestroy() {
|
|
6964
7059
|
this._subscription.unsubscribe();
|
|
7060
|
+
if (this._itemsSubscription) {
|
|
7061
|
+
this._itemsSubscription.unsubscribe();
|
|
7062
|
+
}
|
|
7063
|
+
if (this._openedSubscription) {
|
|
7064
|
+
this._openedSubscription.unsubscribe();
|
|
7065
|
+
}
|
|
6965
7066
|
this.$inputItems.complete();
|
|
7067
|
+
this.$filteredItems.complete();
|
|
7068
|
+
this._reload$.complete();
|
|
7069
|
+
this._$filter.complete();
|
|
7070
|
+
this.dropButtonClick.complete();
|
|
7071
|
+
this.clicked.complete();
|
|
7072
|
+
this.blurred.complete();
|
|
7073
|
+
this.focused.complete();
|
|
7074
|
+
this.keydownEscape.complete();
|
|
7075
|
+
this.keyupEnter.complete();
|
|
7076
|
+
this._fetchMore$.complete();
|
|
7077
|
+
this._implicitValue = undefined;
|
|
7078
|
+
this.formControl = null;
|
|
7079
|
+
this.displayWith = null;
|
|
7080
|
+
this.equals = null;
|
|
7081
|
+
this.suggestFn = null;
|
|
7082
|
+
this.$filteredItems = null;
|
|
7083
|
+
this.config = null;
|
|
7084
|
+
this.classList = null;
|
|
7085
|
+
this._onChangeCallback = null;
|
|
7086
|
+
this._onTouchedCallback = null;
|
|
7087
|
+
this._onFetchMoreCallback = null;
|
|
7088
|
+
// Destroy the 'autocomplete' instance, to avoid memory leak
|
|
7089
|
+
if (this.autocomplete) {
|
|
7090
|
+
this.autocomplete.ngOnDestroy();
|
|
7091
|
+
}
|
|
6966
7092
|
}
|
|
6967
7093
|
/**
|
|
6968
7094
|
* Add item to chips
|
|
@@ -6983,19 +7109,21 @@ class MatChipsField {
|
|
|
6983
7109
|
* @param item
|
|
6984
7110
|
*/
|
|
6985
7111
|
remove(item) {
|
|
6986
|
-
const
|
|
6987
|
-
|
|
6988
|
-
|
|
6989
|
-
value.
|
|
6990
|
-
|
|
6991
|
-
this.
|
|
7112
|
+
const value = this.value;
|
|
7113
|
+
const index = value ? value.indexOf(item) : -1;
|
|
7114
|
+
if (index !== -1) {
|
|
7115
|
+
const newValue = value.slice();
|
|
7116
|
+
newValue.splice(index, 1);
|
|
7117
|
+
this.writeValue(newValue);
|
|
7118
|
+
this.closePanel();
|
|
6992
7119
|
}
|
|
6993
7120
|
}
|
|
6994
7121
|
/**
|
|
6995
7122
|
* Allow to reload content. Useful when filter has been changed but not detected
|
|
6996
7123
|
*/
|
|
6997
|
-
reloadItems() {
|
|
6998
|
-
|
|
7124
|
+
reloadItems(value) {
|
|
7125
|
+
// Force a refresh
|
|
7126
|
+
this._reload$.next(value || '*');
|
|
6999
7127
|
}
|
|
7000
7128
|
writeValue(value) {
|
|
7001
7129
|
if (this.debug)
|
|
@@ -7012,6 +7140,10 @@ class MatChipsField {
|
|
|
7012
7140
|
this._onTouchedCallback = fn;
|
|
7013
7141
|
}
|
|
7014
7142
|
setDisabledState(isDisabled) {
|
|
7143
|
+
var _a;
|
|
7144
|
+
if (isDisabled && ((_a = this.autocomplete) === null || _a === void 0 ? void 0 : _a.isOpen)) {
|
|
7145
|
+
this.closePanel();
|
|
7146
|
+
}
|
|
7015
7147
|
this.cd.markForCheck();
|
|
7016
7148
|
}
|
|
7017
7149
|
focus() {
|
|
@@ -7031,6 +7163,7 @@ class MatChipsField {
|
|
|
7031
7163
|
return false;
|
|
7032
7164
|
}
|
|
7033
7165
|
const hasContent = selectInputContent(event);
|
|
7166
|
+
// If combo is empty, or if has content but should force to show panel on focus
|
|
7034
7167
|
if (!hasContent || (this.showPanelOnFocus && this.showAllOnFocus)) {
|
|
7035
7168
|
if (this.debug)
|
|
7036
7169
|
console.debug(this.logPrefix + ' Emit focus event');
|
|
@@ -7039,10 +7172,67 @@ class MatChipsField {
|
|
|
7039
7172
|
}
|
|
7040
7173
|
return false;
|
|
7041
7174
|
}
|
|
7175
|
+
filterInputTextBlurEvent(event) {
|
|
7176
|
+
if (!event || event.defaultPrevented)
|
|
7177
|
+
return;
|
|
7178
|
+
// Ignore event from mat-option
|
|
7179
|
+
if (event.relatedTarget instanceof HTMLElement && event.relatedTarget.tagName === 'MAT-OPTION') {
|
|
7180
|
+
event.preventDefault();
|
|
7181
|
+
if (event.stopPropagation)
|
|
7182
|
+
event.stopPropagation();
|
|
7183
|
+
event.returnValue = false;
|
|
7184
|
+
//DEBUG console.debug(this.logPrefix + " Cancelling blur event");
|
|
7185
|
+
return false;
|
|
7186
|
+
}
|
|
7187
|
+
//DEBUG
|
|
7188
|
+
//console.debug(this.logPrefix + ' Blur: move caret to the beginning');
|
|
7189
|
+
// Move caret to the beginning (fix issue IMAGINE-469)
|
|
7190
|
+
selectInputRange(event.target, 0, 0);
|
|
7191
|
+
this.blurred.emit(event);
|
|
7192
|
+
return true;
|
|
7193
|
+
}
|
|
7194
|
+
filterChipsFocusEvent(event) {
|
|
7195
|
+
// DEBUG
|
|
7196
|
+
if (this.debug)
|
|
7197
|
+
console.debug(this.logPrefix + ' Focus in chips list', event);
|
|
7198
|
+
this.matInputText.nativeElement.focus();
|
|
7199
|
+
}
|
|
7042
7200
|
clearValue(event) {
|
|
7043
7201
|
this.writeValue(null);
|
|
7044
7202
|
event.stopPropagation();
|
|
7045
7203
|
}
|
|
7204
|
+
_initAutocompleteInfiniteScroll(threshold) {
|
|
7205
|
+
if (!this.autocomplete)
|
|
7206
|
+
return; // Skip
|
|
7207
|
+
// DEBUG
|
|
7208
|
+
//console.debug(this.logPrefix + ' Init autocomplete scroll listener');
|
|
7209
|
+
if (this._openedSubscription) {
|
|
7210
|
+
this._openedSubscription.unsubscribe();
|
|
7211
|
+
this._subscription.remove(this._openedSubscription);
|
|
7212
|
+
}
|
|
7213
|
+
const opened$ = this.autocomplete._isOpen
|
|
7214
|
+
? timer(0)
|
|
7215
|
+
: this.autocomplete.opened.pipe(debounceTime(200));
|
|
7216
|
+
const scrollEnd$ = opened$
|
|
7217
|
+
.pipe(map((_) => this.getAutocompletePanel()), filter(isNotNil), switchMap((panel) => fromScrollEndEvent(panel, threshold)
|
|
7218
|
+
.pipe(takeUntil(this.autocomplete.closed))));
|
|
7219
|
+
// Trigger fetch more, end end scroll reached
|
|
7220
|
+
this._openedSubscription = scrollEnd$
|
|
7221
|
+
.subscribe(() => this._fetchMore$.emit());
|
|
7222
|
+
// Register subscription
|
|
7223
|
+
this._subscription.add(this._openedSubscription);
|
|
7224
|
+
}
|
|
7225
|
+
get isOpen() {
|
|
7226
|
+
var _a;
|
|
7227
|
+
return ((_a = this.autocomplete) === null || _a === void 0 ? void 0 : _a.isOpen) || false;
|
|
7228
|
+
}
|
|
7229
|
+
closePanel() {
|
|
7230
|
+
var _a, _b;
|
|
7231
|
+
if ((_a = this.autocomplete) === null || _a === void 0 ? void 0 : _a.isOpen) {
|
|
7232
|
+
(_b = this.autocompleteTrigger) === null || _b === void 0 ? void 0 : _b.closePanel();
|
|
7233
|
+
return;
|
|
7234
|
+
}
|
|
7235
|
+
}
|
|
7046
7236
|
/* -- private method -- */
|
|
7047
7237
|
suggest(value, filter) {
|
|
7048
7238
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -7064,7 +7254,7 @@ class MatChipsField {
|
|
|
7064
7254
|
this._itemCount = toNumber(total, data && data.length || 0);
|
|
7065
7255
|
}
|
|
7066
7256
|
// Filter out existing items
|
|
7067
|
-
const filteredData = (res || []).slice().filter(item1 => this.value.findIndex(item2 => this.
|
|
7257
|
+
const filteredData = (res || []).slice().filter(item1 => this.value.findIndex(item2 => this.equals(item1, item2)) === -1);
|
|
7068
7258
|
// Update items count
|
|
7069
7259
|
this._itemCount = this._itemCount - (((res === null || res === void 0 ? void 0 : res.length) || 0) - ((filteredData === null || filteredData === void 0 ? void 0 : filteredData.length) || 0));
|
|
7070
7260
|
if (this.debug)
|
|
@@ -7072,15 +7262,64 @@ class MatChipsField {
|
|
|
7072
7262
|
return res;
|
|
7073
7263
|
});
|
|
7074
7264
|
}
|
|
7265
|
+
fetchMore() {
|
|
7266
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
7267
|
+
if (!this._onFetchMoreCallback)
|
|
7268
|
+
return [];
|
|
7269
|
+
// Save then remove fetch function (to avoid multi-call)
|
|
7270
|
+
const fetchMoreFn = this._onFetchMoreCallback;
|
|
7271
|
+
this._onFetchMoreCallback = undefined;
|
|
7272
|
+
const { data, total, fetchMore } = yield fetchMoreFn();
|
|
7273
|
+
this._itemCount = total || this._itemCount;
|
|
7274
|
+
this._onFetchMoreCallback = fetchMore;
|
|
7275
|
+
this._moreItemsCount = Math.max(0, this._moreItemsCount - data.length); // Borne min = 0
|
|
7276
|
+
return data;
|
|
7277
|
+
});
|
|
7278
|
+
}
|
|
7279
|
+
updateImplicitValue(items) {
|
|
7280
|
+
// Store implicit value (will use it onBlur if not other value selected)
|
|
7281
|
+
if (items && items.length === 1) {
|
|
7282
|
+
this._implicitValue = items[0];
|
|
7283
|
+
//this.formControl.setErrors(null);
|
|
7284
|
+
}
|
|
7285
|
+
else {
|
|
7286
|
+
this._implicitValue = undefined;
|
|
7287
|
+
}
|
|
7288
|
+
}
|
|
7289
|
+
getAutocompletePanel() {
|
|
7290
|
+
var _a, _b;
|
|
7291
|
+
const ele = (_b = (_a = this.autocomplete) === null || _a === void 0 ? void 0 : _a.options.last) === null || _b === void 0 ? void 0 : _b._getHostElement().parentElement;
|
|
7292
|
+
if (!ele) {
|
|
7293
|
+
// DEBUG
|
|
7294
|
+
console.warn(this.logPrefix + ' Unable to find the autocomplete div...');
|
|
7295
|
+
}
|
|
7296
|
+
return ele;
|
|
7297
|
+
}
|
|
7298
|
+
checkIfTouched() {
|
|
7299
|
+
if (this.formControl.touched) {
|
|
7300
|
+
this.cd.markForCheck();
|
|
7301
|
+
this._onTouchedCallback();
|
|
7302
|
+
}
|
|
7303
|
+
}
|
|
7075
7304
|
markForCheck() {
|
|
7076
7305
|
this.cd.markForCheck();
|
|
7077
7306
|
}
|
|
7307
|
+
markAsLoading() {
|
|
7308
|
+
if (this.$filteredItems.value) {
|
|
7309
|
+
this.$filteredItems.next(undefined);
|
|
7310
|
+
this._itemCount = undefined;
|
|
7311
|
+
this._implicitValue = undefined;
|
|
7312
|
+
this._onFetchMoreCallback = undefined;
|
|
7313
|
+
this._moreItemsCount = 0;
|
|
7314
|
+
this.markForCheck();
|
|
7315
|
+
}
|
|
7316
|
+
}
|
|
7078
7317
|
}
|
|
7079
7318
|
MatChipsField.decorators = [
|
|
7080
7319
|
{ type: Component, args: [{
|
|
7081
7320
|
// eslint-disable-next-line @angular-eslint/component-selector
|
|
7082
7321
|
selector: 'mat-chips-field',
|
|
7083
|
-
template: "<ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col class=\"ion-no-padding\">\n <mat-form-field [floatLabel]=\"floatLabel\" class=\"material-chips\" [class.mat-form-field-disabled]=\"disabled\">\n <div matPrefix>\n <ng-
|
|
7322
|
+
template: "<ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col class=\"ion-no-padding\">\n <mat-form-field [floatLabel]=\"floatLabel\" class=\"material-chips\" [class.mat-form-field-disabled]=\"disabled\">\n <div matPrefix>\n <ng-container *ngTemplateOutlet=\"matPrefixTemplate\"></ng-container>\n </div>\n <mat-label>{{placeholder}}</mat-label>\n <mat-chip-list #chipList (focus)=\"matInputText.focus()\">\n <mat-chip\n *ngFor=\"let item of value\"\n [selectable]=\"false\"\n [removable]=\"!disabled\"\n (removed)=\"remove(item)\">\n {{displayWith(item)}}\n <mat-icon matChipRemove *ngIf=\"!disabled\">cancel</mat-icon>\n </mat-chip>\n\n <input matInput #matInputText type=\"text\"\n [matAutocomplete]=\"autocomplete\"\n [matAutocompletePosition]=\"matAutocompletePosition\"\n [formControl]=\"inputControl\"\n [appAutofocus]=\"autofocus\"\n [tabindex]=\"_tabindex\"\n [readonly]=\"disabled\"\n [hidden]=\"disabled\"\n [required]=\"required\"\n (click)=\"clicked.emit($event)\"\n (focus)=\"filterInputTextFocusEvent($event)\"\n (blur)=\"filterInputTextBlurEvent($event)\"\n (keydown.escape)=\"keydownEscape.emit($event)\"\n (keyup.enter)=\"keyupEnter.emit($event)\"\n (keyup.arrowdown)=\"!autocomplete.showPanel && dropButtonClick.emit($event)\"\n [matChipInputFor]=\"chipList\"\n >\n </mat-chip-list>\n\n <!-- autocomplete -->\n <mat-autocomplete #autocomplete=\"matAutocomplete\"\n (optionSelected)=\"add($event)\"\n autoActiveFirstOption\n [displayWith]=\"displayWith\"\n [class]=\"classList\"\n [panelWidth]=\"panelWidth\">\n <ion-row class=\"mat-autocomplete-header ion-no-padding\">\n <ion-col *ngFor=\"let attr of displayAttributes; index as i; last as last\" [size]=\"displayColumnSizes[i]\">\n <ion-label [innerHTML]=\"displayColumnNames[i] | translate\"></ion-label>\n <ion-text color=\"light\" *ngIf=\"last && itemCount; let count\" class=\"ion-float-end ion-padding-end\"><i>{{'COMMON.RESULT_COUNT'|translate: {count: count} }}</i></ion-text>\n </ion-col>\n </ion-row>\n\n <ng-container *ngIf=\"$filteredItems | async; else loadingTemplate; let items\">\n <!-- No item option -->\n <mat-option *ngIf=\"items | isEmptyArray\" class=\"ion-padding text-italic\" disabled>\n <ion-label>{{noResultMessage | translate}}</ion-label>\n </mat-option>\n\n <mat-option *ngFor=\"let item of items\" [value]=\"item\" class=\"ion-no-padding\">\n <ion-row [classList]=\"item.classList\">\n <ion-col *ngFor=\"let path of displayAttributes; index as i;\"\n [size]=\"displayColumnSizes[i]\">\n <ion-text [innerHTML]=\"item | propertyGet: path | highlight: { search: inputControl.value, withAccent: highlightAccent } \"></ion-text>\n </ion-col>\n </ion-row>\n </mat-option>\n\n <!-- More item -->\n <mat-option *ngIf=\"_moreItemsCount\" (ngInit)=\"_initAutocompleteInfiniteScroll()\"\n class=\"ion-padding\" disabled>\n <ion-skeleton-text [animated]=\"true\" style=\"width: 100%\"></ion-skeleton-text>\n </mat-option>\n </ng-container>\n\n <!-- Loading spinner -->\n <ng-template #loadingTemplate>\n <mat-option *ngIf=\"(matInputText.value | strLength) >= suggestLengthThreshold; else waitMoreCharacterTemplate\"\n class=\"ion-padding\" disabled>\n <ion-skeleton-text [animated]=\"true\" style=\"width: 100%\"></ion-skeleton-text>\n </mat-option>\n </ng-template>\n\n <!-- Need more characters -->\n <ng-template #waitMoreCharacterTemplate>\n <mat-option class=\"ion-padding text-italic\" disabled>\n <ion-label>\n {{'INFO.PLEASE_TYPE_MORE_CHARACTERS'|translate:{minLength: suggestLengthThreshold} }}\n </ion-label>\n </mat-option>\n </ng-template>\n </mat-autocomplete>\n\n\n\n <div matSuffix>\n <ng-container *ngTemplateOutlet=\"matSuffixTemplate\"></ng-container>\n </div>\n\n <mat-error *ngIf=\"formControl.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <ng-content select=\"[matError]\"></ng-content>\n\n </mat-form-field>\n\n </ion-col>\n <ion-col size=\"auto\" class=\"ion-align-self-center\">\n <ng-content select=\"[matAfter]\"></ng-content>\n </ion-col>\n </ion-row>\n</ion-grid>\n\n<ng-template #matPrefixTemplate>\n <ng-content select=\"[matPrefix]\"></ng-content>\n</ng-template>\n\n\n<ng-template #matSuffixTemplate>\n <button matSuffix mat-icon-button tabindex=\"-1\"\n type=\"button\"\n (click)=\"dropButtonClick.emit($event)\"\n [hidden]=\"disabled\">\n <mat-icon class=\"large select-arrow\">arrow_drop_down</mat-icon>\n </button>\n <button matSuffix mat-icon-button tabindex=\"-1\"\n type=\"button\"\n *ngIf=\"clearable\"\n (click)=\"clearValue($event)\"\n [hidden]=\"disabled || !formControl.value\">\n <mat-icon>close</mat-icon>\n </button>\n\n <ng-content select=\"[matSuffix]\"></ng-content>\n</ng-template>\n",
|
|
7084
7323
|
providers: [
|
|
7085
7324
|
{
|
|
7086
7325
|
provide: NG_VALUE_ACCESSOR,
|
|
@@ -7097,7 +7336,7 @@ MatChipsField.ctorParameters = () => [
|
|
|
7097
7336
|
{ type: FormGroupDirective, decorators: [{ type: Optional }] }
|
|
7098
7337
|
];
|
|
7099
7338
|
MatChipsField.propDecorators = {
|
|
7100
|
-
|
|
7339
|
+
equals: [{ type: Input }],
|
|
7101
7340
|
logPrefix: [{ type: Input }],
|
|
7102
7341
|
formControl: [{ type: Input }],
|
|
7103
7342
|
formControlName: [{ type: Input }],
|
|
@@ -7116,16 +7355,26 @@ MatChipsField.propDecorators = {
|
|
|
7116
7355
|
highlightAccent: [{ type: Input }],
|
|
7117
7356
|
showAllOnFocus: [{ type: Input }],
|
|
7118
7357
|
showPanelOnFocus: [{ type: Input }],
|
|
7119
|
-
|
|
7358
|
+
autofocus: [{ type: Input }],
|
|
7120
7359
|
config: [{ type: Input }],
|
|
7121
7360
|
i18nPrefix: [{ type: Input }],
|
|
7122
7361
|
noResultMessage: [{ type: Input }],
|
|
7123
|
-
|
|
7362
|
+
classList: [{ type: Input, args: ['class',] }],
|
|
7363
|
+
panelWidth: [{ type: Input }],
|
|
7364
|
+
matAutocompletePosition: [{ type: Input }],
|
|
7124
7365
|
debug: [{ type: Input }],
|
|
7366
|
+
itemSize: [{ type: Input }],
|
|
7367
|
+
fetchMoreThreshold: [{ type: Input }],
|
|
7368
|
+
suggestLengthThreshold: [{ type: Input }],
|
|
7369
|
+
showLoadingSpinner: [{ type: Input }],
|
|
7125
7370
|
clicked: [{ type: Output }],
|
|
7126
7371
|
blurred: [{ type: Output }],
|
|
7127
7372
|
focused: [{ type: Output }],
|
|
7373
|
+
dropButtonClick: [{ type: Output }],
|
|
7374
|
+
keydownEscape: [{ type: Output, args: ['keydown.escape',] }],
|
|
7375
|
+
keyupEnter: [{ type: Output, args: ['keyup.enter',] }],
|
|
7128
7376
|
matInputText: [{ type: ViewChild, args: ['matInputText',] }],
|
|
7377
|
+
autocomplete: [{ type: ViewChild, args: [MatAutocomplete,] }],
|
|
7129
7378
|
autocompleteTrigger: [{ type: ViewChild, args: [MatAutocompleteTrigger,] }],
|
|
7130
7379
|
filter: [{ type: Input }],
|
|
7131
7380
|
tabindex: [{ type: Input }],
|
|
@@ -16367,7 +16616,7 @@ class AutocompleteTestPage {
|
|
|
16367
16616
|
AutocompleteTestPage.decorators = [
|
|
16368
16617
|
{ type: Component, args: [{
|
|
16369
16618
|
selector: 'app-autocomplete-test',
|
|
16370
|
-
template: "<ion-header>\n <ion-toolbar color=\"primary\">\n\n <ion-buttons slot=\"start\">\n <ion-back-button></ion-back-button>\n </ion-buttons>\n\n <ion-title>Autocomplete field test page</ion-title>\n </ion-toolbar>\n</ion-header>\n\n<ion-content>\n\n <!-- Tab nav - mobile/desktop mode -->\n <nav mat-tab-nav-bar>\n <a mat-tab-link\n [active]=\"mode==='mobile'\"\n (click)=\"toggleMode('mobile')\">\n <mat-label>Mobile</mat-label>\n </a>\n <a mat-tab-link [active]=\"mode==='desktop'\"\n (click)=\"toggleMode('desktop')\">\n <mat-label>Desktop</mat-label>\n </a>\n <a mat-tab-link [active]=\"mode==='memory'\"\n (click)=\"toggleMode('memory')\">\n <mat-label>Memory leak debug</mat-label>\n </a>\n <a mat-tab-link\n [active]=\"mode==='temp'\"\n (click)=\"toggleMode('temp')\">\n <mat-label>Temporary</mat-label>\n </a>\n </nav>\n\n <form class=\"form-container\" [formGroup]=\"form\" (ngSubmit)=\"doSubmit($event)\">\n\n <!--<ion-grid *ngIf=\"mode === 'temp'\">\n <ion-row>\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Items is an Observable\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>items: Observable<any[]></pre></small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [logPrefix]=\"'[combo-desktop-2]'\"\n [compareWith]=\"compareWithFn\"\n [mobile]=\"false\"\n ></mat-autocomplete-field>\n </ion-card-content>\n\n </ion-card>\n </ion-col>\n </ion-row>\n\n\n </ion-grid>-->\n\n\n <ion-grid *ngIf=\"mode === 'memory'\">\n\n <!-- debugging memory leak -->\n <ion-row>\n <ion-col>\n <ion-text><h4>Debug memory leak</h4></ion-text>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col size=\"2\">\n <mat-form-field floatLabel=\"always\">\n <input matInput type=\"text\" hidden placeholder=\"Items type\">\n <mat-select (selectionChange)=\"memoryAutocompleteFieldName=$event.value\" [value]=\"memoryAutocompleteFieldName\">\n <mat-option value=\"entity-$items\">Observable</mat-option>\n <mat-option value=\"entity-suggestFn\">Suggest function</mat-option>\n </mat-select>\n </mat-form-field>\n </ion-col>\n <ion-col size=\"1\" class=\"ion-no-padding\">\n <mat-form-field floatLabel=\"always\">\n <input matInput type=\"text\" hidden placeholder=\"Mobile ?\">\n <mat-checkbox (change)=\"memoryMobile=$event.checked\" [checked]=\"memoryMobile\">\n </mat-checkbox>\n </mat-form-field>\n </ion-col>\n\n <ion-col size=\"2\">\n <ion-button *ngIf=\"!memoryTimer\" (click)=\"startMemoryTimer()\" color=\"tertiary\">Start</ion-button>\n <ion-button *ngIf=\"memoryTimer\" (click)=\"stopMemoryTimer()\" color=\"tertiary\">Stop</ion-button>\n </ion-col>\n </ion-row>\n\n <ion-row>\n <ion-col>\n <mat-autocomplete-field formControlName=\"entity\"\n *ngIf=\"!memoryHide && memoryAutocompleteFieldName\"\n [config]=\"autocompleteFields.get(memoryAutocompleteFieldName)\"\n [mobile]=\"memoryMobile\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-memory-leak]'\">\n </mat-autocomplete-field>\n </ion-col>\n </ion-row>\n\n </ion-grid>\n\n <!-- Mobile mode -->\n <ion-grid *ngIf=\"mode === 'mobile'\">\n\n <ion-row>\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Suggest() function\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>mobile: true, suggestFn: (searchText, filter) => any[]</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-suggestFn')\"\n [mobile]=\"true\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-mobile-1]'\"\n [required]=\"true\"\n placeholder=\"Suggest field\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Items is an Observable\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>mobile: true, items: Observable<any[]></pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"true\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-mobile-observable]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Control value if missing in items\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>mobile: true, items: Observable<any[]></pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"missingEntity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"true\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-mobile-2]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Disabled control\n </ion-label>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"disableEntity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"true\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-mobile-2]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n </ion-row>\n\n <ion-row>\n <ion-col size=\"9\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Change filter\n </ion-label>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre></pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col>\n <ion-button (click)=\"updateFilter('entity-items-filter')\">Filter on: {{autocompleteFields.get('entity-items-filter').filter?.searchAttribute }}</ion-button>\n </ion-col>\n <ion-col>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-filter')\"\n [mobile]=\"true\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-mobile-filter]'\"\n ></mat-autocomplete-field>\n </ion-col>\n </ion-row>\n </ion-grid>\n\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col size=\"3\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Large combo\n </ion-label>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>class=\"min-width-large\"</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-large')\"\n [mobile]=\"true\"\n class=\"min-width-large\"\n panelWidth=\"400px\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-mobile-large]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col size=\"6\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Readonly toggle\n </ion-text>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <ion-grid>\n <ion-row>\n <ion-col size=\"3\">\n <mat-checkbox (change)=\"readonlyField.readonly=$event.checked\" [checked]=\"readonlyField.readonly\">\n Readonly ?\n </mat-checkbox>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col>\n <mat-autocomplete-field #readonlyField formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items')\"\n [placeholder]=\"'Entity'\"\n [mobile]=\"true\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-mobile-readonly]'\"\n [readonly]=\"true\"\n [clearable]=\"!readonlyField.readonly\">\n </mat-autocomplete-field>\n </ion-col>\n </ion-row>\n </ion-grid>\n </ion-card-content>\n </ion-card>\n </ion-col>\n </ion-row>\n </ion-grid>\n\n <!-- Desktop mode -->\n <ion-grid *ngIf=\"mode === 'desktop'\">\n <ion-row>\n <ion-col>\n <ion-text><h4>Desktop mode</h4></ion-text>\n </ion-col>\n </ion-row>\n <ion-row>\n\n\n <ion-col size=\"6\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n items from suggest function\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>suggest: (value, filter) => LoadResult<any>\nsuggestLengthThreshold: '3'</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-filter')\"\n [placeholder]=\"'Entity'\"\n [mobile]=\"false\"\n [compareWith]=\"compareWithFn\"\n suggestLengthThreshold=\"3\"\n [logPrefix]=\"'[combo-desktop-suggest]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col size=\"6\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Items is an array\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>items: [], value: {{stringify(form.controls.entity.value)}}</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items')\"\n [logPrefix]=\"'[combo-desktop-array-1]'\"\n [compareWith]=\"compareWithFn\"\n [mobile]=\"false\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Items is an Observable\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>items: Observable<any[]></pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [logPrefix]=\"'[combo-desktop-2]'\"\n [compareWith]=\"compareWithFn\"\n [mobile]=\"false\"\n ></mat-autocomplete-field>\n </ion-card-content>\n\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Control value if missing in items\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>items: Observable<any[]></pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"missingEntity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-desktop-missing]'\"\n [mobile]=\"false\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Full size panel\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>class: 'mat-autocomplete-panel-full-size'</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"false\"\n [class]=\"'mat-autocomplete-panel-full-size'\"\n [compareWith]=\"compareWithFn\"\n [matAutocompletePosition]=\"'above'\"\n [logPrefix]=\"'[combo-desktop-full-size]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Disabled control\n </ion-label>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"disableEntity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"false\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-desktop-disable]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Readonly control\n </ion-label>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"false\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-desktop-readonly]'\"\n [readonly]=\"true\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n </ion-row>\n\n <ion-row>\n <ion-col size=\"9\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Full size combo\n </ion-label>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>class=\"mat-autocomplete-panel-full-size\"</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-large')\"\n [mobile]=\"false\"\n class=\"mat-autocomplete-panel-full-size\"\n panelWidth=\"100vw\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-desktop-full-size]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col size=\"3\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Large combo\n </ion-label>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>panelWidth: string</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-large')\"\n [mobile]=\"false\"\n panelWidth=\"400px\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-desktop-large]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col size=\"6\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Readonly toggle\n </ion-text>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <ion-grid>\n <ion-row>\n <ion-col size=\"3\">\n <mat-checkbox (change)=\"readonlyField.readonly=$event.checked\" [checked]=\"readonlyField.readonly\">\n Readonly ?\n </mat-checkbox>\n </ion-col>\n <ion-col size=\"3\">\n <mat-checkbox #showIcons [checked]=\"false\">\n Icons ?\n </mat-checkbox>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col>\n <mat-autocomplete-field #readonlyField formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-filter')\"\n [placeholder]=\"'Entity'\"\n [mobile]=\"false\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-desktop-readonly]'\"\n [readonly]=\"true\"\n [clearable]=\"!readonlyField.readonly\">\n <mat-icon matPrefix *ngIf=\"showIcons.checked\">keyboard_arrow_right</mat-icon>\n <mat-icon matSuffix *ngIf=\"showIcons.checked\">keyboard_arrow_left</mat-icon>\n </mat-autocomplete-field>\n </ion-col>\n </ion-row>\n </ion-grid>\n </ion-card-content>\n </ion-card>\n </ion-col>\n </ion-row>\n\n </ion-grid>\n\n </form>\n\n</ion-content>\n"
|
|
16619
|
+
template: "<ion-header>\n <ion-toolbar color=\"primary\">\n\n <ion-buttons slot=\"start\">\n <ion-back-button></ion-back-button>\n </ion-buttons>\n\n <ion-title>Autocomplete field test page</ion-title>\n </ion-toolbar>\n</ion-header>\n\n<ion-content>\n\n <!-- Tab nav - mobile/desktop mode -->\n <nav mat-tab-nav-bar>\n <a mat-tab-link\n [active]=\"mode==='mobile'\"\n (click)=\"toggleMode('mobile')\">\n <mat-label>Mobile</mat-label>\n </a>\n <a mat-tab-link [active]=\"mode==='desktop'\"\n (click)=\"toggleMode('desktop')\">\n <mat-label>Desktop</mat-label>\n </a>\n <a mat-tab-link [active]=\"mode==='memory'\"\n (click)=\"toggleMode('memory')\">\n <mat-label>Memory leak debug</mat-label>\n </a>\n <a mat-tab-link\n [active]=\"mode==='temp'\"\n (click)=\"toggleMode('temp')\">\n <mat-label>Temporary</mat-label>\n </a>\n </nav>\n\n <form class=\"form-container\" [formGroup]=\"form\" (ngSubmit)=\"doSubmit($event)\">\n\n <!--<ion-grid *ngIf=\"mode === 'temp'\">\n <ion-row>\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Items is an Observable\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>items: Observable<any[]></pre></small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [logPrefix]=\"'[combo-desktop-2]'\"\n [compareWith]=\"compareWithFn\"\n [mobile]=\"false\"\n ></mat-autocomplete-field>\n </ion-card-content>\n\n </ion-card>\n </ion-col>\n </ion-row>\n\n\n </ion-grid>-->\n\n\n <ion-grid *ngIf=\"mode === 'memory'\">\n\n <!-- debugging memory leak -->\n <ion-row>\n <ion-col>\n <ion-text><h4>Debug memory leak</h4></ion-text>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col size=\"2\">\n <mat-form-field floatLabel=\"always\">\n <input matInput type=\"text\" hidden placeholder=\"Items type\">\n <mat-select (selectionChange)=\"memoryAutocompleteFieldName=$event.value\" [value]=\"memoryAutocompleteFieldName\">\n <mat-option value=\"entity-$items\">Observable</mat-option>\n <mat-option value=\"entity-suggestFn\">Suggest function</mat-option>\n </mat-select>\n </mat-form-field>\n </ion-col>\n <ion-col size=\"1\" class=\"ion-no-padding\">\n <mat-form-field floatLabel=\"always\">\n <input matInput type=\"text\" hidden placeholder=\"Mobile ?\">\n <mat-checkbox (change)=\"memoryMobile=$event.checked\" [checked]=\"memoryMobile\">\n </mat-checkbox>\n </mat-form-field>\n </ion-col>\n\n <ion-col size=\"2\">\n <ion-button *ngIf=\"!memoryTimer\" (click)=\"startMemoryTimer()\" color=\"tertiary\">Start</ion-button>\n <ion-button *ngIf=\"memoryTimer\" (click)=\"stopMemoryTimer()\" color=\"tertiary\">Stop</ion-button>\n </ion-col>\n </ion-row>\n\n <ion-row>\n <ion-col>\n <mat-autocomplete-field formControlName=\"entity\"\n *ngIf=\"!memoryHide && memoryAutocompleteFieldName\"\n [config]=\"autocompleteFields.get(memoryAutocompleteFieldName)\"\n [mobile]=\"memoryMobile\"\n [equals]=\"compareWithFn\"\n [logPrefix]=\"'[combo-memory-leak]'\">\n </mat-autocomplete-field>\n </ion-col>\n </ion-row>\n\n </ion-grid>\n\n <!-- Mobile mode -->\n <ion-grid *ngIf=\"mode === 'mobile'\">\n\n <ion-row>\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Suggest() function\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>mobile: true, suggestFn: (searchText, filter) => any[]</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-suggestFn')\"\n [mobile]=\"true\"\n [equals]=\"compareWithFn\"\n [logPrefix]=\"'[combo-mobile-1]'\"\n [required]=\"true\"\n placeholder=\"Suggest field\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Items is an Observable\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>mobile: true, items: Observable<any[]></pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"true\"\n [equals]=\"compareWithFn\"\n [logPrefix]=\"'[combo-mobile-observable]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Control value if missing in items\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>mobile: true, items: Observable<any[]></pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"missingEntity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"true\"\n [equals]=\"compareWithFn\"\n [logPrefix]=\"'[combo-mobile-2]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Disabled control\n </ion-label>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"disableEntity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"true\"\n [equals]=\"compareWithFn\"\n [logPrefix]=\"'[combo-mobile-2]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n </ion-row>\n\n <ion-row>\n <ion-col size=\"9\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Change filter\n </ion-label>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre></pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col>\n <ion-button (click)=\"updateFilter('entity-items-filter')\">Filter on: {{autocompleteFields.get('entity-items-filter').filter?.searchAttribute }}</ion-button>\n </ion-col>\n <ion-col>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-filter')\"\n [mobile]=\"true\"\n [equals]=\"compareWithFn\"\n [logPrefix]=\"'[combo-mobile-filter]'\"\n ></mat-autocomplete-field>\n </ion-col>\n </ion-row>\n </ion-grid>\n\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col size=\"3\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Large combo\n </ion-label>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>class=\"min-width-large\"</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-large')\"\n [mobile]=\"true\"\n class=\"min-width-large\"\n panelWidth=\"400px\"\n [equals]=\"compareWithFn\"\n [logPrefix]=\"'[combo-mobile-large]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col size=\"6\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Readonly toggle\n </ion-text>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <ion-grid>\n <ion-row>\n <ion-col size=\"3\">\n <mat-checkbox (change)=\"readonlyField.readonly=$event.checked\" [checked]=\"readonlyField.readonly\">\n Readonly ?\n </mat-checkbox>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col>\n <mat-autocomplete-field #readonlyField formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items')\"\n [placeholder]=\"'Entity'\"\n [mobile]=\"true\"\n [equals]=\"compareWithFn\"\n [logPrefix]=\"'[combo-mobile-readonly]'\"\n [readonly]=\"true\"\n [clearable]=\"!readonlyField.readonly\">\n </mat-autocomplete-field>\n </ion-col>\n </ion-row>\n </ion-grid>\n </ion-card-content>\n </ion-card>\n </ion-col>\n </ion-row>\n </ion-grid>\n\n <!-- Desktop mode -->\n <ion-grid *ngIf=\"mode === 'desktop'\">\n <ion-row>\n <ion-col>\n <ion-text><h4>Desktop mode</h4></ion-text>\n </ion-col>\n </ion-row>\n <ion-row>\n\n\n <ion-col size=\"6\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n items from suggest function\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>suggest: (value, filter) => LoadResult<any>\nsuggestLengthThreshold: '3'</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-filter')\"\n [placeholder]=\"'Entity'\"\n [mobile]=\"false\"\n [equals]=\"compareWithFn\"\n suggestLengthThreshold=\"3\"\n [logPrefix]=\"'[combo-desktop-suggest]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col size=\"6\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Items is an array\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>items: [], value: {{stringify(form.controls.entity.value)}}</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items')\"\n [logPrefix]=\"'[combo-desktop-array-1]'\"\n [equals]=\"compareWithFn\"\n [mobile]=\"false\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Items is an Observable\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>items: Observable<any[]></pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [logPrefix]=\"'[combo-desktop-2]'\"\n [equals]=\"compareWithFn\"\n [mobile]=\"false\"\n ></mat-autocomplete-field>\n </ion-card-content>\n\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Control value if missing in items\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>items: Observable<any[]></pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"missingEntity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [equals]=\"compareWithFn\"\n [logPrefix]=\"'[combo-desktop-missing]'\"\n [mobile]=\"false\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Full size panel\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>class: 'mat-autocomplete-panel-full-size'</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"false\"\n [class]=\"'mat-autocomplete-panel-full-size'\"\n [equals]=\"compareWithFn\"\n [matAutocompletePosition]=\"'above'\"\n [logPrefix]=\"'[combo-desktop-full-size]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Disabled control\n </ion-label>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"disableEntity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"false\"\n [equals]=\"compareWithFn\"\n [logPrefix]=\"'[combo-desktop-disable]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Readonly control\n </ion-label>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"false\"\n [equals]=\"compareWithFn\"\n [logPrefix]=\"'[combo-desktop-readonly]'\"\n [readonly]=\"true\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n </ion-row>\n\n <ion-row>\n <ion-col size=\"9\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Full size combo\n </ion-label>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>class=\"mat-autocomplete-panel-full-size\"</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-large')\"\n [mobile]=\"false\"\n class=\"mat-autocomplete-panel-full-size\"\n panelWidth=\"100vw\"\n [equals]=\"compareWithFn\"\n [logPrefix]=\"'[combo-desktop-full-size]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col size=\"3\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Large combo\n </ion-label>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>panelWidth: string</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-large')\"\n [mobile]=\"false\"\n panelWidth=\"400px\"\n [equals]=\"compareWithFn\"\n [logPrefix]=\"'[combo-desktop-large]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col size=\"6\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Readonly toggle\n </ion-text>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <ion-grid>\n <ion-row>\n <ion-col size=\"3\">\n <mat-checkbox (change)=\"readonlyField.readonly=$event.checked\" [checked]=\"readonlyField.readonly\">\n Readonly ?\n </mat-checkbox>\n </ion-col>\n <ion-col size=\"3\">\n <mat-checkbox #showIcons [checked]=\"false\">\n Icons ?\n </mat-checkbox>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col>\n <mat-autocomplete-field #readonlyField formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-filter')\"\n [placeholder]=\"'Entity'\"\n [mobile]=\"false\"\n [equals]=\"compareWithFn\"\n [logPrefix]=\"'[combo-desktop-readonly]'\"\n [readonly]=\"true\"\n [clearable]=\"!readonlyField.readonly\">\n <mat-icon matPrefix *ngIf=\"showIcons.checked\">keyboard_arrow_right</mat-icon>\n <mat-icon matSuffix *ngIf=\"showIcons.checked\">keyboard_arrow_left</mat-icon>\n </mat-autocomplete-field>\n </ion-col>\n </ion-row>\n </ion-grid>\n </ion-card-content>\n </ion-card>\n </ion-col>\n </ion-row>\n\n </ion-grid>\n\n </form>\n\n</ion-content>\n"
|
|
16371
16620
|
},] }
|
|
16372
16621
|
];
|
|
16373
16622
|
AutocompleteTestPage.ctorParameters = () => [
|
|
@@ -16522,7 +16771,7 @@ class SwipeTestPage {
|
|
|
16522
16771
|
SwipeTestPage.decorators = [
|
|
16523
16772
|
{ type: Component, args: [{
|
|
16524
16773
|
selector: 'app-swipe-test',
|
|
16525
|
-
template: "<ion-header>\n <ion-toolbar color=\"primary\">\n\n <ion-buttons slot=\"start\">\n <ion-back-button></ion-back-button>\n </ion-buttons>\n\n <ion-title>Swipe test page</ion-title>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class=\"ion-padding\">\n\n <h1>Swipe page:</h1>\n\n <form class=\"form-container\" [formGroup]=\"form\" (ngSubmit)=\"doSubmit($event)\">\n\n <ion-grid>\n\n <ion-row>\n <!-- empty -->\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Empty\n </ion-label>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-swipe-field formControlName=\"empty\"\n placeholder=\"placeholder\"\n [items]=\"$dates\"\n [displayWith]=\"displayDate()\"\n [
|
|
16774
|
+
template: "<ion-header>\n <ion-toolbar color=\"primary\">\n\n <ion-buttons slot=\"start\">\n <ion-back-button></ion-back-button>\n </ion-buttons>\n\n <ion-title>Swipe test page</ion-title>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class=\"ion-padding\">\n\n <h1>Swipe page:</h1>\n\n <form class=\"form-container\" [formGroup]=\"form\" (ngSubmit)=\"doSubmit($event)\">\n\n <ion-grid>\n\n <ion-row>\n <!-- empty -->\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Empty\n </ion-label>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-swipe-field formControlName=\"empty\"\n placeholder=\"placeholder\"\n [items]=\"$dates\"\n [displayWith]=\"displayDate()\"\n [equals]=\"compareDate()\"\n [tabindex]=\"1\"\n [debug]=\"true\"\n >\n </mat-swipe-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <!-- date -->\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Date\n </ion-label>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-swipe-field formControlName=\"date\"\n placeholder=\"placeholder\"\n [items]=\"$dates\"\n [displayWith]=\"displayDate()\"\n [equals]=\"compareDate()\"\n [clearable]=\"true\"\n [tabindex]=\"2\"\n [debug]=\"true\"\n >\n </mat-swipe-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n </ion-row>\n\n <ion-row>\n <!-- disable -->\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Disabled empty\n </ion-label>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-swipe-field formControlName=\"disabledEmpty\"\n placeholder=\"placeholder\"\n [items]=\"$dates\"\n [displayWith]=\"displayDate()\"\n [equals]=\"compareDate()\"\n [clearable]=\"true\"\n [tabindex]=\"3\"\n [debug]=\"true\"\n >\n </mat-swipe-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n<!-- read-only-->\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Disabled with date\n </ion-label>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-swipe-field formControlName=\"disabledDate\"\n placeholder=\"placeholder\"\n [items]=\"$dates\"\n [displayWith]=\"displayDate()\"\n [equals]=\"compareDate()\"\n [clearable]=\"true\"\n [tabindex]=\"4\"\n [debug]=\"true\"\n >\n </mat-swipe-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n </ion-row>\n\n </ion-grid>\n\n </form>\n\n</ion-content>\n"
|
|
16526
16775
|
},] }
|
|
16527
16776
|
];
|
|
16528
16777
|
SwipeTestPage.ctorParameters = () => [
|
|
@@ -16651,13 +16900,15 @@ class ChipsTestPage {
|
|
|
16651
16900
|
this.autocompleteFields.add('entity-suggestFn', {
|
|
16652
16901
|
suggestFn: (value, filter) => this.suggest(value, filter),
|
|
16653
16902
|
attributes: ['label', 'name'],
|
|
16654
|
-
displayWith: this.entityToString
|
|
16903
|
+
displayWith: this.entityToString,
|
|
16904
|
+
equals: (o1, o2) => EntityUtils.compare(o1, o2, 1, 'id') === 0
|
|
16655
16905
|
});
|
|
16656
16906
|
// From items
|
|
16657
16907
|
this.autocompleteFields.add('entity-items', {
|
|
16658
16908
|
items: FAKE_ENTITIES.slice(),
|
|
16659
16909
|
attributes: ['label', 'name'],
|
|
16660
|
-
displayWith: this.entityToString
|
|
16910
|
+
displayWith: this.entityToString,
|
|
16911
|
+
equals: (o1, o2) => EntityUtils.compare(o1, o2, 1, 'id') === 0
|
|
16661
16912
|
});
|
|
16662
16913
|
// From items
|
|
16663
16914
|
this.autocompleteFields.add('entity-$items', {
|
|
@@ -16709,7 +16960,7 @@ class ChipsTestPage {
|
|
|
16709
16960
|
ChipsTestPage.decorators = [
|
|
16710
16961
|
{ type: Component, args: [{
|
|
16711
16962
|
selector: 'app-chips-test',
|
|
16712
|
-
template: "<ion-header>\n <ion-toolbar color=\"primary\">\n\n <ion-buttons slot=\"start\">\n <ion-back-button></ion-back-button>\n </ion-buttons>\n\n <ion-title>Chips field test page</ion-title>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class=\"ion-padding\">\n\n <form class=\"form-container\" [formGroup]=\"form\" (ngSubmit)=\"doSubmit($event)\">\n\n <ion-grid>\n\n <ion-row>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Suggest() function\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <pre><small>suggestFn: (searchText, filter) => any[]</small></pre>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-chips-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-suggestFn')\"\n [logPrefix]=\"'[mat-chips-empty] '\"\n [
|
|
16963
|
+
template: "<ion-header>\n <ion-toolbar color=\"primary\">\n\n <ion-buttons slot=\"start\">\n <ion-back-button></ion-back-button>\n </ion-buttons>\n\n <ion-title>Chips field test page</ion-title>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class=\"ion-padding\">\n\n <form class=\"form-container\" [formGroup]=\"form\" (ngSubmit)=\"doSubmit($event)\">\n\n <ion-grid>\n\n <ion-row>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Suggest() function\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <pre><small>suggestFn: (searchText, filter) => any[]</small></pre>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-chips-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-suggestFn')\"\n [logPrefix]=\"'[mat-chips-empty] '\"\n [equals]=\"compareWithFn\"\n ></mat-chips-field>\n {{stringify(form.controls.entity.value)}}\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Suggest() function with initial value\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <pre><small>suggestFn: (searchText, filter) => any[]</small></pre>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-chips-field formControlName=\"entityInitial\"\n [config]=\"autocompleteFields.get('entity-suggestFn')\"\n [equals]=\"compareWithFn\"\n [logPrefix]=\"'[mat-chips-initialized] '\"\n ></mat-chips-field>\n {{stringify(form.controls.entityInitial.value)}}\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Disabled control\n </ion-label>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-chips-field formControlName=\"disableEntity\"\n [config]=\"autocompleteFields.get('entity-suggestFn')\"\n [equals]=\"compareWithFn\"\n [logPrefix]=\"'[mat-chips-disabled] '\"\n ></mat-chips-field>\n {{stringify(form.controls.disableEntity.value)}}\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Readonly control\n </ion-label>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-chips-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-suggestFn')\"\n [equals]=\"compareWithFn\"\n [logPrefix]=\"'[mat-chips-readonly] '\"\n [readonly]=\"true\"\n ></mat-chips-field>\n {{stringify(form.controls.entity.value)}}\n </ion-card-content>\n </ion-card>\n </ion-col>\n </ion-row>\n </ion-grid>\n\n </form>\n\n</ion-content>\n"
|
|
16713
16964
|
},] }
|
|
16714
16965
|
];
|
|
16715
16966
|
ChipsTestPage.ctorParameters = () => [
|
|
@@ -17253,11 +17504,18 @@ AuthForm.propDecorators = {
|
|
|
17253
17504
|
};
|
|
17254
17505
|
|
|
17255
17506
|
class AuthModal {
|
|
17256
|
-
constructor(accountService, viewCtrl,
|
|
17507
|
+
constructor(accountService, viewCtrl, cd) {
|
|
17257
17508
|
this.accountService = accountService;
|
|
17258
17509
|
this.viewCtrl = viewCtrl;
|
|
17259
|
-
this.
|
|
17260
|
-
|
|
17510
|
+
this.cd = cd;
|
|
17511
|
+
}
|
|
17512
|
+
get loading() {
|
|
17513
|
+
var _a;
|
|
17514
|
+
return (_a = this.form) === null || _a === void 0 ? void 0 : _a.loading;
|
|
17515
|
+
}
|
|
17516
|
+
ngOnInit() {
|
|
17517
|
+
this.form.markAsReady({ emitEvent: false });
|
|
17518
|
+
this.form.markAsLoaded();
|
|
17261
17519
|
}
|
|
17262
17520
|
cancel() {
|
|
17263
17521
|
this.viewCtrl.dismiss();
|
|
@@ -17267,10 +17525,10 @@ class AuthModal {
|
|
|
17267
17525
|
if (this.form.disabled)
|
|
17268
17526
|
return;
|
|
17269
17527
|
if (!this.form.valid) {
|
|
17270
|
-
this.form.
|
|
17528
|
+
this.form.markAllAsTouched();
|
|
17271
17529
|
return;
|
|
17272
17530
|
}
|
|
17273
|
-
this.
|
|
17531
|
+
this.markAsLoading();
|
|
17274
17532
|
try {
|
|
17275
17533
|
const data = this.form.value;
|
|
17276
17534
|
// Disable the form
|
|
@@ -17279,9 +17537,8 @@ class AuthModal {
|
|
|
17279
17537
|
return this.viewCtrl.dismiss(account);
|
|
17280
17538
|
}
|
|
17281
17539
|
catch (err) {
|
|
17282
|
-
this.loading = false;
|
|
17283
17540
|
this.form.error = err && err.message || err;
|
|
17284
|
-
this.
|
|
17541
|
+
this.markAsLoaded();
|
|
17285
17542
|
// Enable the form
|
|
17286
17543
|
this.form.enable();
|
|
17287
17544
|
// Reset form error on next changes
|
|
@@ -17294,7 +17551,13 @@ class AuthModal {
|
|
|
17294
17551
|
});
|
|
17295
17552
|
}
|
|
17296
17553
|
markForCheck() {
|
|
17297
|
-
this.
|
|
17554
|
+
this.cd.markForCheck();
|
|
17555
|
+
}
|
|
17556
|
+
markAsLoading(opts) {
|
|
17557
|
+
this.form.markAsLoading(opts);
|
|
17558
|
+
}
|
|
17559
|
+
markAsLoaded(opts) {
|
|
17560
|
+
this.form.markAsLoaded(opts);
|
|
17298
17561
|
}
|
|
17299
17562
|
}
|
|
17300
17563
|
AuthModal.decorators = [
|