@sumaris-net/ngx-components 1.6.4 → 1.6.5

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.
@@ -1262,10 +1262,11 @@
1262
1262
  var attributesOrFn = attributes.map(function (a, index) { return typeof a === 'function' && options.attributes[index] || a; });
1263
1263
  var filter = Object.assign({ searchAttribute: attributes.length === 1 ? attributes[0] : undefined, searchAttributes: attributes.length > 1 ? attributes : undefined }, options.filter);
1264
1264
  var displayWith = options.displayWith || (function (obj) { return obj && joinPropertiesPath(obj, attributes); });
1265
- var compareWith = options.equals || (function (o1, o2) { return o1 && o2 && o1.id === o2.id; });
1265
+ var equals = options.equals || (function (o1, o2) { return o1 && o2 && o1.id === o2.id; });
1266
1266
  var config = Object.assign(Object.assign({}, options), { attributes: attributesOrFn, suggestFn: suggestFn,
1267
1267
  filter: filter,
1268
- displayWith: displayWith, equals: compareWith });
1268
+ displayWith: displayWith,
1269
+ equals: equals });
1269
1270
  this.fields[fieldName] = config;
1270
1271
  return config;
1271
1272
  };
@@ -1277,14 +1278,14 @@
1277
1278
  };
1278
1279
  return MatAutocompleteConfigHolder;
1279
1280
  }());
1280
- var noop$7 = function () { };
1281
- var ɵ0$a = noop$7;
1281
+ var noop$8 = function (_) { };
1282
+ var ɵ0$b = noop$8;
1282
1283
  var MatAutocompleteField = /** @class */ (function () {
1283
1284
  function MatAutocompleteField(cd, formGroupDir) {
1284
1285
  this.cd = cd;
1285
1286
  this.formGroupDir = formGroupDir;
1286
- this._onChangeCallback = noop$7;
1287
- this._onTouchedCallback = noop$7;
1287
+ this._onChangeCallback = noop$8;
1288
+ this._onTouchedCallback = noop$8;
1288
1289
  this.logPrefix = '[mat-autocomplete] ';
1289
1290
  this.formControlName = null;
1290
1291
  this.required = false;
@@ -1297,13 +1298,13 @@
1297
1298
  this.fetchMoreThreshold = '15%';
1298
1299
  this.suggestLengthThreshold = null;
1299
1300
  this.showLoadingSpinner = true;
1301
+ this.debug = false;
1300
1302
  this.clicked = new i0.EventEmitter();
1301
1303
  this.blurred = new i0.EventEmitter();
1302
1304
  this.focused = new i0.EventEmitter();
1303
1305
  this.dropButtonClick = new i0.EventEmitter(true);
1304
1306
  this.keydownEscape = new i0.EventEmitter();
1305
1307
  this.keyupEnter = new i0.EventEmitter();
1306
- this.animationsDisabled = true;
1307
1308
  this._readonly = false;
1308
1309
  this.$inputItems = new rxjs.BehaviorSubject(undefined);
1309
1310
  this.$filteredItems = new rxjs.BehaviorSubject(undefined);
@@ -1411,6 +1412,13 @@
1411
1412
  enumerable: false,
1412
1413
  configurable: true
1413
1414
  });
1415
+ Object.defineProperty(MatAutocompleteField.prototype, "loading", {
1416
+ get: function () {
1417
+ return isNil(this.$filteredItems.value);
1418
+ },
1419
+ enumerable: false,
1420
+ configurable: true
1421
+ });
1414
1422
  MatAutocompleteField.prototype.ngOnInit = function () {
1415
1423
  var _this = this;
1416
1424
  var _a, _b;
@@ -1432,7 +1440,7 @@
1432
1440
  this.mobile = toBoolean(this.mobile, this.config.mobile);
1433
1441
  this.suggestLengthThreshold = toNumber(this.suggestLengthThreshold, this.config.suggestLengthThreshold || 0);
1434
1442
  this.showAllOnFocus = toBoolean(this.showAllOnFocus, toBoolean(this.config.showAllOnFocus, this.suggestLengthThreshold <= 0));
1435
- this.showPanelOnFocus = toBoolean(this.showPanelOnFocus, toBoolean(this.config.showPanelOnFocus));
1443
+ this.showPanelOnFocus = toBoolean(this.showPanelOnFocus, toBoolean(this.config.showPanelOnFocus, true));
1436
1444
  this.classList = this.classList || this.config.class;
1437
1445
  this.debounceTime = toNumber(this.debounceTime, this.config.debounceTime);
1438
1446
  this.highlightAccent = toBoolean(this.highlightAccent, toBoolean(this.config.highlightAccent));
@@ -1520,15 +1528,15 @@
1520
1528
  // Filter if not enough character
1521
1529
  operators.filter(function (value) { return value.length >= _this.suggestLengthThreshold; }),
1522
1530
  // Wait a debounce time
1523
- operators.debounceTime(this.debounceTime)
1531
+ operators.debounceTime(this.debounceTime),
1524
1532
  // DEBUG
1525
- //tap((value) => console.debug(this.logPrefix + ' Search text changes:', value)),
1526
- ),
1533
+ operators.tap(function (value) { return console.debug(_this.logPrefix + ' Search text changes:', value); })),
1527
1534
  // Object set: use it (no distinctUntilChanged() pipe need)
1528
1535
  this.formControl.valueChanges
1529
1536
  .pipe(operators.startWith(this.formControl.value), operators.filter(function (value) { return (_this.searchable && isNotNil(value) && typeof value === 'object'); }), operators.tap(function (value) {
1530
1537
  // DEBUG
1531
- //console.debug(this.logPrefix + ' object changes:', value)
1538
+ if (_this.debug)
1539
+ console.debug(_this.logPrefix + ' object changes:', value);
1532
1540
  // Update the display value (if need)
1533
1541
  var displayValue = _this.displayWith(value) || '';
1534
1542
  if (_this.displayValue !== displayValue) {
@@ -1538,10 +1546,9 @@
1538
1546
  _this.matInputText.nativeElement.value = _this.displayValue;
1539
1547
  }
1540
1548
  }
1541
- })
1549
+ }),
1542
1550
  // DEBUG
1543
- //tap(value => console.debug(this.logPrefix + ' Received an object value: ', value))
1544
- ),
1551
+ operators.tap(function (value) { return _this.debug && console.debug(_this.logPrefix + ' Received an object value: ', value); })),
1545
1552
  // On dropdown button click (no distinctUntilChanged(), nor debounceTime)
1546
1553
  this.dropButtonClick
1547
1554
  .pipe(operators.filter(function (event) { return _this.searchable && _this.enabled && (!event || !event.defaultPrevented); }), operators.map(function (_) { return _this.showAllOnFocus ? '*' : _this.formControl.value; }),
@@ -1551,20 +1558,23 @@
1551
1558
  rxjs.merge(
1552
1559
  // Focus or click => Load all
1553
1560
  rxjs.merge(this.focused, this.clicked)
1554
- .pipe(operators.filter(function (_) { return _this.enabled && _this.searchable; }), operators.map(function (_) { return _this.showAllOnFocus ? '*' : _this.formControl.value; })), rxjs.merge(this.$inputItems, this._$filter)
1555
- .pipe(operators.filter(function (_) { return _this.searchable && _this.enabled; }), operators.map(function (_) { return _this.formControl.value; })))
1561
+ .pipe(operators.filter(function (_) { return _this.enabled && _this.searchable; }), operators.map(function (_) { return _this.showAllOnFocus ? '*' : _this.formControl.value; }),
1562
+ // DEBUG
1563
+ operators.tap(function (value) { return _this.debug && console.debug(_this.logPrefix + ' Received focused or clicked event: ', value); })), rxjs.merge(this.$inputItems, this._$filter)
1564
+ .pipe(operators.filter(function (_) { return _this.searchable && _this.enabled; }), operators.map(function (_) { return _this.formControl.value; }),
1565
+ // DEBUG
1566
+ operators.tap(function (value) { return _this.debug && console.debug(_this.logPrefix + ' Received $inputItems or filter event: ', value); })))
1556
1567
  .pipe(
1557
- // Make enough characters
1568
+ // Make sure there is enough characters
1558
1569
  operators.filter(thresholdFilterFn),
1559
1570
  // Distinguish changes
1560
- operators.distinctUntilChanged(),
1561
- // DEBUG
1562
- operators.tap(function (value) { return console.debug(_this.logPrefix + ' Received update event: ', value); })))
1571
+ // - do NOT filter if loading, to force update after a blur event
1572
+ operators.distinctUntilChanged(function (v1, v2) { return !_this.loading && (v1 === v2 || _this.equals(v1, v2)); })))
1563
1573
  .pipe(
1564
1574
  // Suggest values
1565
1575
  operators.mergeMap(function (value) { return _this.suggest(value, _this.filter); }),
1566
1576
  // DEBUG
1567
- //tap(items => console.debug(this.logPrefix + ' Received from suggest: ', items)),
1577
+ operators.tap(function (items) { return _this.debug && console.debug(_this.logPrefix + ' Received from suggest: ', items); }),
1568
1578
  // Store implicit value (will use it onBlur if not other value selected)
1569
1579
  operators.tap(function (items) { return _this.updateImplicitValue(items); }));
1570
1580
  // Fetch more events
@@ -1597,7 +1607,9 @@
1597
1607
  this._subscription.add(this.blurred
1598
1608
  .pipe(
1599
1609
  // Skip if not searchable
1600
- operators.filter(function (_) { return _this.searchable; }), operators.map(function (_) { return _this.formControl.value; }))
1610
+ operators.filter(function (_) { return _this.searchable; }), operators.map(function (_) { return _this.formControl.value; }),
1611
+ // DEBUG
1612
+ operators.tap(function (value) { return console.debug(_this.logPrefix + ' Received blurred event: ', value); }))
1601
1613
  .subscribe(function (value) {
1602
1614
  // When leave component without object, use implicit value if :
1603
1615
  // - an explicit value
@@ -1683,7 +1695,7 @@
1683
1695
  };
1684
1696
  MatAutocompleteField.prototype.writeValue = function (value) {
1685
1697
  // DEBUG
1686
- // console.debug(this.logPrefix + " Writing value: ", value);
1698
+ // console.debug(this.logPrefix + ' Writing value: ', value);
1687
1699
  if (value !== this.formControl.value) {
1688
1700
  this.formControl.patchValue(value, { emitEvent: false });
1689
1701
  this._onChangeCallback(value);
@@ -1720,15 +1732,20 @@
1720
1732
  if (event.stopPropagation)
1721
1733
  event.stopPropagation();
1722
1734
  event.returnValue = false;
1723
- //DEBUG console.debug(this.logPrefix + ' Cancelling focus event');
1735
+ // DEBUG
1736
+ if (this.debug)
1737
+ console.debug(this.logPrefix + ' Cancelling focus event');
1724
1738
  return false;
1725
1739
  }
1726
- var hasContent = selectInputContent(event);
1740
+ if (this.debug)
1741
+ console.debug(this.logPrefix + ' Select input content');
1742
+ var hasContent = true; // selectInputContent(event);
1727
1743
  // If combo is empty, or if has content but should force to show panel on focus
1728
- if (!hasContent || (this.showPanelOnFocus && this.showAllOnFocus)) {
1744
+ if (!hasContent || this.showPanelOnFocus || this.showAllOnFocus) {
1729
1745
  // DEBUG
1730
- //console.debug(this.logPrefix + ' Emit focus event');
1731
- this.focused.emit(event);
1746
+ if (this.debug)
1747
+ console.debug(this.logPrefix + ' Emit focus event');
1748
+ this.focused.emit();
1732
1749
  return true;
1733
1750
  }
1734
1751
  return false;
@@ -1742,11 +1759,14 @@
1742
1759
  if (event.stopPropagation)
1743
1760
  event.stopPropagation();
1744
1761
  event.returnValue = false;
1745
- //DEBUG console.debug(this.logPrefix + " Cancelling blur event");
1762
+ // DEBUG
1763
+ if (this.debug)
1764
+ console.debug(this.logPrefix + " Cancelling blur event");
1746
1765
  return false;
1747
1766
  }
1748
1767
  //DEBUG
1749
- //console.debug(this.logPrefix + ' Blur: move caret to the beginning');
1768
+ if (this.debug)
1769
+ console.debug(this.logPrefix + ' Blur: move caret to the beginning');
1750
1770
  // Move caret to the beginning (fix issue IMAGINE-469)
1751
1771
  selectInputRange(event.target, 0, 0);
1752
1772
  this.blurred.emit(event);
@@ -1888,6 +1908,9 @@
1888
1908
  this._moreItemsCount = fetchMore && (this._itemCount - data.length) || 0;
1889
1909
  res = data;
1890
1910
  }
1911
+ // DEBUG
1912
+ if (this.debug)
1913
+ console.debug(this.logPrefix + ' Filtered items by suggestFn:', value, res);
1891
1914
  return [2 /*return*/, res];
1892
1915
  }
1893
1916
  });
@@ -1969,7 +1992,7 @@
1969
1992
  { type: i0.Component, args: [{
1970
1993
  // eslint-disable-next-line @angular-eslint/component-selector
1971
1994
  selector: 'mat-autocomplete-field',
1972
- 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)=\"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",
1995
+ 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)=\"dropButtonClick.emit($event)\">\n\n <!-- autocomplete -->\n <mat-autocomplete #autocomplete=\"matAutocomplete\"\n autoActiveFirstOption\n [displayWith]=\"displayWith\"\n [class]=\"classList\"\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",
1973
1996
  providers: [{
1974
1997
  provide: i1.NG_VALUE_ACCESSOR,
1975
1998
  multi: true,
@@ -2014,6 +2037,7 @@
2014
2037
  fetchMoreThreshold: [{ type: i0.Input }],
2015
2038
  suggestLengthThreshold: [{ type: i0.Input }],
2016
2039
  showLoadingSpinner: [{ type: i0.Input }],
2040
+ debug: [{ type: i0.Input }],
2017
2041
  clicked: [{ type: i0.Output, args: ['click',] }],
2018
2042
  blurred: [{ type: i0.Output, args: ['blur',] }],
2019
2043
  focused: [{ type: i0.Output, args: ['focus',] }],
@@ -2024,7 +2048,6 @@
2024
2048
  matInputText: [{ type: i0.ViewChild, args: ['matInputText',] }],
2025
2049
  autocomplete: [{ type: i0.ViewChild, args: [autocomplete.MatAutocomplete,] }],
2026
2050
  autocompleteTrigger: [{ type: i0.ViewChild, args: [autocomplete.MatAutocompleteTrigger,] }],
2027
- animationsDisabled: [{ type: i0.HostBinding, args: ['@.disabled',] }],
2028
2051
  filter: [{ type: i0.Input }],
2029
2052
  readonly: [{ type: i0.Input }],
2030
2053
  tabindex: [{ type: i0.Input }],
@@ -4647,9 +4670,9 @@
4647
4670
  DD: [/[+-]/, /\d/, /\d/, /\d/, '.', /\d/, /\d/, /\d/, /\d/, /\d/, /\d/, /\d/, '°']
4648
4671
  }
4649
4672
  };
4650
- var noop$6 = function () {
4673
+ var noop$7 = function () {
4651
4674
  };
4652
- var ɵ0$9 = noop$6;
4675
+ var ɵ0$a = noop$7;
4653
4676
  var MatLatLongField = /** @class */ (function () {
4654
4677
  function MatLatLongField(platform, translate, formBuilder, cd, formGroupDir) {
4655
4678
  this.platform = platform;
@@ -4657,8 +4680,8 @@
4657
4680
  this.formBuilder = formBuilder;
4658
4681
  this.cd = cd;
4659
4682
  this.formGroupDir = formGroupDir;
4660
- this._onChangeCallback = noop$6;
4661
- this._onTouchedCallback = noop$6;
4683
+ this._onChangeCallback = noop$7;
4684
+ this._onTouchedCallback = noop$7;
4662
4685
  this._subscription = new rxjs.Subscription();
4663
4686
  this.disabling = false;
4664
4687
  this.writing = false;
@@ -5015,8 +5038,8 @@
5015
5038
  multi: true
5016
5039
  };
5017
5040
  var DAY_MASK$2 = [/\d/, /\d/, '/', /\d/, /\d/, '/', /\d/, /\d/, /\d/, /\d/];
5018
- var noop$5 = function () { };
5019
- var ɵ0$8 = noop$5;
5041
+ var noop$6 = function () { };
5042
+ var ɵ0$9 = noop$6;
5020
5043
  var MatDate = /** @class */ (function () {
5021
5044
  function MatDate(platform, dateAdapter, translate, formBuilder, cd, keyboard, formGroupDir) {
5022
5045
  this.dateAdapter = dateAdapter;
@@ -5025,8 +5048,8 @@
5025
5048
  this.cd = cd;
5026
5049
  this.keyboard = keyboard;
5027
5050
  this.formGroupDir = formGroupDir;
5028
- this._onChangeCallback = noop$5;
5029
- this._onTouchedCallback = noop$5;
5051
+ this._onChangeCallback = noop$6;
5052
+ this._onTouchedCallback = noop$6;
5030
5053
  this._subscription = new rxjs.Subscription();
5031
5054
  this.writing = true;
5032
5055
  this.disabling = false;
@@ -5340,9 +5363,9 @@
5340
5363
  var DAY_MASK$1 = [/\d/, /\d/, '/', /\d/, /\d/, '/', /\d/, /\d/, /\d/, /\d/];
5341
5364
  var HOUR_REGEXP = /^[012][0-9][:][012345][0-9]$/;
5342
5365
  var HOUR_MASK$1 = [/[012]/, /\d/, ':', /[012345]/, /\d/];
5343
- var noop$4 = function () {
5366
+ var noop$5 = function () {
5344
5367
  };
5345
- var ɵ0$7 = noop$4;
5368
+ var ɵ0$8 = noop$5;
5346
5369
  var MatDateTime = /** @class */ (function () {
5347
5370
  function MatDateTime(platform, dateAdapter, translate, formBuilder, keyboard, cd, formGroupDir) {
5348
5371
  this.platform = platform;
@@ -5352,8 +5375,8 @@
5352
5375
  this.keyboard = keyboard;
5353
5376
  this.cd = cd;
5354
5377
  this.formGroupDir = formGroupDir;
5355
- this._onChangeCallback = noop$4;
5356
- this._onTouchedCallback = noop$4;
5378
+ this._onChangeCallback = noop$5;
5379
+ this._onTouchedCallback = noop$5;
5357
5380
  this._subscription = new rxjs.Subscription();
5358
5381
  this.writing = true;
5359
5382
  this.disabling = false;
@@ -5756,9 +5779,9 @@
5756
5779
  multi: true
5757
5780
  };
5758
5781
  var DAY_MASK = [/\d/, /\d/, /\d/, /\d/];
5759
- var noop$3 = function () {
5782
+ var noop$4 = function () {
5760
5783
  };
5761
- var ɵ0$6 = noop$3;
5784
+ var ɵ0$7 = noop$4;
5762
5785
  var MatDateShort = /** @class */ (function () {
5763
5786
  function MatDateShort(platform, dateAdapter, translate, formBuilder, cd, keyboard, formGroupDir) {
5764
5787
  this.dateAdapter = dateAdapter;
@@ -5767,8 +5790,8 @@
5767
5790
  this.cd = cd;
5768
5791
  this.keyboard = keyboard;
5769
5792
  this.formGroupDir = formGroupDir;
5770
- this._onChangeCallback = noop$3;
5771
- this._onTouchedCallback = noop$3;
5793
+ this._onChangeCallback = noop$4;
5794
+ this._onTouchedCallback = noop$4;
5772
5795
  this.writing = true;
5773
5796
  this.disabling = false;
5774
5797
  this.dayMask = DAY_MASK;
@@ -6126,9 +6149,9 @@
6126
6149
  };
6127
6150
  var HOUR_TIME_PATTERN = /[0-9]\d\d:[0-5]\d/;
6128
6151
  var HOUR_MASK = [/\d/, /\d/, /\d/, ':', /[0-5]/, /\d/];
6129
- var noop$2 = function () {
6152
+ var noop$3 = function () {
6130
6153
  };
6131
- var ɵ0$5 = noop$2;
6154
+ var ɵ0$6 = noop$3;
6132
6155
  var MatDuration = /** @class */ (function () {
6133
6156
  function MatDuration(platform, dateAdapter, translate, formBuilder, cd, formGroupDir) {
6134
6157
  this.dateAdapter = dateAdapter;
@@ -6137,8 +6160,8 @@
6137
6160
  this.cd = cd;
6138
6161
  this.formGroupDir = formGroupDir;
6139
6162
  this._subscription = new rxjs.Subscription();
6140
- this._onChangeCallback = noop$2;
6141
- this._onTouchedCallback = noop$2;
6163
+ this._onChangeCallback = noop$3;
6164
+ this._onTouchedCallback = noop$3;
6142
6165
  this.writing = true;
6143
6166
  this.disabling = false;
6144
6167
  this.hourMask = HOUR_MASK;
@@ -6399,17 +6422,17 @@
6399
6422
  useExisting: i0.forwardRef(function () { return MatBooleanField; }),
6400
6423
  multi: true
6401
6424
  };
6402
- var noop$1 = function () {
6425
+ var noop$2 = function () {
6403
6426
  };
6404
- var ɵ0$4 = noop$1;
6427
+ var ɵ0$5 = noop$2;
6405
6428
  var MatBooleanField = /** @class */ (function () {
6406
6429
  function MatBooleanField(translate, formBuilder, cd, formGroupDir) {
6407
6430
  this.translate = translate;
6408
6431
  this.formBuilder = formBuilder;
6409
6432
  this.cd = cd;
6410
6433
  this.formGroupDir = formGroupDir;
6411
- this._onChangeCallback = noop$1;
6412
- this._onTouchedCallback = noop$1;
6434
+ this._onChangeCallback = noop$2;
6435
+ this._onTouchedCallback = noop$2;
6413
6436
  this._writing = false;
6414
6437
  this.showRadio = false;
6415
6438
  this.disabled = false;
@@ -7627,12 +7650,14 @@
7627
7650
  },] }
7628
7651
  ];
7629
7652
 
7653
+ var noop$1 = function () { };
7654
+ var ɵ0$4 = noop$1;
7630
7655
  var MatChipsField = /** @class */ (function () {
7631
7656
  function MatChipsField(cd, formGroupDir) {
7632
7657
  this.cd = cd;
7633
7658
  this.formGroupDir = formGroupDir;
7634
- this._onChangeCallback = function (_) { };
7635
- this._onTouchedCallback = function () { };
7659
+ this._onChangeCallback = noop$1;
7660
+ this._onTouchedCallback = noop$1;
7636
7661
  this.logPrefix = '[mat-chips] ';
7637
7662
  this.formControlName = null;
7638
7663
  this.required = false;
@@ -7641,12 +7666,12 @@
7641
7666
  this.debounceTime = null;
7642
7667
  this.i18nPrefix = 'REFERENTIAL.';
7643
7668
  this.noResultMessage = 'COMMON.NO_RESULT';
7644
- this.debug = false;
7645
7669
  this.itemSize = '48px';
7646
7670
  this.fetchMoreThreshold = '15%';
7647
7671
  this.suggestLengthThreshold = null;
7648
7672
  this.showLoadingSpinner = true;
7649
7673
  this.chipColor = null;
7674
+ this.debug = false;
7650
7675
  this.clicked = new i0.EventEmitter();
7651
7676
  this.blurred = new i0.EventEmitter();
7652
7677
  this.focused = new i0.EventEmitter();
@@ -7748,6 +7773,13 @@
7748
7773
  enumerable: false,
7749
7774
  configurable: true
7750
7775
  });
7776
+ Object.defineProperty(MatChipsField.prototype, "loading", {
7777
+ get: function () {
7778
+ return isNil(this.$filteredItems.value);
7779
+ },
7780
+ enumerable: false,
7781
+ configurable: true
7782
+ });
7751
7783
  MatChipsField.prototype.ngOnInit = function () {
7752
7784
  var _this = this;
7753
7785
  var _a, _b;
@@ -7854,19 +7886,9 @@
7854
7886
  ),
7855
7887
  // Object set: use it (no distinctUntilChanged() pipe need)
7856
7888
  this.inputControl.valueChanges
7857
- .pipe(operators.startWith(this.inputControl.value), operators.filter(function (value) { return isNotNil(value) && typeof value === 'object'; }), operators.tap(function (value) {
7858
- // DEBUG
7859
- //console.debug(this.logPrefix + ' object changes:', value)
7860
- // Update the display value (if need)
7861
- var displayValue = _this.displayWith(value) || '';
7862
- // Apply to the input[type=text] field
7863
- if (_this.matInputText && _this.matInputText.nativeElement) {
7864
- _this.matInputText.nativeElement.value = displayValue;
7865
- }
7866
- })
7889
+ .pipe(operators.startWith(this.inputControl.value), operators.filter(function (value) { return isNotNil(value) && typeof value === 'object'; }),
7867
7890
  // DEBUG
7868
- //tap(value => console.debug(this.logPrefix + ' Received an object value: ', value))
7869
- ),
7891
+ operators.tap(function (value) { return _this.debug && console.debug(_this.logPrefix + ' Received an object value: ', value); })),
7870
7892
  // On dropdown button click (no distinctUntilChanged(), nor debounceTime)
7871
7893
  this.dropButtonClick
7872
7894
  .pipe(operators.filter(function (event) { return _this.enabled && (!event || !event.defaultPrevented); }), operators.tap(function (_) { return _this.matInputText.nativeElement.focus(); }), operators.map(function (_) { return _this.showAllOnFocus ? '*' : _this.formControl.value; }),
@@ -7956,7 +7978,9 @@
7956
7978
  this._openedSubscription.unsubscribe();
7957
7979
  }
7958
7980
  this.$inputItems.complete();
7981
+ this.$inputItems.unsubscribe();
7959
7982
  this.$filteredItems.complete();
7983
+ this.$filteredItems.unsubscribe();
7960
7984
  this._reload$.complete();
7961
7985
  this._$filter.complete();
7962
7986
  this.dropButtonClick.complete();
@@ -8018,12 +8042,18 @@
8018
8042
  this._reload$.next(value || '*');
8019
8043
  };
8020
8044
  MatChipsField.prototype.writeValue = function (value) {
8021
- if (this.debug)
8022
- console.debug(this.logPrefix + ' Writing value: ', value);
8045
+ if (value && !Array.isArray(value)) {
8046
+ value = [value];
8047
+ }
8023
8048
  if (value !== this.formControl.value) {
8049
+ if (this.debug)
8050
+ console.debug(this.logPrefix + ' Writing value: ', value);
8024
8051
  this.formControl.patchValue(value, { emitEvent: false });
8025
8052
  this._onChangeCallback(value);
8026
8053
  }
8054
+ else {
8055
+ this.markForCheck();
8056
+ }
8027
8057
  };
8028
8058
  MatChipsField.prototype.registerOnChange = function (fn) {
8029
8059
  this._onChangeCallback = fn;
@@ -8134,7 +8164,7 @@
8134
8164
  /* -- private method -- */
8135
8165
  MatChipsField.prototype.suggest = function (value, filter) {
8136
8166
  return __awaiter(this, void 0, void 0, function () {
8137
- var res, data, total, filteredData;
8167
+ var res, data, total, fetchMore, filteredData, removedItemCount;
8138
8168
  var _this = this;
8139
8169
  return __generator(this, function (_c) {
8140
8170
  switch (_c.label) {
@@ -8142,7 +8172,7 @@
8142
8172
  case 1:
8143
8173
  res = _c.sent();
8144
8174
  // DEBUG
8145
- // console.debug(this.logPrefix + " Filtered items by suggestFn:", value, res);
8175
+ //console.debug(this.logPrefix + ' Filtered items by suggestFn:', value, res);
8146
8176
  if (!res) {
8147
8177
  this._itemCount = 0;
8148
8178
  res = [];
@@ -8152,13 +8182,16 @@
8152
8182
  this._itemCount = res.length || 0;
8153
8183
  }
8154
8184
  else {
8155
- data = res.data, total = res.total;
8156
- res = data;
8185
+ data = res.data, total = res.total, fetchMore = res.fetchMore;
8157
8186
  this._itemCount = toNumber(total, data && data.length || 0);
8187
+ this._onFetchMoreCallback = fetchMore;
8188
+ this._moreItemsCount = fetchMore && (this._itemCount - data.length) || 0;
8189
+ res = data;
8158
8190
  }
8159
8191
  filteredData = (res || []).slice().filter(function (item1) { return _this.value.findIndex(function (item2) { return _this.equals(item1, item2); }) === -1; });
8160
- // Update items count
8161
- this._itemCount = this._itemCount - (((res === null || res === void 0 ? void 0 : res.length) || 0) - ((filteredData === null || filteredData === void 0 ? void 0 : filteredData.length) || 0));
8192
+ removedItemCount = (((res === null || res === void 0 ? void 0 : res.length) || 0) - ((filteredData === null || filteredData === void 0 ? void 0 : filteredData.length) || 0));
8193
+ // Decrease the item count, with delta
8194
+ this._itemCount -= removedItemCount;
8162
8195
  if (this.debug)
8163
8196
  console.debug(this.logPrefix + ' Filtered items by suggestFn:', value, res);
8164
8197
  return [2 /*return*/, res];
@@ -8197,6 +8230,12 @@
8197
8230
  this._implicitValue = undefined;
8198
8231
  }
8199
8232
  };
8233
+ MatChipsField.prototype.checkIfTouched = function () {
8234
+ if (this.formControl.touched) {
8235
+ this.cd.markForCheck();
8236
+ this._onTouchedCallback();
8237
+ }
8238
+ };
8200
8239
  MatChipsField.prototype.getAutocompletePanel = function () {
8201
8240
  var _a, _b;
8202
8241
  var ele = (_b = (_a = this.autocomplete) === null || _a === void 0 ? void 0 : _a.options.last) === null || _b === void 0 ? void 0 : _b._getHostElement().parentElement;
@@ -8206,12 +8245,6 @@
8206
8245
  }
8207
8246
  return ele;
8208
8247
  };
8209
- MatChipsField.prototype.checkIfTouched = function () {
8210
- if (this.formControl.touched) {
8211
- this.cd.markForCheck();
8212
- this._onTouchedCallback();
8213
- }
8214
- };
8215
8248
  MatChipsField.prototype.markForCheck = function () {
8216
8249
  this.cd.markForCheck();
8217
8250
  };
@@ -8232,13 +8265,11 @@
8232
8265
  // eslint-disable-next-line @angular-eslint/component-selector
8233
8266
  selector: 'mat-chips-field',
8234
8267
  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\n (focus)=\"filterChipsFocusEvent($event)\" >\n <mat-chip\n *ngFor=\"let item of value\"\n [selectable]=\"false\"\n [removable]=\"!disabled\"\n (removed)=\"remove(item)\"\n [color]=\"chipColor\"\n >\n {{displayWith(item)}}\n <mat-icon matChipRemove *ngIf=\"!disabled\">cancel</mat-icon>\n </mat-chip>\n\n <input #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 <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 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 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",
8235
- providers: [
8236
- {
8268
+ providers: [{
8237
8269
  provide: i1.NG_VALUE_ACCESSOR,
8238
8270
  multi: true,
8239
8271
  useExisting: i0.forwardRef(function () { return MatChipsField; })
8240
- }
8241
- ],
8272
+ }],
8242
8273
  encapsulation: i0.ViewEncapsulation.None,
8243
8274
  changeDetection: i0.ChangeDetectionStrategy.OnPush,
8244
8275
  styles: [":host{width:100%;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%}.mat-form-field-suffix{position:absolute!important;right:0!important;top:calc(100% - 50px)!important}.mat-chip.mat-standard-chip.mat-primary{background-color:var(--ion-color-primary);color:var(--ion-color-primary-contrast)}.mat-chip.mat-standard-chip.mat-secondary{background-color:var(--ion-color-secondary);color:var(--ion-color-secondary-contrast)}.mat-chip.mat-standard-chip.mat-tertiary{background-color:var(--ion-color-tertiary);color:var(--ion-color-tertiary-contrast)}.mat-chip.mat-standard-chip.mat-accent{background-color:var(--ion-color-accent);color:var(--ion-color-accent-contrast)}.mat-chip.mat-standard-chip.mat-warning{background-color:var(--ion-color-warning);color:var(--ion-color-warning-contrast)}"]
@@ -8275,12 +8306,12 @@
8275
8306
  classList: [{ type: i0.Input, args: ['class',] }],
8276
8307
  panelWidth: [{ type: i0.Input }],
8277
8308
  matAutocompletePosition: [{ type: i0.Input }],
8278
- debug: [{ type: i0.Input }],
8279
8309
  itemSize: [{ type: i0.Input }],
8280
8310
  fetchMoreThreshold: [{ type: i0.Input }],
8281
8311
  suggestLengthThreshold: [{ type: i0.Input }],
8282
8312
  showLoadingSpinner: [{ type: i0.Input }],
8283
8313
  chipColor: [{ type: i0.Input }],
8314
+ debug: [{ type: i0.Input }],
8284
8315
  clicked: [{ type: i0.Output }],
8285
8316
  blurred: [{ type: i0.Output }],
8286
8317
  focused: [{ type: i0.Output }],
@@ -18955,7 +18986,7 @@
18955
18986
  function AutocompleteTestPage(formBuilder) {
18956
18987
  this.formBuilder = formBuilder;
18957
18988
  this._items = deepCopy$1(FAKE_ENTITIES$1, 100);
18958
- this.$items = new rxjs.BehaviorSubject(undefined);
18989
+ this._$items = new rxjs.BehaviorSubject(undefined);
18959
18990
  this.autocompleteFields = new MatAutocompleteConfigHolder();
18960
18991
  this.memoryHide = false;
18961
18992
  this.memoryMobile = true;
@@ -18985,7 +19016,7 @@
18985
19016
  });
18986
19017
  // From $items observable
18987
19018
  this.autocompleteFields.add('entity-$items', {
18988
- items: this.$items,
19019
+ items: this._$items,
18989
19020
  attributes: ['label', 'name'],
18990
19021
  displayWith: this.entityToString
18991
19022
  });
@@ -19029,7 +19060,7 @@
19029
19060
  AutocompleteTestPage.prototype.loadItems = function () {
19030
19061
  return __awaiter(this, void 0, void 0, function () {
19031
19062
  return __generator(this, function (_a) {
19032
- this.$items.next(this._items.slice());
19063
+ this._$items.next(this._items.slice());
19033
19064
  return [2 /*return*/];
19034
19065
  });
19035
19066
  });
@@ -19070,7 +19101,7 @@
19070
19101
  AutocompleteTestPage.prototype.doSubmit = function (event) {
19071
19102
  console.debug('Validate form: ', this.form.value);
19072
19103
  };
19073
- AutocompleteTestPage.prototype.compareWithFn = function (o1, o2) {
19104
+ AutocompleteTestPage.prototype.equals = function (o1, o2) {
19074
19105
  return o1 && o2 && o1.id === o2.id;
19075
19106
  };
19076
19107
  AutocompleteTestPage.prototype.toggleMode = function (value) {
@@ -19103,7 +19134,7 @@
19103
19134
  AutocompleteTestPage.decorators = [
19104
19135
  { type: i0.Component, args: [{
19105
19136
  selector: 'app-autocomplete-test',
19106
- 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&lt;any[]&gt;</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) =&gt; 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&lt;any[]&gt;</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&lt;any[]&gt;</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&lt;any&gt;</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 [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 search with a suggestLengthThreshold\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>suggest: (value, filter) => LoadResult&lt;any&gt;\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&lt;any[]&gt;</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&lt;any[]&gt;</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"
19137
+ 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&lt;any[]&gt;</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]=\"equals\"\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) =&gt; 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]=\"equals\"\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&lt;any[]&gt;</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]=\"equals\"\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&lt;any[]&gt;</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]=\"equals\"\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]=\"equals\"\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]=\"equals\"\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]=\"equals\"\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]=\"equals\"\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&lt;any&gt;</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]=\"equals\"\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 search with a suggestLengthThreshold\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>suggest: (value, filter) => LoadResult&lt;any&gt;\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]=\"equals\"\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]=\"equals\"\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&lt;any[]&gt;</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]=\"equals\"\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&lt;any[]&gt;</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]=\"equals\"\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 [matAutocompletePosition]=\"'above'\"\n [logPrefix]=\"'[combo-desktop-full-size]'\"\n [debug]=\"true\"\n [showAllOnFocus]=\"true\"\n [showPanelOnFocus]=\"true\"\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]=\"equals\"\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]=\"equals\"\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]=\"equals\"\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]=\"equals\"\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]=\"equals\"\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"
19107
19138
  },] }
19108
19139
  ];
19109
19140
  AutocompleteTestPage.ctorParameters = function () { return [
@@ -19397,13 +19428,24 @@
19397
19428
  { id: 6, label: 'FFF', name: 'Item F' },
19398
19429
  { id: 7, label: 'GGG', name: 'Item G' }
19399
19430
  ];
19400
- function deepCopy(values) {
19401
- return (values || FAKE_ENTITIES).map(function (entity) { return Object.assign({}, entity); });
19431
+ function deepCopy(values, size) {
19432
+ if (isNil(size)) {
19433
+ return (values || FAKE_ENTITIES).map(function (entity) { return Object.assign({}, entity); });
19434
+ }
19435
+ var result = [];
19436
+ var i = 1;
19437
+ while (result.length < size) {
19438
+ result = result.concat((values || FAKE_ENTITIES).map(function (entity) {
19439
+ var name = entity.name + ' #' + i;
19440
+ return Object.assign(Object.assign({}, entity), { id: i++, name: name });
19441
+ }));
19442
+ }
19443
+ return result.slice(0, size);
19402
19444
  }
19403
19445
  var ChipsTestPage = /** @class */ (function () {
19404
19446
  function ChipsTestPage(formBuilder) {
19405
19447
  this.formBuilder = formBuilder;
19406
- this._items = deepCopy(FAKE_ENTITIES);
19448
+ this._items = deepCopy(FAKE_ENTITIES, 100);
19407
19449
  this._$items = new rxjs.BehaviorSubject(undefined);
19408
19450
  this.autocompleteFields = new MatAutocompleteConfigHolder();
19409
19451
  this.form = formBuilder.group({
@@ -19424,12 +19466,12 @@
19424
19466
  });
19425
19467
  // From items
19426
19468
  this.autocompleteFields.add('entity-items', {
19427
- items: FAKE_ENTITIES.slice(),
19469
+ items: this._items.slice(),
19428
19470
  attributes: ['label', 'name'],
19429
19471
  displayWith: this.entityToString,
19430
19472
  equals: function (o1, o2) { return EntityUtils.compare(o1, o2, 1, 'id') === 0; }
19431
19473
  });
19432
- // From items
19474
+ // From $items observable
19433
19475
  this.autocompleteFields.add('entity-$items', {
19434
19476
  items: this._$items,
19435
19477
  attributes: ['label', 'name'],
@@ -19443,15 +19485,18 @@
19443
19485
  // Load the form with data
19444
19486
  ChipsTestPage.prototype.loadData = function () {
19445
19487
  return __awaiter(this, void 0, void 0, function () {
19446
- var data;
19488
+ var items, data;
19489
+ var _this = this;
19447
19490
  return __generator(this, function (_a) {
19491
+ items = deepCopy(FAKE_ENTITIES);
19448
19492
  data = {
19449
- entity: [],
19450
- // THis item is NOT in the items list => i should be displayed anyway
19451
- entityInitial: FAKE_ENTITIES.slice(1, 2),
19452
- disableEntity: FAKE_ENTITIES.slice(1, 2)
19493
+ entity: items.slice(0, 1),
19494
+ entityInitial: items.slice(1, 2),
19495
+ disableEntity: items.slice(1, 2)
19453
19496
  };
19454
19497
  this.form.setValue(data);
19498
+ // Load observables
19499
+ setTimeout(function () { return _this.loadItems(); }, 1000);
19455
19500
  return [2 /*return*/];
19456
19501
  });
19457
19502
  });
@@ -19459,7 +19504,7 @@
19459
19504
  ChipsTestPage.prototype.loadItems = function () {
19460
19505
  return __awaiter(this, void 0, void 0, function () {
19461
19506
  return __generator(this, function (_a) {
19462
- this._$items.next(deepCopy(FAKE_ENTITIES));
19507
+ this._$items.next(this._items.slice());
19463
19508
  return [2 /*return*/];
19464
19509
  });
19465
19510
  });
@@ -19469,8 +19514,31 @@
19469
19514
  };
19470
19515
  ChipsTestPage.prototype.suggest = function (value, filter) {
19471
19516
  return __awaiter(this, void 0, void 0, function () {
19517
+ var res, total, nextOffset;
19518
+ var _this = this;
19472
19519
  return __generator(this, function (_a) {
19473
- return [2 /*return*/, suggestFromArray(this._items, value, Object.assign(Object.assign({}, filter), { searchAttributes: ['label', 'name'] }))];
19520
+ filter = Object.assign({ offset: 0, size: 30 }, filter);
19521
+ res = suggestFromArray(this._items, value, Object.assign(Object.assign({}, filter), { searchAttributes: ['label', 'name'] }));
19522
+ total = res.total || res.data.length;
19523
+ nextOffset = filter.offset + res.data.length;
19524
+ if (nextOffset < total) {
19525
+ filter = Object.assign(Object.assign({}, filter), { offset: nextOffset });
19526
+ return [2 /*return*/, {
19527
+ total: total,
19528
+ data: res.data,
19529
+ fetchMore: function (variables) { return __awaiter(_this, void 0, void 0, function () {
19530
+ return __generator(this, function (_a) {
19531
+ switch (_a.label) {
19532
+ case 0: return [4 /*yield*/, sleep(1000)];
19533
+ case 1:
19534
+ _a.sent();
19535
+ return [2 /*return*/, this.suggest(value, Object.assign(Object.assign({}, filter), variables))];
19536
+ }
19537
+ });
19538
+ }); }
19539
+ }];
19540
+ }
19541
+ return [2 /*return*/, res];
19474
19542
  });
19475
19543
  });
19476
19544
  };
@@ -19489,7 +19557,7 @@
19489
19557
  ChipsTestPage.decorators = [
19490
19558
  { type: i0.Component, args: [{
19491
19559
  selector: 'app-chips-test',
19492
- 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) =&gt; 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 chipColor=\"accent\"\n [debug]=\"true\"\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) =&gt; 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 [logPrefix]=\"'[mat-chips-initialized] '\"\n chipColor=\"primary\"\n [debug]=\"true\"\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]=\"equals\"\n [logPrefix]=\"'[mat-chips-disabled] '\"\n chipColor=\"warning\"\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]=\"equals\"\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"
19560
+ 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) =&gt; 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 chipColor=\"accent\"\n [debug]=\"false\"\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) =&gt; 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 [logPrefix]=\"'[mat-chips-initialized] '\"\n chipColor=\"primary\"\n [debug]=\"true\"\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]=\"equals\"\n [logPrefix]=\"'[mat-chips-disabled] '\"\n chipColor=\"warning\"\n [debug]=\"true\"\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]=\"equals\"\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"
19493
19561
  },] }
19494
19562
  ];
19495
19563
  ChipsTestPage.ctorParameters = function () { return [
@@ -29231,7 +29299,6 @@
29231
29299
  exports.waitForTrue = waitForTrue;
29232
29300
  exports.waitIdle = waitIdle;
29233
29301
  exports.waitWhilePending = waitWhilePending;
29234
- exports["ɵ0"] = ɵ0$5;
29235
29302
  exports["ɵa"] = CustomReuseStrategy;
29236
29303
  exports["ɵb"] = MatNumpadDomService;
29237
29304
  exports["ɵc"] = SharedMatBadgeIconModule;