@sumaris-net/ngx-components 1.6.6 → 1.6.11

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.
Files changed (29) hide show
  1. package/bundles/sumaris-net.ngx-components.umd.js +130 -116
  2. package/bundles/sumaris-net.ngx-components.umd.js.map +1 -1
  3. package/bundles/sumaris-net.ngx-components.umd.min.js +2 -2
  4. package/bundles/sumaris-net.ngx-components.umd.min.js.map +1 -1
  5. package/doc/changelog.md +3 -0
  6. package/esm2015/public_api.js +3 -3
  7. package/esm2015/src/app/core/auth/form/form-auth.js +2 -2
  8. package/esm2015/src/app/core/services/model/filter.model.js +1 -1
  9. package/esm2015/src/app/core/services/model/referential.model.js +1 -1
  10. package/esm2015/src/app/core/table/table.class.js +8 -8
  11. package/esm2015/src/app/shared/form/field.component.js +2 -2
  12. package/esm2015/src/app/shared/material/autocomplete/material.autocomplete.js +25 -22
  13. package/esm2015/src/app/shared/material/boolean/material.boolean.js +3 -4
  14. package/esm2015/src/app/shared/material/chips/material.chips.js +21 -9
  15. package/esm2015/src/app/shared/material/datetime/material.date.js +42 -42
  16. package/esm2015/src/app/shared/material/datetime/material.dateshort.js +2 -2
  17. package/esm2015/src/app/shared/material/datetime/material.datetime.js +32 -32
  18. package/esm2015/src/app/shared/material/duration/material.duration.js +2 -2
  19. package/fesm2015/sumaris-net.ngx-components.js +128 -114
  20. package/fesm2015/sumaris-net.ngx-components.js.map +1 -1
  21. package/package.json +1 -1
  22. package/public_api.d.ts +2 -2
  23. package/src/app/core/services/model/filter.model.d.ts +1 -1
  24. package/src/app/core/services/model/referential.model.d.ts +3 -3
  25. package/src/app/core/table/table.class.d.ts +4 -4
  26. package/src/app/shared/material/boolean/material.boolean.d.ts +0 -1
  27. package/src/app/shared/material/datetime/material.date.d.ts +6 -6
  28. package/src/app/shared/material/datetime/material.datetime.d.ts +11 -11
  29. package/sumaris-net.ngx-components.metadata.json +1 -1
@@ -1189,9 +1189,10 @@ class MatAutocompleteField {
1189
1189
  // Filter if not enough character
1190
1190
  filter(value => value.length >= this.suggestLengthThreshold),
1191
1191
  // Wait a debounce time
1192
- debounceTime(this.debounceTime),
1192
+ debounceTime(this.debounceTime)
1193
1193
  // DEBUG
1194
- tap((value) => console.debug(this.logPrefix + ' Search text changes:', value))),
1194
+ //,tap((value) => this.debug && console.debug(this.logPrefix + ' Search text changes:', value))
1195
+ ),
1195
1196
  // Object set: use it (no distinctUntilChanged() pipe need)
1196
1197
  this.formControl.valueChanges
1197
1198
  .pipe(startWith(this.formControl.value), filter(value => (this.searchable && isNotNil(value) && typeof value === 'object')), tap(value => {
@@ -1207,35 +1208,38 @@ class MatAutocompleteField {
1207
1208
  this.matInputText.nativeElement.value = this.displayValue;
1208
1209
  }
1209
1210
  }
1210
- }),
1211
+ })
1211
1212
  // DEBUG
1212
- tap(value => this.debug && console.debug(this.logPrefix + ' Received an object value: ', value))),
1213
+ //,tap(value => this.debug && console.debug(this.logPrefix + ' Received an object value: ', value))
1214
+ ),
1213
1215
  // On dropdown button click (no distinctUntilChanged(), nor debounceTime)
1214
1216
  this.dropButtonClick
1215
1217
  .pipe(filter(event => this.searchable && this.enabled && (!event || !event.defaultPrevented)), map(_ => this.showAllOnFocus ? '*' : this.formControl.value),
1216
- // Make enough characters
1218
+ // Make sure there is enough characters
1217
1219
  filter(thresholdFilterFn)),
1218
1220
  // Merge some observables, with a common distinctUntilChanged() pipe, and NO debounceTime
1219
1221
  merge(
1220
1222
  // Focus or click => Load all
1221
1223
  merge(this.focused, this.clicked)
1222
- .pipe(filter(_ => this.enabled && this.searchable), map(_ => this.showAllOnFocus ? '*' : this.formControl.value),
1223
- // DEBUG
1224
- tap(value => this.debug && console.debug(this.logPrefix + ' Received focused or clicked event: ', value))), merge(this.$inputItems, this._$filter)
1225
- .pipe(filter(_ => this.searchable && this.enabled), map(_ => this.formControl.value),
1224
+ .pipe(filter(_ => this.enabled && this.searchable), map(_ => this.showAllOnFocus ? '*' : this.formControl.value)
1226
1225
  // DEBUG
1227
- tap(value => this.debug && console.debug(this.logPrefix + ' Received $inputItems or filter event: ', value))))
1226
+ //,tap(value => this.debug && console.debug(this.logPrefix + ' Received focused or clicked event: ', value))
1227
+ ), merge(this.$inputItems, this._$filter)
1228
+ .pipe(filter(_ => this.searchable && this.enabled), map(_ => this.formControl.value)))
1228
1229
  .pipe(
1229
1230
  // Make sure there is enough characters
1230
1231
  filter(thresholdFilterFn),
1231
1232
  // Distinguish changes
1232
1233
  // - do NOT filter if loading, to force update after a blur event
1233
- distinctUntilChanged((v1, v2) => !this.loading && (v1 === v2 || this.equals(v1, v2)))))
1234
+ distinctUntilChanged((v1, v2) => !this.loading && (v1 === v2 || this.equals(v1, v2)))
1235
+ // DEBUG
1236
+ //,tap(value => this.debug && console.debug(this.logPrefix + ' Received update event: ', value))
1237
+ ))
1234
1238
  .pipe(
1235
1239
  // Suggest values
1236
1240
  mergeMap(value => this.suggest(value, this.filter)),
1237
1241
  // DEBUG
1238
- tap(items => this.debug && console.debug(this.logPrefix + ' Received from suggest: ', items)),
1242
+ //tap(items => this.debug && console.debug(this.logPrefix + ' Received from suggest: ', items)),
1239
1243
  // Store implicit value (will use it onBlur if not other value selected)
1240
1244
  tap(items => this.updateImplicitValue(items)));
1241
1245
  // Fetch more events
@@ -1268,9 +1272,10 @@ class MatAutocompleteField {
1268
1272
  this._subscription.add(this.blurred
1269
1273
  .pipe(
1270
1274
  // Skip if not searchable
1271
- filter(_ => this.searchable), map(_ => this.formControl.value),
1275
+ filter(_ => this.searchable), map(_ => this.formControl.value)
1272
1276
  // DEBUG
1273
- tap(value => console.debug(this.logPrefix + ' Received blurred event: ', value)))
1277
+ //,tap(value => this.debug && console.debug(this.logPrefix + ' Received blurred event: ', value)),
1278
+ )
1274
1279
  .subscribe(value => {
1275
1280
  // When leave component without object, use implicit value if :
1276
1281
  // - an explicit value
@@ -1356,7 +1361,7 @@ class MatAutocompleteField {
1356
1361
  }
1357
1362
  writeValue(value) {
1358
1363
  // DEBUG
1359
- // console.debug(this.logPrefix + ' Writing value: ', value);
1364
+ // if (this.debug) console.debug(this.logPrefix + ' Writing value: ', value);
1360
1365
  if (value !== this.formControl.value) {
1361
1366
  this.formControl.patchValue(value, { emitEvent: false });
1362
1367
  this._onChangeCallback(value);
@@ -1394,18 +1399,16 @@ class MatAutocompleteField {
1394
1399
  event.stopPropagation();
1395
1400
  event.returnValue = false;
1396
1401
  // DEBUG
1397
- if (this.debug)
1398
- console.debug(this.logPrefix + ' Cancelling focus event');
1402
+ //if (this.debug) console.debug(this.logPrefix + ' Cancelling focus event');
1399
1403
  return false;
1400
1404
  }
1401
- if (this.debug)
1402
- console.debug(this.logPrefix + ' Select input content');
1405
+ // DEBUG
1406
+ //if (this.debug) console.debug(this.logPrefix + ' Select input content');
1403
1407
  const hasContent = true; // selectInputContent(event);
1404
1408
  // If combo is empty, or if has content but should force to show panel on focus
1405
1409
  if (!hasContent || this.showPanelOnFocus || this.showAllOnFocus) {
1406
1410
  // DEBUG
1407
- if (this.debug)
1408
- console.debug(this.logPrefix + ' Emit focus event');
1411
+ //if (this.debug) console.debug(this.logPrefix + ' Emit focus event');
1409
1412
  this.focused.emit();
1410
1413
  return true;
1411
1414
  }
@@ -4502,7 +4505,7 @@ class MatDate {
4502
4505
  ngOnInit() {
4503
4506
  this.formControl = this.formControl || this.formControlName && this.formGroupDir && this.formGroupDir.form.get(this.formControlName);
4504
4507
  if (!this.formControl)
4505
- throw new Error('Missing mandatory attribute \'formControl\' or \'formControlName\' in <mat-date-time-field>.');
4508
+ throw new Error('Missing mandatory attribute \'formControl\' or \'formControlName\' in <mat-date-field>.');
4506
4509
  this.required = toBoolean(this.required, this.formControl.validator === Validators.required);
4507
4510
  // Redirect errors from main control, into day sub control
4508
4511
  const $error = new BehaviorSubject(null);
@@ -4599,44 +4602,6 @@ class MatDate {
4599
4602
  this.markForCheck();
4600
4603
  this._onChangeCallback(dateStr);
4601
4604
  }
4602
- updatePattern(pattern) {
4603
- pattern = pattern !== 'COMMON.DATE_PATTERN' ? pattern : 'L';
4604
- if (this.displayPattern !== pattern) {
4605
- this.displayPattern = pattern;
4606
- this.dayPattern = pattern;
4607
- this.markForCheck();
4608
- }
4609
- }
4610
- onFormChange(dayValue) {
4611
- if (this.writing)
4612
- return; // Skip if call by self
4613
- this.writing = true;
4614
- // Make to remove placeholder chars
4615
- while (dayValue && dayValue.indexOf(this.placeholderChar) !== -1) {
4616
- dayValue = dayValue.replace(this.placeholderChar, '');
4617
- }
4618
- let date;
4619
- // Parse day string
4620
- date = dayValue && this.dateAdapter.parse(dayValue, this.dayPattern) || null;
4621
- // Reset time
4622
- date = date && date.utc(true).hour(0).minute(0).seconds(0).millisecond(0);
4623
- // update date picker
4624
- this._value = date && this.dateAdapter.parse(date.clone(), DATE_ISO_PATTERN);
4625
- // Get the model value
4626
- const dateStr = date && date.isValid() && this.dateAdapter.format(date, DATE_ISO_PATTERN).replace('+00:00', 'Z') || date;
4627
- //console.debug("[mat-date-time] Setting date: ", dateStr);
4628
- this.formControl.patchValue(dateStr, { emitEvent: false });
4629
- //this.formControl.updateValueAndValidity();
4630
- this.writing = false;
4631
- this.markForCheck();
4632
- this._onChangeCallback(dateStr);
4633
- }
4634
- checkIfTouched() {
4635
- if (this.dayControl.touched) {
4636
- this.markForCheck();
4637
- this._onTouchedCallback();
4638
- }
4639
- }
4640
4605
  openDatePickerIfMobile(event, datePicker) {
4641
4606
  return __awaiter(this, void 0, void 0, function* () {
4642
4607
  if (!this.mobile || event.defaultPrevented)
@@ -4676,7 +4641,45 @@ class MatDate {
4676
4641
  }
4677
4642
  });
4678
4643
  }
4679
- /* -- protected method -- */
4644
+ /* -- private method -- */
4645
+ updatePattern(pattern) {
4646
+ pattern = pattern !== 'COMMON.DATE_PATTERN' ? pattern : 'L';
4647
+ if (this.displayPattern !== pattern) {
4648
+ this.displayPattern = pattern;
4649
+ this.dayPattern = pattern;
4650
+ this.markForCheck();
4651
+ }
4652
+ }
4653
+ onFormChange(dayValue) {
4654
+ if (this.writing)
4655
+ return; // Skip if call by self
4656
+ this.writing = true;
4657
+ // Make to remove placeholder chars
4658
+ while (dayValue && dayValue.indexOf(this.placeholderChar) !== -1) {
4659
+ dayValue = dayValue.replace(this.placeholderChar, '');
4660
+ }
4661
+ let date;
4662
+ // Parse day string
4663
+ date = dayValue && this.dateAdapter.parse(dayValue, this.dayPattern) || null;
4664
+ // Reset time
4665
+ date = date && date.utc(true).hour(0).minute(0).seconds(0).millisecond(0);
4666
+ // update date picker
4667
+ this._value = date && this.dateAdapter.parse(date.clone(), DATE_ISO_PATTERN);
4668
+ // Get the model value
4669
+ const dateStr = date && date.isValid() && this.dateAdapter.format(date, DATE_ISO_PATTERN).replace('+00:00', 'Z') || date;
4670
+ //console.debug("[mat-date-time] Setting date: ", dateStr);
4671
+ this.formControl.patchValue(dateStr, { emitEvent: false });
4672
+ //this.formControl.updateValueAndValidity();
4673
+ this.writing = false;
4674
+ this.markForCheck();
4675
+ this._onChangeCallback(dateStr);
4676
+ }
4677
+ checkIfTouched() {
4678
+ if (this.dayControl.touched) {
4679
+ this.markForCheck();
4680
+ this._onTouchedCallback();
4681
+ }
4682
+ }
4680
4683
  waitKeyboardHide(waitKeyboardDelay) {
4681
4684
  return __awaiter(this, void 0, void 0, function* () {
4682
4685
  if (!this.keyboard || !this.keyboard.isVisible)
@@ -4756,13 +4759,13 @@ const noop$5 = () => {
4756
4759
  };
4757
4760
  const ɵ0$8 = noop$5;
4758
4761
  class MatDateTime {
4759
- constructor(platform, dateAdapter, translate, formBuilder, keyboard, cd, formGroupDir) {
4762
+ constructor(platform, dateAdapter, translate, formBuilder, cd, keyboard, formGroupDir) {
4760
4763
  this.platform = platform;
4761
4764
  this.dateAdapter = dateAdapter;
4762
4765
  this.translate = translate;
4763
4766
  this.formBuilder = formBuilder;
4764
- this.keyboard = keyboard;
4765
4767
  this.cd = cd;
4768
+ this.keyboard = keyboard;
4766
4769
  this.formGroupDir = formGroupDir;
4767
4770
  this._onChangeCallback = noop$5;
4768
4771
  this._onTouchedCallback = noop$5;
@@ -4801,7 +4804,7 @@ class MatDateTime {
4801
4804
  }
4802
4805
  ngOnInit() {
4803
4806
  this.mobile = isNil(this.mobile) ? this.platform.is('mobile') : this.mobile;
4804
- this.waitHideKeyboardDelay = this.mobile && KEYBOARD_HIDE_DELAY_MS || 0;
4807
+ this.keyboardHideDelay = this.mobile && KEYBOARD_HIDE_DELAY_MS || 0;
4805
4808
  this.formControl = this.formControl || this.formControlName && this.formGroupDir && this.formGroupDir.form.get(this.formControlName);
4806
4809
  if (!this.formControl)
4807
4810
  throw new Error('Missing mandatory attribute \'formControl\' or \'formControlName\' in <mat-date-time-field>.');
@@ -4925,10 +4928,6 @@ class MatDateTime {
4925
4928
  this.disabling = false;
4926
4929
  this.markForCheck();
4927
4930
  }
4928
- updatePattern(patterns) {
4929
- this.displayPattern = (patterns['COMMON.DATE_TIME_PATTERN'] !== 'COMMON.DATE_TIME_PATTERN' ? patterns['COMMON.DATE_TIME_PATTERN'] : 'L LT');
4930
- this.dayPattern = (patterns['COMMON.DATE_PATTERN'] !== 'COMMON.DATE_PATTERN' ? patterns['COMMON.DATE_PATTERN'] : 'L');
4931
- }
4932
4931
  onDatePickerChange(event) {
4933
4932
  // Make sure event is valid
4934
4933
  if (!event || (event.value !== null && !isMoment(event.value))) {
@@ -4966,7 +4965,7 @@ class MatDateTime {
4966
4965
  return;
4967
4966
  this.preventEvent(event);
4968
4967
  // Make sure the keyboard is closed
4969
- yield this.hideKeyboard(false);
4968
+ yield this.waitKeyboardHide(false);
4970
4969
  // Open the picker
4971
4970
  this.openDatePicker(null, datePicker);
4972
4971
  });
@@ -4987,7 +4986,7 @@ class MatDateTime {
4987
4986
  return;
4988
4987
  this.preventEvent(event);
4989
4988
  // Make sure the keyboard is closed
4990
- yield this.hideKeyboard(true);
4989
+ yield this.waitKeyboardHide(true);
4991
4990
  // Open the picker
4992
4991
  this.openTimePicker(null);
4993
4992
  });
@@ -5006,12 +5005,6 @@ class MatDateTime {
5006
5005
  event.stopPropagation();
5007
5006
  event.returnValue = false;
5008
5007
  }
5009
- checkIfTouched() {
5010
- if (this.dateFormControl.touched || this.timeFormControl.touched) {
5011
- this._onTouchedCallback();
5012
- this.markForCheck();
5013
- }
5014
- }
5015
5008
  focus() {
5016
5009
  if (!this.matInputs.length)
5017
5010
  return;
@@ -5027,7 +5020,31 @@ class MatDateTime {
5027
5020
  this.markAsTouched();
5028
5021
  this.markAsDirty();
5029
5022
  }
5030
- /* -- protected method -- */
5023
+ /* -- private method -- */
5024
+ updatePattern(patterns) {
5025
+ this.displayPattern = (patterns['COMMON.DATE_TIME_PATTERN'] !== 'COMMON.DATE_TIME_PATTERN' ? patterns['COMMON.DATE_TIME_PATTERN'] : 'L LT');
5026
+ this.dayPattern = (patterns['COMMON.DATE_PATTERN'] !== 'COMMON.DATE_PATTERN' ? patterns['COMMON.DATE_PATTERN'] : 'L');
5027
+ }
5028
+ checkIfTouched() {
5029
+ if (this.dateFormControl.touched || this.timeFormControl.touched) {
5030
+ this._onTouchedCallback();
5031
+ this.markForCheck();
5032
+ }
5033
+ }
5034
+ waitKeyboardHide(waitKeyboardDelay) {
5035
+ return __awaiter(this, void 0, void 0, function* () {
5036
+ if (!this.keyboard || !this.keyboard.isVisible)
5037
+ return; // ok, already hidden (or not accessible)
5038
+ // Force keyboard to be hide
5039
+ this.keyboard.hide();
5040
+ // Wait hide occur
5041
+ yield this.keyboard.onKeyboardHide().pipe(first()).toPromise();
5042
+ // Wait an additional delay if need (depending on the OS)
5043
+ if (this.keyboardHideDelay > 0 && waitKeyboardDelay) {
5044
+ yield sleep(this.keyboardHideDelay);
5045
+ }
5046
+ });
5047
+ }
5031
5048
  emitChange(value) {
5032
5049
  // Get the model value
5033
5050
  const dateStr = toDateISOString(value) || null;
@@ -5040,20 +5057,6 @@ class MatDateTime {
5040
5057
  this.checkIfTouched();
5041
5058
  }
5042
5059
  }
5043
- hideKeyboard(waitIsHidden) {
5044
- return __awaiter(this, void 0, void 0, function* () {
5045
- if (!this.keyboard.isVisible)
5046
- return; // ok, already hidden
5047
- // Force keyboard to be hide
5048
- this.keyboard.hide();
5049
- // Wait hide occur
5050
- yield this.keyboard.onKeyboardHide().pipe(first()).toPromise();
5051
- // Wait an additional delay if need (depending on the OS)
5052
- if (this.waitHideKeyboardDelay > 0 && waitIsHidden) {
5053
- yield sleep(this.waitHideKeyboardDelay);
5054
- }
5055
- });
5056
- }
5057
5060
  updateTabIndex() {
5058
5061
  if (isNil(this._tabindex) || this._tabindex === -1)
5059
5062
  return; // skip
@@ -5094,8 +5097,8 @@ MatDateTime.ctorParameters = () => [
5094
5097
  { type: DateAdapter },
5095
5098
  { type: TranslateService },
5096
5099
  { type: FormBuilder },
5097
- { type: Keyboard },
5098
5100
  { type: ChangeDetectorRef },
5101
+ { type: Keyboard, decorators: [{ type: Optional }] },
5099
5102
  { type: FormGroupDirective, decorators: [{ type: Optional }] }
5100
5103
  ];
5101
5104
  MatDateTime.propDecorators = {
@@ -5165,7 +5168,7 @@ class MatDateShort {
5165
5168
  ngOnInit() {
5166
5169
  this.formControl = this.formControl || this.formControlName && this.formGroupDir && this.formGroupDir.form.get(this.formControlName);
5167
5170
  if (!this.formControl)
5168
- throw new Error('Missing mandatory attribute \'formControl\' or \'formControlName\' in <mat-date-time-field>.');
5171
+ throw new Error('Missing mandatory attribute \'formControl\' or \'formControlName\' in <mat-date-short-field>.');
5169
5172
  // Redirect errors from main control, into day sub control
5170
5173
  const $error = new BehaviorSubject(null);
5171
5174
  this.required = toBoolean(this.required, this.formControl.validator === Validators.required);
@@ -5507,7 +5510,7 @@ class MatDuration {
5507
5510
  }
5508
5511
  this.formControl = this.formControl || this.formControlName && this.formGroupDir && this.formGroupDir.form.get(this.formControlName);
5509
5512
  if (!this.formControl)
5510
- throw new Error('Missing mandatory attribute \'formControl\' or \'formControlName\' in <mat-date-time-field>.');
5513
+ throw new Error('Missing mandatory attribute \'formControl\' or \'formControlName\' in <mat-duration-field>.');
5511
5514
  this.required = toBoolean(this.required, this.formControl.validator === Validators.required);
5512
5515
  // Redirect errors from main control, into day sub control
5513
5516
  const $error = new BehaviorSubject(null);
@@ -5886,7 +5889,7 @@ class MatBooleanField {
5886
5889
  MatBooleanField.decorators = [
5887
5890
  { type: Component, args: [{
5888
5891
  selector: 'mat-boolean-field',
5889
- template: "<mat-form-field *ngIf=\"readonly; else writable\"\n [floatLabel]=\"floatLabel\"\n class=\"mat-form-field-disabled {{classList}}\">\n <div matPrefix>\n <ng-container *ngTemplateOutlet=\"matPrefixTemplate\"></ng-container>\n </div>\n <input matInput hidden type=\"text\" readonly\n [placeholder]=\"placeholder\"\n [formControl]=\"formControl\">\n <ion-text>{{(formControl.value == null && 'COMMON.EMPTY_OPTION' || (formControl.value === true && yesLabel) || noLabel) | translate }}</ion-text>\n <div matSuffix>\n <ng-container *ngTemplateOutlet=\"matSuffixTemplate\"></ng-container>\n </div>\n</mat-form-field>\n\n<ng-template #writable>\n <ng-container [ngSwitch]=\"style\">\n\n <!-- Radio -->\n <mat-form-field *ngSwitchCase=\"'radio'\"\n [floatLabel]=\"showRadio && (!floatLabel || floatLabel === 'auto') ? 'always': floatLabel\"\n class=\"mat-boolean-field mat-boolean-field-radio {{classList}}\">\n <mat-label *ngIf=\"placeholder && floatLabel!=='never'\">\n {{placeholder}}\n <span [hidden]=\"showRadio\">({{yesLabel|translate}}/{{'COMMON.NO'|translate}})</span>\n </mat-label>\n <div matPrefix>\n <ng-container *ngTemplateOutlet=\"matPrefixTemplate\"></ng-container>\n </div>\n <input matInput #fakeInput type=\"text\" readonly=\"true\"\n [formControl]=\"formControl\"\n (focus)=\"_onFocusFakeInput($event)\"\n [required]=\"required\"\n [class.cdk-visually-hidden]=\"showRadio\"\n [tabindex]=\"tabindex\">\n\n <!-- radio button -->\n <mat-radio-group [hidden]=\"!showRadio\"\n [formControl]=\"formControl\"\n (change)=\"onRadioValueChanged($event)\">\n <mat-radio-button #yesButton [value]=\"true\">\n <span>{{yesLabel|translate}}</span>\n </mat-radio-button>&nbsp;\n <mat-radio-button #noButton [value]=\"false\">\n <span>{{noLabel|translate}}</span>\n </mat-radio-button>\n </mat-radio-group>\n\n <mat-error *ngIf=\"formControl.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n\n <div matSuffix>\n <ng-container *ngTemplateOutlet=\"matSuffixTemplate\"></ng-container>\n </div>\n </mat-form-field>\n\n <!-- Checkbox -->\n <mat-form-field *ngSwitchCase=\"'checkbox'\"\n [floatLabel]=\"floatLabel\"\n class=\"mat-boolean-field mat-boolean-field-checkbox {{classList}}\">\n <mat-label *ngIf=\"placeholder && !showRadio\">\n {{placeholder}}\n </mat-label>\n <div matPrefix>\n <ng-container *ngTemplateOutlet=\"matPrefixTemplate\"></ng-container>\n </div>\n <input matInput #matInput\n [formControl]=\"formControl\"\n (focus)=\"_onFocusFakeInput($event)\"\n [required]=\"required\"\n [class.cdk-visually-hidden]=\"showRadio\"\n [tabindex]=\"tabindex\">\n\n <ion-label>&nbsp;</ion-label>\n\n <!-- checkbox, when compact -->\n <mat-checkbox #checkboxButton\n [formControl]=\"formControl\"\n (change)=\"onCheckboxValueChanged($event)\"\n [indeterminate]=\"value===undefined\"\n [hidden]=\"!showRadio\"\n [tabindex]=\"tabindex\">\n </mat-checkbox>\n\n <mat-error *ngIf=\"formControl.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n\n <div matSuffix>\n <ng-container *ngTemplateOutlet=\"matSuffixTemplate\"></ng-container>\n </div>\n </mat-form-field>\n\n <!-- Buttons -->\n <mat-form-field *ngSwitchCase=\"'button'\"\n [floatLabel]=\"floatLabel === 'never' ? 'never' : 'always'\"\n class=\"mat-boolean-field mat-boolean-field-button {{classList}}\">\n <div matPrefix>\n <ng-container *ngTemplateOutlet=\"matPrefixTemplate\"></ng-container>\n </div>\n <input matInput type=\"text\" hidden\n [formControl]=\"formControl\"\n [placeholder]=\"placeholder\"\n [required]=\"required\">\n <div class=\"mat-form-field-buttons\"\n [style.--buttons-col-count]=\"buttonsColCount\"\n *ngIf=\"!formControl.disabled; else disabledLabel\">\n <!-- yes -->\n <ion-button class=\"mat-form-field-button\"\n [tabindex]=\"_tabindex\"\n (click)=\"writeValue(true, $event)\"\n (keyup.enter)=\"writeValue(true, $event)\"\n [color]=\"_value == null ? 'tertiary' : (_value === true) ? 'accent' : 'light'\">\n <ion-icon *ngIf=\"showButtonIcons && yesIcon; let icon\" slot=\"start\" [name]=\"icon\"></ion-icon>\n {{yesLabel|translate}}\n </ion-button>\n\n <!-- No button -->\n <ion-button class=\"mat-form-field-button\"\n [tabindex]=\"_tabindex !== undefined ? (_tabindex + 1) : undefined\"\n (click)=\"writeValue(false, $event)\"\n (keyup.enter)=\"writeValue(false, $event)\"\n [color]=\"_value == null ? 'tertiary' : (_value === false) ? 'accent' : 'light'\">\n <ion-icon *ngIf=\"showButtonIcons && noIcon; let icon\" slot=\"start\" [name]=\"icon\"></ion-icon>\n {{noLabel|translate}}\n </ion-button>\n </div>\n <ng-template #disabledLabel>\n <ion-label><i translate>COMMON.EMPTY_OPTION</i></ion-label>\n </ng-template>\n\n <mat-error *ngIf=\"formControl.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <div matSuffix>\n <ng-container *ngTemplateOutlet=\"matSuffixTemplate\"></ng-container>\n </div>\n\n </mat-form-field>\n </ng-container>\n\n <div class=\"cdk-visually-hidden\">\n <div #suffix><ng-content select=\"[matSuffix]\"></ng-content></div>\n </div>\n\n</ng-template>\n\n\n<ng-template #matPrefixTemplate>\n <ng-content select=\"[matPrefix]\"></ng-content>\n</ng-template>\n<ng-template #matSuffixTemplate>\n <ng-content select=\"[matSuffix]\"></ng-content>\n</ng-template>\n",
5892
+ template: "<mat-form-field *ngIf=\"readonly; else writable\"\n [floatLabel]=\"floatLabel\"\n class=\"mat-form-field-disabled {{classList}}\">\n <div matPrefix>\n <ng-container *ngTemplateOutlet=\"matPrefixTemplate\"></ng-container>\n </div>\n <input matInput hidden type=\"text\" readonly\n [placeholder]=\"placeholder\"\n [formControl]=\"formControl\">\n <ion-text>{{(formControl.value == null && 'COMMON.EMPTY_OPTION' || (formControl.value === true && yesLabel) || noLabel) | translate }}</ion-text>\n <div matSuffix>\n <ng-container *ngTemplateOutlet=\"matSuffixTemplate\"></ng-container>\n </div>\n</mat-form-field>\n\n<ng-template #writable>\n <ng-container [ngSwitch]=\"style\">\n\n <!-- Radio -->\n <mat-form-field *ngSwitchCase=\"'radio'\"\n [floatLabel]=\"showRadio && (!floatLabel || floatLabel === 'auto') ? 'always': floatLabel\"\n class=\"mat-boolean-field mat-boolean-field-radio {{classList}}\">\n <mat-label *ngIf=\"placeholder && floatLabel!=='never'\">\n {{placeholder}}\n <span [hidden]=\"showRadio\">({{yesLabel|translate}}/{{'COMMON.NO'|translate}})</span>\n </mat-label>\n <div matPrefix>\n <ng-container *ngTemplateOutlet=\"matPrefixTemplate\"></ng-container>\n </div>\n <input matInput #fakeInput type=\"text\" readonly=\"true\"\n [formControl]=\"formControl\"\n (focus)=\"_onFocusFakeInput($event)\"\n [required]=\"required\"\n [class.cdk-visually-hidden]=\"showRadio\"\n [tabindex]=\"tabindex\">\n\n <!-- radio button -->\n <mat-radio-group [hidden]=\"!showRadio\"\n [formControl]=\"formControl\"\n (change)=\"onRadioValueChanged($event)\">\n <mat-radio-button #yesButton [value]=\"true\">\n <span>{{yesLabel|translate}}</span>\n </mat-radio-button>&nbsp;\n <mat-radio-button #noButton [value]=\"false\">\n <span>{{noLabel|translate}}</span>\n </mat-radio-button>\n </mat-radio-group>\n\n <mat-error *ngIf=\"formControl.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n\n <div matSuffix>\n <ng-container *ngTemplateOutlet=\"matSuffixTemplate\"></ng-container>\n </div>\n </mat-form-field>\n\n <!-- Checkbox -->\n <mat-form-field *ngSwitchCase=\"'checkbox'\"\n [floatLabel]=\"floatLabel\"\n class=\"mat-boolean-field mat-boolean-field-checkbox {{classList}}\">\n <mat-label *ngIf=\"placeholder && !showRadio\">\n {{placeholder}}\n </mat-label>\n <div matPrefix>\n <ng-container *ngTemplateOutlet=\"matPrefixTemplate\"></ng-container>\n </div>\n <input matInput #matInput\n [formControl]=\"formControl\"\n (focus)=\"_onFocusFakeInput($event)\"\n [required]=\"required\"\n [class.cdk-visually-hidden]=\"showRadio\"\n [tabindex]=\"tabindex\">\n\n <ion-label>&nbsp;</ion-label>\n\n <!-- checkbox, when compact -->\n <mat-checkbox #checkboxButton\n [formControl]=\"formControl\"\n (change)=\"onCheckboxValueChanged($event)\"\n [indeterminate]=\"value===undefined\"\n [hidden]=\"!showRadio\"\n [tabindex]=\"tabindex\">\n </mat-checkbox>\n\n <mat-error *ngIf=\"formControl.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n\n <div matSuffix>\n <ng-container *ngTemplateOutlet=\"matSuffixTemplate\"></ng-container>\n </div>\n </mat-form-field>\n\n <!-- Buttons -->\n <mat-form-field *ngSwitchCase=\"'button'\"\n [floatLabel]=\"floatLabel === 'never' ? 'never' : 'always'\"\n class=\"mat-boolean-field mat-boolean-field-button {{classList}}\">\n <div matPrefix>\n <ng-container *ngTemplateOutlet=\"matPrefixTemplate\"></ng-container>\n </div>\n <input matInput type=\"text\" hidden\n [formControl]=\"formControl\"\n [placeholder]=\"placeholder\"\n [required]=\"required\">\n <div class=\"mat-form-field-buttons\"\n [style.--buttons-col-count]=\"buttonsColCount\"\n *ngIf=\"!formControl.disabled; else disabledLabel\">\n <!-- yes -->\n <ion-button class=\"mat-form-field-button\"\n [tabindex]=\"_tabindex\"\n (click)=\"writeValue(true, $event)\"\n (keyup.enter)=\"writeValue(true, $event)\"\n [color]=\"_value == null ? 'tertiary' : (_value === true) ? 'accent' : 'light'\">\n <ion-icon *ngIf=\"showButtonIcons && yesIcon; let icon\" slot=\"start\" [name]=\"icon\"></ion-icon>\n {{yesLabel|translate}}\n </ion-button>\n\n <!-- No button -->\n <ion-button class=\"mat-form-field-button\"\n [tabindex]=\"_tabindex !== undefined ? (_tabindex + 1) : undefined\"\n (click)=\"writeValue(false, $event)\"\n (keyup.enter)=\"writeValue(false, $event)\"\n [color]=\"_value == null ? 'tertiary' : (_value === false) ? 'accent' : 'light'\">\n <ion-icon *ngIf=\"showButtonIcons && noIcon; let icon\" slot=\"start\" [name]=\"icon\"></ion-icon>\n {{noLabel|translate}}\n </ion-button>\n </div>\n <ng-template #disabledLabel>\n <ion-label><i translate>COMMON.EMPTY_OPTION</i></ion-label>\n </ng-template>\n\n <mat-error *ngIf=\"formControl.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <div matSuffix>\n <ng-container *ngTemplateOutlet=\"matSuffixTemplate\"></ng-container>\n </div>\n\n </mat-form-field>\n </ng-container>\n\n</ng-template>\n\n\n<ng-template #matPrefixTemplate>\n <ng-content select=\"[matPrefix]\"></ng-content>\n</ng-template>\n<ng-template #matSuffixTemplate>\n <ng-content select=\"[matSuffix]\"></ng-content>\n</ng-template>\n",
5890
5893
  providers: [
5891
5894
  DEFAULT_VALUE_ACCESSOR$1
5892
5895
  ],
@@ -5924,8 +5927,7 @@ MatBooleanField.propDecorators = {
5924
5927
  yesButton: [{ type: ViewChild, args: ['yesButton',] }],
5925
5928
  noButton: [{ type: ViewChild, args: ['noButton',] }],
5926
5929
  checkboxButton: [{ type: ViewChild, args: ['checkboxButton',] }],
5927
- fakeInput: [{ type: ViewChild, args: ['fakeInput',] }],
5928
- suffixDiv: [{ type: ViewChild, args: ['suffix', { static: false },] }]
5930
+ fakeInput: [{ type: ViewChild, args: ['fakeInput',] }]
5929
5931
  };
5930
5932
 
5931
5933
  class SharedMatBooleanModule {
@@ -7004,7 +7006,7 @@ class MatChipsField {
7004
7006
  // Wait a debounce time
7005
7007
  debounceTime(this.debounceTime)
7006
7008
  // DEBUG
7007
- //tap((value) => console.debug(this.logPrefix + ' Search text changes:', value))
7009
+ //,tap((value) => this.debug && console.debug(this.logPrefix + ' Search text changes:', value))
7008
7010
  ),
7009
7011
  // Object set: use it (no distinctUntilChanged() pipe need)
7010
7012
  this.inputControl.valueChanges
@@ -7020,18 +7022,25 @@ class MatChipsField {
7020
7022
  merge(
7021
7023
  // Focus or click => Load all
7022
7024
  merge(this.focused, this.clicked)
7023
- .pipe(filter(_ => this.enabled), map((_) => this.showAllOnFocus ? '*' : this.inputControl.value)), merge(this.$inputItems, this._$filter)
7025
+ .pipe(filter(_ => this.enabled), map((_) => this.showAllOnFocus ? '*' : this.inputControl.value)
7026
+ // DEBUG
7027
+ //,tap(value => this.debug && console.debug(this.logPrefix + ' Received focused or clicked event: ', value))
7028
+ ), merge(this.$inputItems, this._$filter)
7024
7029
  .pipe(filter(_ => this.enabled), map(_ => this.inputControl.value)))
7025
7030
  .pipe(
7026
7031
  // Make sure there is enough characters
7027
7032
  filter(thresholdFilterFn),
7028
7033
  // Distinguish changes
7029
- distinctUntilChanged()))
7034
+ // - do NOT filter if loading, to force update after a blur event
7035
+ distinctUntilChanged((v1, v2) => !this.loading && (v1 === v2 || this.equals(v1, v2)))
7036
+ // DEBUG
7037
+ //,tap(value => this.debug && console.debug(this.logPrefix + ' Received update event: ', value))
7038
+ ))
7030
7039
  .pipe(
7031
7040
  // Suggest values
7032
7041
  mergeMap(value => this.suggest(value, this.filter)),
7033
7042
  // DEBUG
7034
- //tap(items => console.debug(this.logPrefix + ' Received from suggest: ', items)),
7043
+ //tap(items => this.debug && console.debug(this.logPrefix + ' Received from suggest: ', items)),
7035
7044
  // Store implicit value (will use it onBlur if not other value selected)
7036
7045
  tap(items => this.updateImplicitValue(items)));
7037
7046
  // Fetch more events
@@ -7052,7 +7061,10 @@ class MatChipsField {
7052
7061
  .subscribe(items => this.$filteredItems.next(items)));
7053
7062
  // Applying implicit value, on blur
7054
7063
  this._subscription.add(this.blurred
7055
- .pipe(map(_ => this.formControl.value))
7064
+ .pipe(map(_ => this.formControl.value)
7065
+ // DEBUG
7066
+ //,tap(value => this.debug && console.debug(this.logPrefix + ' Received blurred event: ', value)),
7067
+ )
7056
7068
  .subscribe(value => {
7057
7069
  // When leave component without object, use implicit value if :
7058
7070
  // - an explicit value
@@ -7164,6 +7176,8 @@ class MatChipsField {
7164
7176
  this._reload$.next(value || '*');
7165
7177
  }
7166
7178
  writeValue(value) {
7179
+ // DEBUG
7180
+ // if (this.debug) console.debug(this.logPrefix + ' Writing value: ', value);
7167
7181
  if (value && !Array.isArray(value)) {
7168
7182
  value = [value];
7169
7183
  }
@@ -7415,9 +7429,9 @@ MatChipsField.propDecorators = {
7415
7429
  showLoadingSpinner: [{ type: Input }],
7416
7430
  chipColor: [{ type: Input }],
7417
7431
  debug: [{ type: Input }],
7418
- clicked: [{ type: Output }],
7419
- blurred: [{ type: Output }],
7420
- focused: [{ type: Output }],
7432
+ clicked: [{ type: Output, args: ['click',] }],
7433
+ blurred: [{ type: Output, args: ['blur',] }],
7434
+ focused: [{ type: Output, args: ['focus',] }],
7421
7435
  dropButtonClick: [{ type: Output }],
7422
7436
  keydownEscape: [{ type: Output, args: ['keydown.escape',] }],
7423
7437
  keyupEnter: [{ type: Output, args: ['keyup.enter',] }],
@@ -8135,7 +8149,7 @@ class AppFormField {
8135
8149
  AppFormField.decorators = [
8136
8150
  { type: Component, args: [{
8137
8151
  selector: 'app-form-field',
8138
- template: "<ng-container [ngSwitch]=\"type\">\n\n <!-- integer -->\n <mat-form-field *ngSwitchCase=\"'integer'\" [floatLabel]=\"floatLabel\" [class]=\"classList\">\n <input matInput #matInput\n type=\"number\"\n autocomplete=\"off\"\n [readonly]=\"readonly\"\n [min]=\"definition.minValue\"\n [max]=\"definition.maxValue\"\n pattern=\"-?[0-9]*\"\n step=\"1\"\n [appAutofocus]=\"autofocus\"\n [placeholder]=\"placeholder\"\n (keyup.enter)=\"onKeyupEnter.emit($event)\"\n (keypress)=\"filterNumberInput($event, false)\"\n [formControl]=\"formControl\"\n [required]=\"required\"\n [tabIndex]=\"tabindex\"\n (click)=\"selectInputContent($event)\">\n <mat-error *ngIf=\"formControl.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"formControl.hasError('min')\">\n {{(compact ? 'ERROR.FIELD_MIN_COMPACT' : 'ERROR.FIELD_MIN') | translate:formControl.errors['min'] }}</mat-error>\n <mat-error *ngIf=\"formControl.hasError('max')\">\n {{(compact ? 'ERROR.FIELD_MAX_COMPACT' : 'ERROR.FIELD_MAX') | translate:formControl.errors['max'] }}</mat-error>\n <mat-error *ngIf=\"formControl.hasError('pattern')\">\n {{'ERROR.FIELD_NOT_VALID_INTEGER'| translate }}</mat-error>\n <mat-error *ngIf=\"formControl.hasError('integer')\">\n {{'ERROR.FIELD_NOT_VALID_INTEGER'| translate }}</mat-error>\n\n <div matSuffix>\n <ng-content select=\"[matSuffix]\"></ng-content>\n </div>\n </mat-form-field>\n\n <!-- double -->\n <mat-form-field *ngSwitchCase=\"'double'\" [floatLabel]=\"floatLabel\" [class]=\"classList\">\n\n <input matInput #matInput\n type=\"number\"\n decimal=\"true\"\n autocomplete=\"off\"\n [min]=\"definition.minValue\"\n [max]=\"definition.maxValue\"\n [appAutofocus]=\"autofocus\"\n [readonly]=\"readonly\"\n [placeholder]=\"placeholder\"\n [step]=\"numberInputStep\"\n (keypress)=\"filterNumberInput($event, true)\"\n [formControl]=\"formControl\"\n [required]=\"required\"\n [tabIndex]=\"tabindex\"\n (click)=\"selectInputContent($event)\">\n <mat-error *ngIf=\"formControl.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"formControl.hasError('min')\">\n {{ (compact ? 'ERROR.FIELD_MIN_COMPACT' : 'ERROR.FIELD_MIN')| translate:formControl.errors['min'] }}</mat-error>\n <mat-error *ngIf=\"formControl.hasError('max')\">\n {{(compact ? 'ERROR.FIELD_MAX_COMPACT' : 'ERROR.FIELD_MAX') | translate:formControl.errors['max'] }}</mat-error>\n <mat-error *ngIf=\"formControl.hasError('maxDecimals')\">\n {{ (compact ? 'ERROR.FIELD_MAXIMUM_DECIMALS_COMPACT' : 'ERROR.FIELD_MAXIMUM_DECIMALS')| translate:{max:\n definition.maximumNumberDecimals} }}</mat-error>\n <div matSuffix>\n <ng-content select=\"[matSuffix]\"></ng-content>\n </div>\n </mat-form-field>\n\n <!-- boolean -->\n <mat-boolean-field *ngSwitchCase=\"'boolean'\" #matInput\n [class]=\"classList\"\n [formControl]=\"formControl\"\n [placeholder]=\"placeholder\"\n [floatLabel]=\"floatLabel\"\n [required]=\"required\"\n [compact]=\"compact\"\n [tabindex]=\"tabindex\"\n [readonly]=\"readonly\">\n <div matSuffix>\n <ng-content select=\"[matSuffix]\"></ng-content>\n </div>\n </mat-boolean-field>\n\n <!-- date -->\n <mat-date-field *ngSwitchCase=\"'date'\" #matInput\n [class]=\"classList\"\n [formControl]=\"formControl\"\n [placeholder]=\"compact ? ('COMMON.DATE_PLACEHOLDER'|translate): placeholder\"\n [floatLabel]=\"floatLabel\"\n [required]=\"required\"\n [readonly]=\"readonly\"\n [compact]=\"compact\"\n [tabindex]=\"tabindex\"\n [autofocus]=\"autofocus\">\n <div matSuffix>\n <ng-content select=\"[matSuffix]\"></ng-content>\n </div>\n </mat-date-field>\n\n <!-- date time -->\n <mat-date-time-field *ngSwitchCase=\"'dateTime'\"\n [class]=\"classList\"\n [formControl]=\"formControl\"\n [placeholder]=\"compact ? ('COMMON.DATE_TIME_PLACEHOLDER'|translate): placeholder\"\n [floatLabel]=\"floatLabel\"\n [required]=\"required\"\n [readonly]=\"readonly\"\n [compact]=\"compact\"\n [tabindex]=\"tabindex\"\n [autofocus]=\"autofocus\">\n <div matSuffix>\n <ng-content select=\"[matSuffix]\"></ng-content>\n </div>\n </mat-date-time-field>\n\n <!-- enum -->\n <mat-form-field *ngSwitchCase=\"'enum'\" [floatLabel]=\"floatLabel\" [class]=\"classList\">\n <mat-select [formControl]=\"formControl\"\n [placeholder]=\"placeholder\"\n [required]=\"required\"\n [tabindex]=\"tabindex\"\n (keyup.enter)=\"onKeyupEnter.emit($event)\">\n <mat-option *ngFor=\"let item of definition.values\" [value]=\"item.key || item\">{{ (item.value || item) | translate }}</mat-option>\n </mat-select>\n\n <mat-error *ngIf=\"formControl.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n\n <div matSuffix>\n <ng-content select=\"[matSuffix]\"></ng-content>\n </div>\n </mat-form-field>\n\n <!-- color -->\n <mat-form-field *ngSwitchCase=\"'color'\" [floatLabel]=\"floatLabel\" [class]=\"classList\">\n\n <ion-icon margin-right name=\"color-fill\" matPrefix></ion-icon>\n\n <input matInput autocomplete=\"off\"\n [appAutofocus]=\"autofocus\"\n [formControl]=\"formControl\"\n [style.color]=\"getColorContrast(formControl.value)\"\n [style.background]=\"formControl.value\"\n [colorPicker]=\"formControl.value\"\n (colorPickerChange)=\"writeValue($event)\"\n [cpSaveClickOutside]=\"true\"\n cpPosition=\"top\"\n cpOutputFormat=\"hex\"\n [cpOKButton]=\"false\"\n [required]=\"required\"/>\n <mat-error *ngIf=\"formControl.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n </mat-form-field>\n\n <!-- string -->\n <mat-form-field *ngSwitchCase=\"'string'\" [floatLabel]=\"floatLabel\" [class]=\"classList\">\n <input matInput #matInput\n autocomplete=\"off\"\n [appAutofocus]=\"autofocus\"\n [formControl]=\"formControl\"\n [placeholder]=\"placeholder\"\n [required]=\"required\"\n [readonly]=\"readonly\"\n [tabIndex]=\"tabindex\"\n (click)=\"selectInputContent($event)\"\n (keypress)=\"filterAlphanumericalInput($event)\"\n (keyup.enter)=\"onKeyupEnter.emit($event)\">\n <mat-error *ngIf=\"formControl.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <div matSuffix>\n <ng-content select=\"[matSuffix]\"></ng-content>\n </div>\n </mat-form-field>\n\n <!-- auto-complete -->\n <mat-autocomplete-field *ngSwitchCase=\"'entity'\"\n [class]=\"classList\"\n [autofocus]=\"autofocus\"\n [placeholder]=\"placeholder\"\n [floatLabel]=\"floatLabel\"\n [formControl]=\"formControl\"\n [config]=\"definition.autocomplete\"\n [required]=\"required\"\n [displayWith]=\"getDisplayValueFn(definition)\">\n <ng-content select=\"[matPrefix]\"></ng-content>\n <ng-content select=\"[matSuffix]\"></ng-content>\n </mat-autocomplete-field>\n\n <!-- multi auto-complete -->\n <mat-chips-field *ngSwitchCase=\"'entities'\"\n [class]=\"classList\"\n [placeholder]=\"placeholder\"\n [floatLabel]=\"floatLabel\"\n [formControl]=\"formControl\"\n [config]=\"definition.autocomplete\"\n [required]=\"required\"\n [displayWith]=\"getDisplayValueFn(definition)\">\n <ng-content select=\"[matPrefix]\"></ng-content>\n <ng-content select=\"[matSuffix]\"></ng-content>\n </mat-chips-field>\n\n <!-- other -->\n <div *ngSwitchDefault>\n <mat-error *ngIf=\"type\">Unknown type {{type}} for option {{definition.key}}. Please report this error.</mat-error>\n <mat-error *ngIf=\"!type\">Error on option field. Please check console log for details.</mat-error>\n <div matSuffix>\n <ng-content select=\"[matSuffix]\"></ng-content>\n </div>\n </div>\n\n</ng-container>\n",
8152
+ template: "<ng-container [ngSwitch]=\"type\">\n\n <!-- integer -->\n <mat-form-field *ngSwitchCase=\"'integer'\" [floatLabel]=\"floatLabel\" [class]=\"classList\">\n <input matInput #matInput\n type=\"number\"\n autocomplete=\"off\"\n [readonly]=\"readonly\"\n [min]=\"definition.minValue\"\n [max]=\"definition.maxValue\"\n pattern=\"-?[0-9]*\"\n step=\"1\"\n [appAutofocus]=\"autofocus\"\n [placeholder]=\"placeholder\"\n (keyup.enter)=\"onKeyupEnter.emit($event)\"\n (keypress)=\"filterNumberInput($event, false)\"\n [formControl]=\"formControl\"\n [required]=\"required\"\n [tabIndex]=\"tabindex\"\n (click)=\"selectInputContent($event)\">\n <mat-error *ngIf=\"formControl.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"formControl.hasError('min')\">\n {{(compact ? 'ERROR.FIELD_MIN_COMPACT' : 'ERROR.FIELD_MIN') | translate:formControl.errors['min'] }}</mat-error>\n <mat-error *ngIf=\"formControl.hasError('max')\">\n {{(compact ? 'ERROR.FIELD_MAX_COMPACT' : 'ERROR.FIELD_MAX') | translate:formControl.errors['max'] }}</mat-error>\n <mat-error *ngIf=\"formControl.hasError('pattern')\">\n {{'ERROR.FIELD_NOT_VALID_INTEGER'| translate }}</mat-error>\n <mat-error *ngIf=\"formControl.hasError('integer')\">\n {{'ERROR.FIELD_NOT_VALID_INTEGER'| translate }}</mat-error>\n\n <div matSuffix>\n <ng-content select=\"[matSuffix]\"></ng-content>\n </div>\n </mat-form-field>\n\n <!-- double -->\n <mat-form-field *ngSwitchCase=\"'double'\" [floatLabel]=\"floatLabel\" [class]=\"classList\">\n\n <input matInput #matInput\n type=\"number\"\n decimal=\"true\"\n autocomplete=\"off\"\n [min]=\"definition.minValue\"\n [max]=\"definition.maxValue\"\n [appAutofocus]=\"autofocus\"\n [readonly]=\"readonly\"\n [placeholder]=\"placeholder\"\n [step]=\"numberInputStep\"\n (keypress)=\"filterNumberInput($event, true)\"\n [formControl]=\"formControl\"\n [required]=\"required\"\n [tabIndex]=\"tabindex\"\n (click)=\"selectInputContent($event)\">\n <mat-error *ngIf=\"formControl.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"formControl.hasError('min')\">\n {{ (compact ? 'ERROR.FIELD_MIN_COMPACT' : 'ERROR.FIELD_MIN')| translate:formControl.errors['min'] }}</mat-error>\n <mat-error *ngIf=\"formControl.hasError('max')\">\n {{(compact ? 'ERROR.FIELD_MAX_COMPACT' : 'ERROR.FIELD_MAX') | translate:formControl.errors['max'] }}</mat-error>\n <mat-error *ngIf=\"formControl.hasError('maxDecimals')\">\n {{ (compact ? 'ERROR.FIELD_MAXIMUM_DECIMALS_COMPACT' : 'ERROR.FIELD_MAXIMUM_DECIMALS')| translate:{max:\n definition.maximumNumberDecimals} }}</mat-error>\n <div matSuffix>\n <ng-content select=\"[matSuffix]\"></ng-content>\n </div>\n </mat-form-field>\n\n <!-- boolean -->\n <mat-boolean-field *ngSwitchCase=\"'boolean'\" #matInput\n [class]=\"classList\"\n [formControl]=\"formControl\"\n [placeholder]=\"placeholder\"\n [floatLabel]=\"floatLabel\"\n [required]=\"required\"\n [compact]=\"compact\"\n [tabindex]=\"tabindex\"\n [readonly]=\"readonly\">\n <div matSuffix>\n <ng-content select=\"[matSuffix]\"></ng-content>\n </div>\n </mat-boolean-field>\n\n <!-- date -->\n <mat-date-field *ngSwitchCase=\"'date'\" #matInput\n [class]=\"classList\"\n [formControl]=\"formControl\"\n [placeholder]=\"compact ? ('COMMON.DATE_PLACEHOLDER'|translate): placeholder\"\n [floatLabel]=\"floatLabel\"\n [required]=\"required\"\n [readonly]=\"readonly\"\n [compact]=\"compact\"\n [tabindex]=\"tabindex\"\n [autofocus]=\"autofocus\">\n <div matSuffix>\n <ng-content select=\"[matSuffix]\"></ng-content>\n </div>\n </mat-date-field>\n\n <!-- date time -->\n <mat-date-time-field *ngSwitchCase=\"'dateTime'\" #matInput\n [class]=\"classList\"\n [formControl]=\"formControl\"\n [placeholder]=\"compact ? ('COMMON.DATE_TIME_PLACEHOLDER'|translate): placeholder\"\n [floatLabel]=\"floatLabel\"\n [required]=\"required\"\n [readonly]=\"readonly\"\n [compact]=\"compact\"\n [tabindex]=\"tabindex\"\n [autofocus]=\"autofocus\">\n <div matSuffix>\n <ng-content select=\"[matSuffix]\"></ng-content>\n </div>\n </mat-date-time-field>\n\n <!-- enum -->\n <mat-form-field *ngSwitchCase=\"'enum'\" [floatLabel]=\"floatLabel\" [class]=\"classList\">\n <mat-select [formControl]=\"formControl\"\n [placeholder]=\"placeholder\"\n [required]=\"required\"\n [tabindex]=\"tabindex\"\n (keyup.enter)=\"onKeyupEnter.emit($event)\">\n <mat-option *ngFor=\"let item of definition.values\" [value]=\"item.key || item\">{{ (item.value || item) | translate }}</mat-option>\n </mat-select>\n\n <mat-error *ngIf=\"formControl.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n\n <div matSuffix>\n <ng-content select=\"[matSuffix]\"></ng-content>\n </div>\n </mat-form-field>\n\n <!-- color -->\n <mat-form-field *ngSwitchCase=\"'color'\" [floatLabel]=\"floatLabel\" [class]=\"classList\">\n\n <ion-icon margin-right name=\"color-fill\" matPrefix></ion-icon>\n\n <input matInput autocomplete=\"off\"\n [appAutofocus]=\"autofocus\"\n [formControl]=\"formControl\"\n [style.color]=\"getColorContrast(formControl.value)\"\n [style.background]=\"formControl.value\"\n [colorPicker]=\"formControl.value\"\n (colorPickerChange)=\"writeValue($event)\"\n [cpSaveClickOutside]=\"true\"\n cpPosition=\"top\"\n cpOutputFormat=\"hex\"\n [cpOKButton]=\"false\"\n [required]=\"required\"/>\n <mat-error *ngIf=\"formControl.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n </mat-form-field>\n\n <!-- string -->\n <mat-form-field *ngSwitchCase=\"'string'\" [floatLabel]=\"floatLabel\" [class]=\"classList\">\n <input matInput #matInput\n autocomplete=\"off\"\n [appAutofocus]=\"autofocus\"\n [formControl]=\"formControl\"\n [placeholder]=\"placeholder\"\n [required]=\"required\"\n [readonly]=\"readonly\"\n [tabIndex]=\"tabindex\"\n (click)=\"selectInputContent($event)\"\n (keypress)=\"filterAlphanumericalInput($event)\"\n (keyup.enter)=\"onKeyupEnter.emit($event)\">\n <mat-error *ngIf=\"formControl.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <div matSuffix>\n <ng-content select=\"[matSuffix]\"></ng-content>\n </div>\n </mat-form-field>\n\n <!-- auto-complete -->\n <mat-autocomplete-field *ngSwitchCase=\"'entity'\"\n [class]=\"classList\"\n [autofocus]=\"autofocus\"\n [placeholder]=\"placeholder\"\n [floatLabel]=\"floatLabel\"\n [formControl]=\"formControl\"\n [config]=\"definition.autocomplete\"\n [required]=\"required\"\n [displayWith]=\"getDisplayValueFn(definition)\">\n <ng-content select=\"[matPrefix]\"></ng-content>\n <ng-content select=\"[matSuffix]\"></ng-content>\n </mat-autocomplete-field>\n\n <!-- multi auto-complete -->\n <mat-chips-field *ngSwitchCase=\"'entities'\"\n [class]=\"classList\"\n [placeholder]=\"placeholder\"\n [floatLabel]=\"floatLabel\"\n [formControl]=\"formControl\"\n [config]=\"definition.autocomplete\"\n [required]=\"required\"\n [displayWith]=\"getDisplayValueFn(definition)\">\n <ng-content select=\"[matPrefix]\"></ng-content>\n <ng-content select=\"[matSuffix]\"></ng-content>\n </mat-chips-field>\n\n <!-- other -->\n <div *ngSwitchDefault>\n <mat-error *ngIf=\"type\">Unknown type {{type}} for option {{definition.key}}. Please report this error.</mat-error>\n <mat-error *ngIf=\"!type\">Error on option field. Please check console log for details.</mat-error>\n <div matSuffix>\n <ng-content select=\"[matSuffix]\"></ng-content>\n </div>\n </div>\n\n</ng-container>\n",
8139
8153
  providers: [
8140
8154
  {
8141
8155
  provide: NG_VALUE_ACCESSOR,
@@ -17511,7 +17525,7 @@ class AuthForm extends AppForm {
17511
17525
  this.form.get('username').setValidators(Validators.required);
17512
17526
  }
17513
17527
  // Enable/disable registration link
17514
- this.canRegister = config.getProperty(CORE_CONFIG_OPTIONS.REGISTRATION_ENABLE);
17528
+ this.canRegister = config.getPropertyAsBoolean(CORE_CONFIG_OPTIONS.REGISTRATION_ENABLE);
17515
17529
  this.markForCheck();
17516
17530
  }));
17517
17531
  // For DEV only
@@ -21381,13 +21395,6 @@ class AppTable {
21381
21395
  markAsLoaded(opts) {
21382
21396
  this.setLoading(false, opts);
21383
21397
  }
21384
- markRowAsDirty(row, opts) {
21385
- var _a;
21386
- row = row || this.editedRow;
21387
- if (row)
21388
- (_a = row.validator) === null || _a === void 0 ? void 0 : _a.markAsDirty(opts);
21389
- this.markAsDirty(opts);
21390
- }
21391
21398
  markAsReady(opts) {
21392
21399
  if (this.readySubject.value !== true) {
21393
21400
  this.readySubject.next(true);
@@ -22508,6 +22515,13 @@ class AppTable {
22508
22515
  equals(d1, d2) {
22509
22516
  return EntityUtils.equals(d1, d2, 'id');
22510
22517
  }
22518
+ markRowAsDirty(row, opts) {
22519
+ var _a;
22520
+ row = row || this.editedRow;
22521
+ if (row)
22522
+ (_a = row.validator) === null || _a === void 0 ? void 0 : _a.markAsDirty(opts);
22523
+ this.markAsDirty(opts);
22524
+ }
22511
22525
  /* -- private method -- */
22512
22526
  setLoading(value, opts) {
22513
22527
  if (this.loadingSubject.value !== value) {