igniteui-angular 12.3.40 → 12.3.42

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.
@@ -35248,6 +35248,9 @@ class IgxComboAPIService {
35248
35248
  }
35249
35249
  set_selected_item(itemID, event) {
35250
35250
  const selected = this.combo.isItemSelected(itemID);
35251
+ if (itemID === undefined) {
35252
+ return;
35253
+ }
35251
35254
  if (!selected) {
35252
35255
  this.combo.select([itemID], false, event);
35253
35256
  }
@@ -35829,7 +35832,13 @@ class IgxComboBaseDirective extends DisplayDensityBase {
35829
35832
  return this._data;
35830
35833
  }
35831
35834
  set data(val) {
35832
- this._data = (val) ? val : [];
35835
+ // igxFor directive ignores undefined values
35836
+ // if the combo uses simple data and filtering is applied
35837
+ // an error will occur due to the mismatch of the length of the data
35838
+ // this can occur during filtering for the igx-combo and
35839
+ // during filtering & selection for the igx-simple-combo
35840
+ // since the simple combo's input is both a container for the selection and a filter
35841
+ this._data = (val) ? val.filter(x => x !== undefined) : [];
35833
35842
  }
35834
35843
  set displayKey(val) {
35835
35844
  this._displayKey = val;
@@ -36335,6 +36344,14 @@ class IgxComboBaseDirective extends DisplayDensityBase {
36335
36344
  this.registerRemoteEntries(removedItems, false);
36336
36345
  return Object.keys(this._remoteSelection).map(e => this._remoteSelection[e]).join(', ');
36337
36346
  }
36347
+ get required() {
36348
+ if (this.ngControl && this.ngControl.control && this.ngControl.control.validator) {
36349
+ // Run the validation with empty object to check if required is enabled.
36350
+ const error = this.ngControl.control.validator({});
36351
+ return error && error.required;
36352
+ }
36353
+ return false;
36354
+ }
36338
36355
  }
36339
36356
  IgxComboBaseDirective.decorators = [
36340
36357
  { type: Directive }
@@ -36508,7 +36525,7 @@ class IgxComboDropDownComponent extends IgxDropDownComponent {
36508
36525
  * @hidden
36509
36526
  */
36510
36527
  navigateFirst() {
36511
- this.navigateItem(this.virtDir.igxForOf.findIndex(e => !e.isHeader));
36528
+ this.navigateItem(this.virtDir.igxForOf.findIndex(e => !(e === null || e === void 0 ? void 0 : e.isHeader)));
36512
36529
  }
36513
36530
  /**
36514
36531
  * @hidden
@@ -36643,8 +36660,8 @@ class IgxComboFilteringPipe {
36643
36660
  });
36644
36661
  }
36645
36662
  else {
36646
- return collection.filter(e => filteringOptions.caseSensitive ? e.includes(searchTerm) :
36647
- e.toString().toLowerCase().includes(searchTerm));
36663
+ return collection.filter(e => filteringOptions.caseSensitive ? e === null || e === void 0 ? void 0 : e.includes(searchTerm) :
36664
+ e === null || e === void 0 ? void 0 : e.toString().toLowerCase().includes(searchTerm));
36648
36665
  }
36649
36666
  }
36650
36667
  }
@@ -36658,6 +36675,7 @@ class IgxComboGroupingPipe {
36658
36675
  this.combo = combo;
36659
36676
  }
36660
36677
  transform(collection, groupKey, valueKey) {
36678
+ // TODO: should filteredData be changed here?
36661
36679
  this.combo.filteredData = collection;
36662
36680
  if ((!groupKey && groupKey !== 0) || !collection.length) {
36663
36681
  return collection;
@@ -36832,7 +36850,7 @@ class IgxComboComponent extends IgxComboBaseDirective {
36832
36850
  * @hidden @internal
36833
36851
  */
36834
36852
  writeValue(value) {
36835
- const selection = Array.isArray(value) ? value : [];
36853
+ const selection = Array.isArray(value) ? value.filter(x => x !== undefined) : [];
36836
36854
  const oldSelection = this.selection;
36837
36855
  this.selectionService.select_items(this.id, selection, true);
36838
36856
  this.cdr.markForCheck();
@@ -36945,6 +36963,9 @@ class IgxComboComponent extends IgxComboBaseDirective {
36945
36963
  * ```
36946
36964
  */
36947
36965
  setSelectedItem(itemID, select = true, event) {
36966
+ if (itemID === undefined) {
36967
+ return;
36968
+ }
36948
36969
  if (select) {
36949
36970
  this.select([itemID], false, event);
36950
36971
  }
@@ -37028,7 +37049,7 @@ class IgxComboComponent extends IgxComboBaseDirective {
37028
37049
  IgxComboComponent.decorators = [
37029
37050
  { type: Component, args: [{
37030
37051
  selector: 'igx-combo',
37031
- template: "<igx-input-group #inputGroup [displayDensity]=\"displayDensity\" [type]=\"type\" (click)=\"onClick($event)\">\n <ng-container ngProjectAs=\"[igxLabel]\">\n <ng-content select=\"[igxLabel]\"></ng-content>\n </ng-container>\n <ng-container ngProjectAs=\"igx-prefix\">\n <ng-content select=\"igx-prefix\"></ng-content>\n </ng-container>\n <ng-container ngProjectAs=\"igx-hint, [igxHint]\">\n <ng-content select=\"igx-hint, [igxHint]\"></ng-content>\n </ng-container>\n <input igxInput #comboInput name=\"comboInput\" type=\"text\" [value]=\"value\" readonly [attr.placeholder]=\"placeholder\"\n [disabled]=\"disabled\" (blur)=\"onBlur()\" />\n <ng-container ngProjectAs=\"igx-suffix\">\n <ng-content select=\"igx-suffix\"></ng-content>\n </ng-container>\n <igx-suffix *ngIf=\"value.length\" aria-label=\"Clear Selection\" class=\"igx-combo__clear-button\"\n (click)=\"handleClearItems($event)\">\n <ng-container *ngIf=\"clearIconTemplate\">\n <ng-container *ngTemplateOutlet=\"clearIconTemplate\"></ng-container>\n </ng-container>\n <igx-icon *ngIf=\"!clearIconTemplate\">\n clear\n </igx-icon>\n </igx-suffix>\n <igx-suffix class=\"igx-combo__toggle-button\">\n <ng-container *ngIf=\"toggleIconTemplate\">\n <ng-container *ngTemplateOutlet=\"toggleIconTemplate; context: {$implicit: this.collapsed}\"></ng-container>\n </ng-container>\n <igx-icon *ngIf=\"!toggleIconTemplate\">\n {{ dropdown.collapsed ? 'arrow_drop_down' : 'arrow_drop_up'}}\n </igx-icon>\n </igx-suffix>\n</igx-input-group>\n<igx-combo-drop-down #igxComboDropDown class=\"igx-combo__drop-down\" [displayDensity]=\"displayDensity\"\n [width]=\"itemsWidth || '100%'\" (opening)=\"handleOpening($event)\" (closing)=\"handleClosing($event)\"\n (opened)=\"handleOpened()\" (closed)=\"handleClosed()\">\n <igx-input-group *ngIf=\"displaySearchInput\" [displayDensity]=\"displayDensity\" theme=\"material\" class=\"igx-combo__search\">\n <input class=\"igx-combo-input\" igxInput #searchInput name=\"searchInput\" autocomplete=\"off\" type=\"text\"\n [(ngModel)]=\"searchValue\" (ngModelChange)=\"handleInputChange($event)\" (keyup)=\"handleKeyUp($event)\"\n (keydown)=\"handleKeyDown($event)\" (focus)=\"dropdown.onBlur($event)\" [attr.placeholder]=\"searchPlaceholder\"\n aria-autocomplete=\"both\" [attr.aria-owns]=\"dropdown.id\" [attr.aria-labelledby]=\"ariaLabelledBy\" />\n <igx-suffix *ngIf=\"showSearchCaseIcon\">\n <igx-icon family=\"imx-icons\" name=\"case-sensitive\" [active]=\"filteringOptions.caseSensitive\"\n (click)=\"toggleCaseSensitive()\">\n </igx-icon>\n </igx-suffix>\n </igx-input-group>\n <ng-container *ngTemplateOutlet=\"headerTemplate\">\n </ng-container>\n <div #dropdownItemContainer class=\"igx-combo__content\" [style.overflow]=\"'hidden'\"\n [style.maxHeight.px]=\"itemsMaxHeight\" [igxDropDownItemNavigation]=\"dropdown\" (focus)=\"dropdown.onFocus()\"\n [tabindex]=\"dropdown.collapsed ? -1 : 0\" role=\"listbox\" [attr.id]=\"dropdown.id\">\n <igx-combo-item role=\"option\" [itemHeight]='itemHeight' *igxFor=\"let item of data\n | comboFiltering:filterValue:displayKey:filteringOptions:filterable\n | comboGrouping:groupKey:valueKey\n index as rowIndex; containerSize: itemsMaxHeight; scrollOrientation: 'vertical'; itemSize: itemHeight\"\n [value]=\"item\" [isHeader]=\"item.isHeader\" [index]=\"rowIndex\">\n <ng-container *ngIf=\"item.isHeader\">\n <ng-container\n *ngTemplateOutlet=\"headerItemTemplate ? headerItemTemplate : headerItemBase;\n context: {$implicit: item, data: data, valueKey: valueKey, groupKey: groupKey, displayKey: displayKey}\">\n </ng-container>\n </ng-container>\n <ng-container *ngIf=\"!item.isHeader\">\n <ng-container #listItem\n *ngTemplateOutlet=\"template; context: {$implicit: item, data: data, valueKey: valueKey, displayKey: displayKey};\">\n </ng-container>\n </ng-container>\n </igx-combo-item>\n </div>\n <div class=\"igx-combo__add\" *ngIf=\"filteredData.length === 0 || isAddButtonVisible()\">\n <div class=\"igx-combo__empty\" *ngIf=\"filteredData.length === 0\">\n <ng-container *ngTemplateOutlet=\"emptyTemplate ? emptyTemplate : empty\">\n </ng-container>\n </div>\n <igx-combo-add-item [itemHeight]=\"itemHeight\" *ngIf=\"isAddButtonVisible()\"\n [tabindex]=\"dropdown.collapsed ? -1 : customValueFlag ? 1 : -1\" class=\"igx-combo__add-item\" role=\"button\"\n aria-label=\"Add Item\" [index]=\"virtualScrollContainer.igxForOf.length\">\n <ng-container *ngTemplateOutlet=\"addItemTemplate ? addItemTemplate : addItemDefault\">\n </ng-container>\n </igx-combo-add-item>\n </div>\n <ng-container *ngTemplateOutlet=\"footerTemplate\">\n </ng-container>\n</igx-combo-drop-down>\n<ng-template #complex let-display let-data=\"data\" let-key=\"displayKey\">\n {{display[key]}}\n</ng-template>\n<ng-template #primitive let-display>\n {{display}}\n</ng-template>\n<ng-template #empty>\n <span>{{resourceStrings.igx_combo_empty_message}}</span>\n</ng-template>\n<ng-template #addItemDefault let-control>\n <button igxButton=\"flat\" igxRipple>Add item</button>\n</ng-template>\n<ng-template #headerItemBase let-item let-key=\"valueKey\" let-groupKey=\"groupKey\">\n {{ item[key] }}\n</ng-template>\n",
37052
+ template: "<igx-input-group #inputGroup [displayDensity]=\"displayDensity\" [type]=\"type\" (click)=\"onClick($event)\">\n <ng-container ngProjectAs=\"[igxLabel]\">\n <ng-content select=\"[igxLabel]\"></ng-content>\n </ng-container>\n <ng-container ngProjectAs=\"igx-prefix\">\n <ng-content select=\"igx-prefix\"></ng-content>\n </ng-container>\n <ng-container ngProjectAs=\"igx-hint, [igxHint]\">\n <ng-content select=\"igx-hint, [igxHint]\"></ng-content>\n </ng-container>\n <input igxInput #comboInput name=\"comboInput\" type=\"text\" [value]=\"value\" readonly [attr.placeholder]=\"placeholder\"\n [disabled]=\"disabled\" (blur)=\"onBlur()\" />\n <ng-container ngProjectAs=\"igx-suffix\">\n <ng-content select=\"igx-suffix\"></ng-content>\n </ng-container>\n <igx-suffix *ngIf=\"value.length\" aria-label=\"Clear Selection\" class=\"igx-combo__clear-button\"\n (click)=\"handleClearItems($event)\">\n <ng-container *ngIf=\"clearIconTemplate\">\n <ng-container *ngTemplateOutlet=\"clearIconTemplate\"></ng-container>\n </ng-container>\n <igx-icon *ngIf=\"!clearIconTemplate\">\n clear\n </igx-icon>\n </igx-suffix>\n <igx-suffix class=\"igx-combo__toggle-button\">\n <ng-container *ngIf=\"toggleIconTemplate\">\n <ng-container *ngTemplateOutlet=\"toggleIconTemplate; context: {$implicit: this.collapsed}\"></ng-container>\n </ng-container>\n <igx-icon *ngIf=\"!toggleIconTemplate\">\n {{ dropdown.collapsed ? 'arrow_drop_down' : 'arrow_drop_up'}}\n </igx-icon>\n </igx-suffix>\n</igx-input-group>\n<igx-combo-drop-down #igxComboDropDown class=\"igx-combo__drop-down\" [displayDensity]=\"displayDensity\"\n [width]=\"itemsWidth || '100%'\" (opening)=\"handleOpening($event)\" (closing)=\"handleClosing($event)\"\n (opened)=\"handleOpened()\" (closed)=\"handleClosed()\">\n <igx-input-group *ngIf=\"displaySearchInput\" [displayDensity]=\"displayDensity\" theme=\"material\" class=\"igx-combo__search\">\n <input class=\"igx-combo-input\" igxInput #searchInput name=\"searchInput\" autocomplete=\"off\" type=\"text\"\n [(ngModel)]=\"searchValue\" (ngModelChange)=\"handleInputChange($event)\" (keyup)=\"handleKeyUp($event)\"\n (keydown)=\"handleKeyDown($event)\" (focus)=\"dropdown.onBlur($event)\" [attr.placeholder]=\"searchPlaceholder\"\n aria-autocomplete=\"both\" [attr.aria-owns]=\"dropdown.id\" [attr.aria-labelledby]=\"ariaLabelledBy\" />\n <igx-suffix *ngIf=\"showSearchCaseIcon\">\n <igx-icon family=\"imx-icons\" name=\"case-sensitive\" [active]=\"filteringOptions.caseSensitive\"\n (click)=\"toggleCaseSensitive()\">\n </igx-icon>\n </igx-suffix>\n </igx-input-group>\n <ng-container *ngTemplateOutlet=\"headerTemplate\">\n </ng-container>\n <div #dropdownItemContainer class=\"igx-combo__content\" [style.overflow]=\"'hidden'\"\n [style.maxHeight.px]=\"itemsMaxHeight\" [igxDropDownItemNavigation]=\"dropdown\" (focus)=\"dropdown.onFocus()\"\n [tabindex]=\"dropdown.collapsed ? -1 : 0\" role=\"listbox\" [attr.id]=\"dropdown.id\">\n <igx-combo-item role=\"option\" [itemHeight]='itemHeight' *igxFor=\"let item of data\n | comboFiltering:filterValue:displayKey:filteringOptions:filterable\n | comboGrouping:groupKey:valueKey\n index as rowIndex; containerSize: itemsMaxHeight; scrollOrientation: 'vertical'; itemSize: itemHeight\"\n [value]=\"item\" [isHeader]=\"item?.isHeader\" [index]=\"rowIndex\">\n <ng-container *ngIf=\"item?.isHeader\">\n <ng-container\n *ngTemplateOutlet=\"headerItemTemplate ? headerItemTemplate : headerItemBase;\n context: {$implicit: item, data: data, valueKey: valueKey, groupKey: groupKey, displayKey: displayKey}\">\n </ng-container>\n </ng-container>\n <!-- if item is 'null' it should be displayed and !!(item?.isHeader) would resolve it to 'false' and not display it -->\n <ng-container *ngIf=\"!item?.isHeader\">\n <ng-container #listItem\n *ngTemplateOutlet=\"template; context: {$implicit: item, data: data, valueKey: valueKey, displayKey: displayKey};\">\n </ng-container>\n </ng-container>\n </igx-combo-item>\n </div>\n <div class=\"igx-combo__add\" *ngIf=\"filteredData.length === 0 || isAddButtonVisible()\">\n <div class=\"igx-combo__empty\" *ngIf=\"filteredData.length === 0\">\n <ng-container *ngTemplateOutlet=\"emptyTemplate ? emptyTemplate : empty\">\n </ng-container>\n </div>\n <igx-combo-add-item [itemHeight]=\"itemHeight\" *ngIf=\"isAddButtonVisible()\"\n [tabindex]=\"dropdown.collapsed ? -1 : customValueFlag ? 1 : -1\" class=\"igx-combo__add-item\" role=\"button\"\n aria-label=\"Add Item\" [index]=\"virtualScrollContainer.igxForOf.length\">\n <ng-container *ngTemplateOutlet=\"addItemTemplate ? addItemTemplate : addItemDefault\">\n </ng-container>\n </igx-combo-add-item>\n </div>\n <ng-container *ngTemplateOutlet=\"footerTemplate\">\n </ng-container>\n</igx-combo-drop-down>\n<ng-template #complex let-display let-data=\"data\" let-key=\"displayKey\">\n {{display[key]}}\n</ng-template>\n<ng-template #primitive let-display>\n {{display}}\n</ng-template>\n<ng-template #empty>\n <span>{{resourceStrings.igx_combo_empty_message}}</span>\n</ng-template>\n<ng-template #addItemDefault let-control>\n <button igxButton=\"flat\" igxRipple>Add item</button>\n</ng-template>\n<ng-template #headerItemBase let-item let-key=\"valueKey\" let-groupKey=\"groupKey\">\n {{ item[key] }}\n</ng-template>\n",
37032
37053
  providers: [
37033
37054
  IgxComboAPIService,
37034
37055
  { provide: IGX_COMBO_COMPONENT, useExisting: IgxComboComponent },
@@ -37131,6 +37152,7 @@ class IgxSimpleComboComponent extends IgxComboBaseDirective {
37131
37152
  this._updateInput = true;
37132
37153
  // stores the last filtered value - move to common?
37133
37154
  this._internalFilter = '';
37155
+ this._collapsing = false;
37134
37156
  this.findAllMatches = (element) => {
37135
37157
  const value = this.displayKey ? element[this.displayKey] : element;
37136
37158
  if (value === null || value === undefined || value === '') {
@@ -37187,7 +37209,7 @@ class IgxSimpleComboComponent extends IgxComboBaseDirective {
37187
37209
  * ```
37188
37210
  */
37189
37211
  select(item) {
37190
- if (item !== null && item !== undefined) {
37212
+ if (item !== undefined) {
37191
37213
  const newSelection = this.selectionService.add_items(this.id, item instanceof Array ? item : [item], true);
37192
37214
  this.setSelection(newSelection);
37193
37215
  }
@@ -37205,17 +37227,19 @@ class IgxSimpleComboComponent extends IgxComboBaseDirective {
37205
37227
  }
37206
37228
  /** @hidden @internal */
37207
37229
  writeValue(value) {
37230
+ var _a;
37208
37231
  const oldSelection = this.selection;
37209
- this.selectionService.select_items(this.id, value ? [value] : [], true);
37232
+ this.selectionService.select_items(this.id, this.isValid(value) ? [value] : [], true);
37210
37233
  this.cdr.markForCheck();
37211
37234
  this._value = this.createDisplayText(this.selection, oldSelection);
37235
+ this.filterValue = this._internalFilter = (_a = this._value) === null || _a === void 0 ? void 0 : _a.toString();
37212
37236
  }
37213
37237
  /** @hidden @internal */
37214
37238
  ngAfterViewInit() {
37215
37239
  this.virtDir.contentSizeChange.pipe(takeUntil(this.destroy$)).subscribe(() => {
37216
37240
  if (this.selection.length > 0) {
37217
37241
  const index = this.virtDir.igxForOf.findIndex(e => {
37218
- let current = e[this.valueKey];
37242
+ let current = e ? e[this.valueKey] : undefined;
37219
37243
  if (this.valueKey === null || this.valueKey === undefined) {
37220
37244
  current = e;
37221
37245
  }
@@ -37229,7 +37253,11 @@ class IgxSimpleComboComponent extends IgxComboBaseDirective {
37229
37253
  }
37230
37254
  }
37231
37255
  });
37232
- this.dropdown.opening.pipe(takeUntil(this.destroy$)).subscribe(() => {
37256
+ this.dropdown.opening.pipe(takeUntil(this.destroy$)).subscribe((args) => {
37257
+ if (args.cancel) {
37258
+ return;
37259
+ }
37260
+ this._collapsing = false;
37233
37261
  const filtered = this.filteredData.find(this.findAllMatches);
37234
37262
  if (filtered === undefined || filtered === null) {
37235
37263
  this.filterValue = this.searchValue = this.comboInput.value;
@@ -37244,17 +37272,27 @@ class IgxSimpleComboComponent extends IgxComboBaseDirective {
37244
37272
  this._internalFilter = this.comboInput.value;
37245
37273
  });
37246
37274
  this.dropdown.closing.pipe(takeUntil(this.destroy$)).subscribe((args) => {
37275
+ if (args.cancel) {
37276
+ return;
37277
+ }
37247
37278
  if (this.getEditElement() && !args.event) {
37248
- this.comboInput.focus();
37279
+ this._collapsing = true;
37249
37280
  }
37250
37281
  else {
37251
37282
  this.clearOnBlur();
37252
37283
  this._onTouchedCallback();
37253
37284
  }
37285
+ this.comboInput.focus();
37254
37286
  });
37255
37287
  this.dropdown.closed.pipe(takeUntil(this.destroy$)).subscribe(() => {
37256
37288
  this.filterValue = this._internalFilter = this.comboInput.value;
37257
37289
  });
37290
+ // in reactive form the control is not present initially
37291
+ // and sets the selection to an invalid value in writeValue method
37292
+ if (!this.isValid(this.selectedItem)) {
37293
+ this.selectionService.clear(this.id);
37294
+ this._value = '';
37295
+ }
37258
37296
  super.ngAfterViewInit();
37259
37297
  }
37260
37298
  /** @hidden @internal */
@@ -37266,7 +37304,7 @@ class IgxSimpleComboComponent extends IgxComboBaseDirective {
37266
37304
  if (this.collapsed && this.comboInput.focused) {
37267
37305
  this.open();
37268
37306
  }
37269
- if (!this.comboInput.value.trim() && this.selectionService.size(this.id) > 0) {
37307
+ if (!this.comboInput.value.trim() && this.selection.length) {
37270
37308
  // handle clearing of input by space
37271
37309
  this.clearSelection();
37272
37310
  this._onChangeCallback(null);
@@ -37301,6 +37339,7 @@ class IgxSimpleComboComponent extends IgxComboBaseDirective {
37301
37339
  }
37302
37340
  if (!this.collapsed && event.key === this.platformUtil.KEYMAP.TAB) {
37303
37341
  this.clearOnBlur();
37342
+ this.close();
37304
37343
  }
37305
37344
  this.composing = false;
37306
37345
  super.handleKeyDown(event);
@@ -37332,6 +37371,15 @@ class IgxSimpleComboComponent extends IgxComboBaseDirective {
37332
37371
  this.comboInput.focus();
37333
37372
  }
37334
37373
  /** @hidden @internal */
37374
+ onBlur() {
37375
+ // when clicking the toggle button to close the combo and immediately clicking outside of it
37376
+ // the collapsed state is not modified as the dropdown is still not closed
37377
+ if (this.collapsed || this._collapsing) {
37378
+ this.clearOnBlur();
37379
+ }
37380
+ super.onBlur();
37381
+ }
37382
+ /** @hidden @internal */
37335
37383
  onFocus() {
37336
37384
  this._internalFilter = this.comboInput.value || '';
37337
37385
  }
@@ -37405,17 +37453,12 @@ class IgxSimpleComboComponent extends IgxComboBaseDirective {
37405
37453
  owner: this,
37406
37454
  cancel: false
37407
37455
  };
37408
- // additional checks when selecting and clearing an item with valueKey=undefined
37409
- // as the event should emit when args.newSelection differs from args.oldSelection
37410
- // however in this case both args.newSelection and args.oldSelection are 'undefined'
37411
- if (args.newSelection !== args.oldSelection
37412
- || args.newSelection === undefined && (newSelection === null || newSelection === void 0 ? void 0 : newSelection.size) > 0
37413
- || args.oldSelection === undefined && oldSelectionAsArray.length > 0) {
37456
+ if (args.newSelection !== args.oldSelection) {
37414
37457
  this.selectionChanging.emit(args);
37415
37458
  }
37416
37459
  // TODO: refactor below code as it sets the selection and the display text
37417
37460
  if (!args.cancel) {
37418
- let argsSelection = (newSelection === null || newSelection === void 0 ? void 0 : newSelection.size) > 0
37461
+ let argsSelection = this.isValid(args.newSelection)
37419
37462
  ? args.newSelection
37420
37463
  : [];
37421
37464
  argsSelection = Array.isArray(argsSelection) ? argsSelection : [argsSelection];
@@ -37452,32 +37495,31 @@ class IgxSimpleComboComponent extends IgxComboBaseDirective {
37452
37495
  }
37453
37496
  clearOnBlur() {
37454
37497
  const filtered = this.filteredData.find(this.findMatch);
37455
- if (filtered === undefined || filtered === null || this.getElementKey(filtered) !== this.selectedItem) {
37456
- this.clearAndClose();
37498
+ // selecting null in primitive data returns undefined as the search text is '', but the item is null
37499
+ if (filtered === undefined && this.selectedItem !== null || !this.selection.length) {
37500
+ this.clear();
37457
37501
  return;
37458
37502
  }
37459
37503
  }
37460
- getElementKey(element) {
37461
- const elementVal = this.valueKey ? element[this.valueKey] : element;
37462
- return elementVal;
37463
- }
37464
37504
  getElementVal(element) {
37465
37505
  const elementVal = this.displayKey ? element[this.displayKey] : element;
37466
37506
  return String(elementVal);
37467
37507
  }
37468
- clearAndClose() {
37508
+ clear() {
37469
37509
  this.clearSelection(true);
37470
37510
  this._internalFilter = '';
37471
37511
  this.searchValue = '';
37472
- if (!this.collapsed) {
37473
- this.close();
37474
- }
37512
+ }
37513
+ isValid(value) {
37514
+ return this.required
37515
+ ? value !== null && value !== '' && value !== undefined
37516
+ : value !== undefined;
37475
37517
  }
37476
37518
  }
37477
37519
  IgxSimpleComboComponent.decorators = [
37478
37520
  { type: Component, args: [{
37479
37521
  selector: 'igx-simple-combo',
37480
- template: "<igx-input-group #inputGroup [displayDensity]=\"displayDensity\" [suppressInputAutofocus]=\"true\" [type]=\"type\">\n <ng-container ngProjectAs=\"[igxLabel]\">\n <ng-content select=\"[igxLabel]\"></ng-content>\n </ng-container>\n <ng-container ngProjectAs=\"igx-prefix\">\n <ng-content select=\"igx-prefix\"></ng-content>\n </ng-container>\n <ng-container ngProjectAs=\"igx-hint, [igxHint]\">\n <ng-content select=\"igx-hint, [igxHint]\"></ng-content>\n </ng-container>\n\n <input #comboInput igxInput [value]=\"value\" (focus)=\"onFocus()\" (input)=\"handleInputChange($event)\" (keyup)=\"handleKeyUp($event)\"\n (keydown)=\"handleKeyDown($event)\" (blur)=\"onBlur()\" [attr.placeholder]=\"placeholder\" aria-autocomplete=\"both\"\n [attr.aria-owns]=\"dropdown.id\" [attr.aria-labelledby]=\"ariaLabelledBy\" [disabled]=\"disabled\"\n [igxTextSelection]=\"!composing\" />\n\n <ng-container ngProjectAs=\"igx-suffix\">\n <ng-content select=\"igx-suffix\"></ng-content>\n </ng-container>\n <igx-suffix *ngIf=\"comboInput.value.length\" aria-label=\"Clear Selection\" class=\"igx-combo__clear-button\"\n (click)=\"handleClear($event)\">\n <ng-container *ngIf=\"clearIconTemplate\">\n <ng-container *ngTemplateOutlet=\"clearIconTemplate\"></ng-container>\n </ng-container>\n <igx-icon *ngIf=\"!clearIconTemplate\">\n clear\n </igx-icon>\n </igx-suffix>\n <igx-suffix *ngIf=\"showSearchCaseIcon\">\n <igx-icon family=\"imx-icons\" name=\"case-sensitive\" [active]=\"filteringOptions.caseSensitive\"\n (click)=\"toggleCaseSensitive()\">\n </igx-icon>\n </igx-suffix>\n <igx-suffix class=\"igx-combo__toggle-button\">\n <ng-container *ngIf=\"toggleIconTemplate\">\n <ng-container *ngTemplateOutlet=\"toggleIconTemplate; context: {$implicit: collapsed}\"></ng-container>\n </ng-container>\n <igx-icon (click)=\"onClick($event)\" *ngIf=\"!toggleIconTemplate\">\n {{ dropdown.collapsed ? 'arrow_drop_down' : 'arrow_drop_up'}}\n </igx-icon>\n </igx-suffix>\n</igx-input-group>\n\n<igx-combo-drop-down #igxComboDropDown class=\"igx-combo__drop-down\" [displayDensity]=\"displayDensity\"\n [width]=\"itemsWidth || '100%'\" (opening)=\"handleOpening($event)\" (closing)=\"handleClosing($event)\"\n (opened)=\"handleOpened()\" (closed)=\"handleClosed()\" [singleMode]=\"true\">\n <ng-container *ngTemplateOutlet=\"headerTemplate\">\n </ng-container>\n <div #dropdownItemContainer class=\"igx-combo__content\" [style.overflow]=\"'hidden'\"\n [style.maxHeight.px]=\"itemsMaxHeight\" [igxDropDownItemNavigation]=\"dropdown\" (focus)=\"dropdown.onFocus()\"\n [tabindex]=\"dropdown.collapsed ? -1 : 0\" role=\"listbox\" [attr.id]=\"dropdown.id\"\n (keydown)=\"handleItemKeyDown($event)\">\n <igx-combo-item role=\"option\" [singleMode]=\"true\" [itemHeight]='itemHeight' (click)=\"handleItemClick()\" *igxFor=\"let item of data\n | comboFiltering:filterValue:displayKey:filteringOptions:true\n | comboGrouping:groupKey:valueKey\n index as rowIndex; containerSize: itemsMaxHeight; scrollOrientation: 'vertical'; itemSize: itemHeight\"\n [value]=\"item\" [isHeader]=\"item.isHeader\" [index]=\"rowIndex\">\n <ng-container *ngIf=\"item.isHeader\">\n <ng-container\n *ngTemplateOutlet=\"headerItemTemplate ? headerItemTemplate : headerItemBase;\n context: {$implicit: item, data: data, valueKey: valueKey, groupKey: groupKey, displayKey: displayKey}\">\n </ng-container>\n </ng-container>\n <ng-container *ngIf=\"!item.isHeader\">\n <ng-container #listItem\n *ngTemplateOutlet=\"template; context: {$implicit: item, data: data, valueKey: valueKey, displayKey: displayKey};\">\n </ng-container>\n </ng-container>\n </igx-combo-item>\n </div>\n\n <div class=\"igx-combo__add\" *ngIf=\"filteredData.length === 0 || isAddButtonVisible()\">\n <div class=\"igx-combo__empty\" *ngIf=\"filteredData.length === 0\">\n <ng-container *ngTemplateOutlet=\"emptyTemplate ? emptyTemplate : empty\">\n </ng-container>\n </div>\n <igx-combo-add-item #addItem [itemHeight]=\"itemHeight\" *ngIf=\"isAddButtonVisible()\"\n [tabindex]=\"dropdown.collapsed ? -1 : customValueFlag ? 1 : -1\" class=\"igx-combo__add-item\" role=\"button\"\n aria-label=\"Add Item\" [index]=\"virtualScrollContainer.igxForOf.length\">\n <ng-container *ngTemplateOutlet=\"addItemTemplate ? addItemTemplate : addItemDefault\">\n </ng-container>\n </igx-combo-add-item>\n </div>\n <ng-container *ngTemplateOutlet=\"footerTemplate\">\n </ng-container>\n</igx-combo-drop-down>\n\n<ng-template #complex let-display let-data=\"data\" let-key=\"displayKey\">\n {{display[key]}}\n</ng-template>\n<ng-template #primitive let-display>\n {{display}}\n</ng-template>\n<ng-template #empty>\n <span>{{resourceStrings.igx_combo_empty_message}}</span>\n</ng-template>\n<ng-template #addItemDefault let-control>\n <button igxButton=\"flat\" igxRipple>Add item</button>\n</ng-template>\n<ng-template #headerItemBase let-item let-key=\"valueKey\" let-groupKey=\"groupKey\">\n {{ item[key] }}\n</ng-template>\n",
37522
+ template: "<igx-input-group #inputGroup [displayDensity]=\"displayDensity\" [suppressInputAutofocus]=\"true\" [type]=\"type\">\n <ng-container ngProjectAs=\"[igxLabel]\">\n <ng-content select=\"[igxLabel]\"></ng-content>\n </ng-container>\n <ng-container ngProjectAs=\"igx-prefix\">\n <ng-content select=\"igx-prefix\"></ng-content>\n </ng-container>\n <ng-container ngProjectAs=\"igx-hint, [igxHint]\">\n <ng-content select=\"igx-hint, [igxHint]\"></ng-content>\n </ng-container>\n\n <input #comboInput igxInput [value]=\"value\" (focus)=\"onFocus()\" (input)=\"handleInputChange($event)\" (keyup)=\"handleKeyUp($event)\"\n (keydown)=\"handleKeyDown($event)\" (blur)=\"onBlur()\" [attr.placeholder]=\"placeholder\" aria-autocomplete=\"both\"\n [attr.aria-owns]=\"dropdown.id\" [attr.aria-labelledby]=\"ariaLabelledBy\" [disabled]=\"disabled\"\n [igxTextSelection]=\"!composing\" />\n\n <ng-container ngProjectAs=\"igx-suffix\">\n <ng-content select=\"igx-suffix\"></ng-content>\n </ng-container>\n <igx-suffix *ngIf=\"comboInput.value.length\" aria-label=\"Clear Selection\" class=\"igx-combo__clear-button\"\n (click)=\"handleClear($event)\">\n <ng-container *ngIf=\"clearIconTemplate\">\n <ng-container *ngTemplateOutlet=\"clearIconTemplate\"></ng-container>\n </ng-container>\n <igx-icon *ngIf=\"!clearIconTemplate\">\n clear\n </igx-icon>\n </igx-suffix>\n <igx-suffix *ngIf=\"showSearchCaseIcon\">\n <igx-icon family=\"imx-icons\" name=\"case-sensitive\" [active]=\"filteringOptions.caseSensitive\"\n (click)=\"toggleCaseSensitive()\">\n </igx-icon>\n </igx-suffix>\n <igx-suffix class=\"igx-combo__toggle-button\">\n <ng-container *ngIf=\"toggleIconTemplate\">\n <ng-container *ngTemplateOutlet=\"toggleIconTemplate; context: {$implicit: collapsed}\"></ng-container>\n </ng-container>\n <igx-icon (click)=\"onClick($event)\" *ngIf=\"!toggleIconTemplate\">\n {{ dropdown.collapsed ? 'arrow_drop_down' : 'arrow_drop_up'}}\n </igx-icon>\n </igx-suffix>\n</igx-input-group>\n\n<igx-combo-drop-down #igxComboDropDown class=\"igx-combo__drop-down\" [displayDensity]=\"displayDensity\"\n [width]=\"itemsWidth || '100%'\" (opening)=\"handleOpening($event)\" (closing)=\"handleClosing($event)\"\n (opened)=\"handleOpened()\" (closed)=\"handleClosed()\" [singleMode]=\"true\">\n <ng-container *ngTemplateOutlet=\"headerTemplate\">\n </ng-container>\n <div #dropdownItemContainer class=\"igx-combo__content\" [style.overflow]=\"'hidden'\"\n [style.maxHeight.px]=\"itemsMaxHeight\" [igxDropDownItemNavigation]=\"dropdown\" (focus)=\"dropdown.onFocus()\"\n [tabindex]=\"dropdown.collapsed ? -1 : 0\" role=\"listbox\" [attr.id]=\"dropdown.id\"\n (keydown)=\"handleItemKeyDown($event)\">\n <igx-combo-item role=\"option\" [singleMode]=\"true\" [itemHeight]='itemHeight' (click)=\"handleItemClick()\" *igxFor=\"let item of data\n | comboFiltering:filterValue:displayKey:filteringOptions:true\n | comboGrouping:groupKey:valueKey\n index as rowIndex; containerSize: itemsMaxHeight; scrollOrientation: 'vertical'; itemSize: itemHeight\"\n [value]=\"item\" [isHeader]=\"item?.isHeader\" [index]=\"rowIndex\">\n <ng-container *ngIf=\"item?.isHeader\">\n <ng-container\n *ngTemplateOutlet=\"headerItemTemplate ? headerItemTemplate : headerItemBase;\n context: {$implicit: item, data: data, valueKey: valueKey, groupKey: groupKey, displayKey: displayKey}\">\n </ng-container>\n </ng-container>\n <!-- if item is 'null' it should be displayed and !!(item?.isHeader) would resolve it to 'false' and not display it -->\n <ng-container *ngIf=\"!item?.isHeader\">\n <ng-container #listItem\n *ngTemplateOutlet=\"template; context: {$implicit: item, data: data, valueKey: valueKey, displayKey: displayKey};\">\n </ng-container>\n </ng-container>\n </igx-combo-item>\n </div>\n\n <div class=\"igx-combo__add\" *ngIf=\"filteredData.length === 0 || isAddButtonVisible()\">\n <div class=\"igx-combo__empty\" *ngIf=\"filteredData.length === 0\">\n <ng-container *ngTemplateOutlet=\"emptyTemplate ? emptyTemplate : empty\">\n </ng-container>\n </div>\n <igx-combo-add-item #addItem [itemHeight]=\"itemHeight\" *ngIf=\"isAddButtonVisible()\"\n [tabindex]=\"dropdown.collapsed ? -1 : customValueFlag ? 1 : -1\" class=\"igx-combo__add-item\" role=\"button\"\n aria-label=\"Add Item\" [index]=\"virtualScrollContainer.igxForOf.length\">\n <ng-container *ngTemplateOutlet=\"addItemTemplate ? addItemTemplate : addItemDefault\">\n </ng-container>\n </igx-combo-add-item>\n </div>\n <ng-container *ngTemplateOutlet=\"footerTemplate\">\n </ng-container>\n</igx-combo-drop-down>\n\n<ng-template #complex let-display let-data=\"data\" let-key=\"displayKey\">\n {{display[key]}}\n</ng-template>\n<ng-template #primitive let-display>\n {{display}}\n</ng-template>\n<ng-template #empty>\n <span>{{resourceStrings.igx_combo_empty_message}}</span>\n</ng-template>\n<ng-template #addItemDefault let-control>\n <button igxButton=\"flat\" igxRipple>Add item</button>\n</ng-template>\n<ng-template #headerItemBase let-item let-key=\"valueKey\" let-groupKey=\"groupKey\">\n {{ item[key] }}\n</ng-template>\n",
37481
37523
  providers: [
37482
37524
  IgxComboAPIService,
37483
37525
  { provide: IGX_COMBO_COMPONENT, useExisting: IgxSimpleComboComponent },