UNPKG

igniteui-angular

Version:

Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps

607 lines (601 loc) 41.5 kB
import * as i3 from 'igniteui-angular/input-group'; import { IgxInputGroupComponent, IgxInputDirective, IgxSuffixDirective, IgxLabelDirective, IgxPrefixDirective, IgxHintDirective } from 'igniteui-angular/input-group'; import { NgTemplateOutlet } from '@angular/common'; import * as i0 from '@angular/core'; import { inject, EventEmitter, HostListener, ViewChild, Output, Component, NgModule } from '@angular/core'; import { FormGroupDirective, NG_VALUE_ACCESSOR } from '@angular/forms'; import { takeUntil } from 'rxjs/operators'; import { PlatformUtil } from 'igniteui-angular/core'; import { IgxTextSelectionDirective, IgxForOfDirective, IgxButtonDirective, IgxRippleDirective } from 'igniteui-angular/directives'; import { IgxIconComponent } from 'igniteui-angular/icon'; import * as i2 from 'igniteui-angular/combo'; import { IgxComboBaseDirective, IgxComboDropDownComponent, IgxComboItemComponent, IgxComboAddItemComponent, IgxComboFilteringPipe, IgxComboGroupingPipe, IgxComboAPIService, IGX_COMBO_COMPONENT, IgxComboAddItemDirective, IgxComboClearIconDirective, IgxComboEmptyDirective, IgxComboFooterDirective, IgxComboHeaderDirective, IgxComboHeaderItemDirective, IgxComboItemDirective, IgxComboToggleIconDirective } from 'igniteui-angular/combo'; import { IgxDropDownItemNavigationDirective } from 'igniteui-angular/drop-down'; /** * Represents a drop-down list that provides filtering functionality, allowing users to choose a single option from a predefined list. * * @igxModule IgxSimpleComboModule * @igxTheme igx-combo-theme * @igxKeywords combobox, single combo selection * @igxGroup Grids & Lists * * @remarks * It provides the ability to filter items as well as perform single selection on the provided data. * Additionally, it exposes keyboard navigation and custom styling capabilities. * @example * ```html * <igx-simple-combo [itemsMaxHeight]="250" [data]="locationData" * [displayKey]="'field'" [valueKey]="'field'" * placeholder="Location" searchPlaceholder="Search..."> * </igx-simple-combo> * ``` */ class IgxSimpleComboComponent extends IgxComboBaseDirective { get value() { return this._value[0]; } /** * Get current selection state * * @returns The selected item, if any * ```typescript * let mySelection = this.combo.selection; * ``` */ get selection() { return super.selection[0]; } /** @hidden @internal */ get filteredData() { return this._filteredData; } /** @hidden @internal */ set filteredData(val) { this._filteredData = this.groupKey ? (val || []).filter((e) => e.isHeader !== true) : val; this.checkMatch(); } /** @hidden @internal */ get searchValue() { return this._searchValue; } set searchValue(val) { this._searchValue = val; } get selectedItem() { return this.selectionService.get(this.id).values().next().value; } get hasSelectedItem() { return !!this.selectionService.get(this.id).size; } constructor() { super(); this.platformUtil = inject(PlatformUtil); this.formGroupDirective = inject(FormGroupDirective, { optional: true }); /** * Emitted when item selection is changing, before the selection completes * * ```html * <igx-simple-combo (selectionChanging)='handleSelection()'></igx-simple-combo> * ``` */ this.selectionChanging = new EventEmitter(); /** @hidden @internal */ this.composing = false; this._updateInput = true; this._collapsing = false; this.findAllMatches = (element) => { const value = this.displayKey ? element[this.displayKey] : element; if (value === null || value === undefined || value === '') { // we can accept null, undefined and empty strings as empty display values return true; } const searchValue = this.searchValue || this.comboInput.value; return !!searchValue && value.toString().toLowerCase().includes(searchValue.toLowerCase()); }; this.comboAPI.register(this); } /** @hidden @internal */ onArrowDown(event) { if (this.collapsed) { event.preventDefault(); event.stopPropagation(); this.open(); } else { if (this.virtDir.igxForOf.length > 0 && !this.hasSelectedItem) { this.dropdown.navigateNext(); this.dropdownContainer.nativeElement.focus(); } else if (this.allowCustomValues) { this.addItem?.element.nativeElement.focus(); } } } /** * Select a defined item * * @param item the item to be selected * ```typescript * this.combo.select("New York"); * ``` */ select(item) { if (item !== undefined) { const newSelection = this.selectionService.add_items(this.id, item instanceof Array ? item : [item], true); this.setSelection(newSelection); } } /** * Deselect the currently selected item * * @param item the items to be deselected * ```typescript * this.combo.deselect("New York"); * ``` */ deselect() { this.clearSelection(); } /** @hidden @internal */ writeValue(value) { const oldSelection = super.selection; this.selectionService.select_items(this.id, this.isValid(value) ? [value] : [], true); this.cdr.markForCheck(); this._displayValue = this.createDisplayText(super.selection, oldSelection); this._value = this.valueKey ? super.selection.map(item => item[this.valueKey]) : super.selection; this.filterValue = this._displayValue?.toString() || ''; } /** @hidden @internal */ ngAfterViewInit() { this.virtDir.contentSizeChange.pipe(takeUntil(this.destroy$)).subscribe(() => { if (super.selection.length > 0) { const index = this.virtDir.igxForOf.findIndex(e => { let current = e ? e[this.valueKey] : undefined; if (this.valueKey === null || this.valueKey === undefined) { current = e; } return current === super.selection[0]; }); if (!this.isRemote) { // navigate to item only if we have local data // as with remote data this will fiddle with igxFor's scroll handler // and will trigger another chunk load which will break the visualization this.dropdown.navigateItem(index); } } }); this.dropdown.opening.pipe(takeUntil(this.destroy$)).subscribe((args) => { if (args.cancel) { return; } this._collapsing = false; const filtered = this.filteredData.find(this.findAllMatches); if (filtered === undefined || filtered === null) { this.filterValue = this.searchValue = this.comboInput.value; return; } }); this.dropdown.opened.pipe(takeUntil(this.destroy$)).subscribe(() => { if (this.composing) { this.comboInput.focus(); } }); this.dropdown.closing.pipe(takeUntil(this.destroy$)).subscribe((args) => { if (args.cancel) { return; } if (this.getEditElement() && !args.event) { this._collapsing = true; } else { this.clearOnBlur(); this._onTouchedCallback(); } this.comboInput.focus(); }); // in reactive form the control is not present initially // and sets the selection to an invalid value in writeValue method if (!this.isValid(this.selectedItem)) { this.selectionService.clear(this.id); this._displayValue = ''; } super.ngAfterViewInit(); } /** @hidden @internal */ ngDoCheck() { if (this.data?.length && super.selection.length && !this._displayValue) { this._displayValue = this.createDisplayText(super.selection, []); this._value = this.valueKey ? super.selection.map(item => item[this.valueKey]) : super.selection; } } /** @hidden @internal */ handleInputChange(event) { if (this.collapsed && this.comboInput.focused) { this.open(); } if (event !== undefined) { this.filterValue = this.searchValue = typeof event === 'string' ? event : event.target.value; } if (!this.comboInput.value.trim() && super.selection.length) { // handle clearing of input by space this.clearSelection(); this._onChangeCallback(null); this.filterValue = ''; } if (super.selection.length) { const args = { newValue: undefined, oldValue: this.selectedItem, newSelection: undefined, oldSelection: this.selection, displayText: typeof event === 'string' ? event : event?.target?.value, owner: this, cancel: false }; this.selectionChanging.emit(args); if (!args.cancel) { this.selectionService.select_items(this.id, [], true); } } // when filtering the focused item should be the first item or the currently selected item if (!this.dropdown.focusedItem || this.dropdown.focusedItem.id !== this.dropdown.items[0].id) { this.dropdown.navigateFirst(); } super.handleInputChange(event); this.composing = true; } /** @hidden @internal */ handleInputClick() { if (this.collapsed) { this.open(); this.comboInput.focus(); } } /** @hidden @internal */ handleKeyDown(event) { if (event.key === this.platformUtil.KEYMAP.ENTER) { const filtered = this.filteredData.find(this.findAllMatches); if (filtered === null || filtered === undefined) { return; } if (!this.dropdown.collapsed) { const focusedItem = this.dropdown.focusedItem; if (focusedItem && !focusedItem.isHeader) { this.select(focusedItem.itemID); event.preventDefault(); event.stopPropagation(); this.close(); } else { event.preventDefault(); event.stopPropagation(); this.comboInput.focus(); } } // manually trigger text selection as it will not be triggered during editing this.textSelection.trigger(); return; } if (event.key === this.platformUtil.KEYMAP.BACKSPACE || event.key === this.platformUtil.KEYMAP.DELETE) { this._updateInput = false; this.clearSelection(true); } if (!this.collapsed && event.key === this.platformUtil.KEYMAP.TAB) { const filtered = this.filteredData.find(this.findAllMatches); if (filtered === null || filtered === undefined) { this.clearOnBlur(); this.close(); return; } const focusedItem = this.dropdown.focusedItem; if (focusedItem && !focusedItem.isHeader) { this.select(focusedItem.itemID); this.close(); this.textSelection.trigger(); } else { this.clearOnBlur(); this.close(); } } this.composing = false; super.handleKeyDown(event); } /** @hidden @internal */ handleKeyUp(event) { if (event.key === this.platformUtil.KEYMAP.ARROW_DOWN) { this.dropdown.focusedItem = this.hasSelectedItem && this.filteredData.length > 0 ? this.dropdown.items.find(i => i.itemID === this.selectedItem) : this.dropdown.items[0]; this.dropdownContainer.nativeElement.focus(); } } /** @hidden @internal */ handleItemKeyDown(event) { if (event.key === this.platformUtil.KEYMAP.ARROW_UP && event.altKey) { this.close(); this.comboInput.focus(); return; } if (event.key === this.platformUtil.KEYMAP.ENTER) { this.comboInput.focus(); } } /** @hidden @internal */ handleItemClick() { this.close(); this.comboInput.focus(); } /** @hidden @internal */ onBlur() { // when clicking the toggle button to close the combo and immediately clicking outside of it // the collapsed state is not modified as the dropdown is still not closed if (this.collapsed || this._collapsing) { this.clearOnBlur(); } super.onBlur(); } /** @hidden @internal */ getEditElement() { return this.comboInput.nativeElement; } /** @hidden @internal */ clearInput(event) { const oldSelection = this.selection; this.clearSelection(true); if (!this.collapsed) { this.focusSearchInput(true); } event.stopPropagation(); if (this.selection !== oldSelection) { this.comboInput.value = this.filterValue = this.searchValue = ''; } this.dropdown.focusedItem = null; this.composing = false; this.comboInput.focus(); } /** @hidden @internal */ handleClear(event) { if (this.disabled) { return; } this.clearInput(event); } /** @hidden @internal */ handleClearKeyDown(event) { if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); this.clearInput(event); } } /** @hidden @internal */ handleOpened() { this.triggerCheck(); if (!this.comboInput.focused) { this.dropdownContainer.nativeElement.focus(); } this.opened.emit({ owner: this }); } /** @hidden @internal */ handleClosing(e) { const args = { owner: this, event: e.event, cancel: e.cancel }; this.closing.emit(args); e.cancel = args.cancel; if (e.cancel) { return; } this.composing = false; // explicitly update selection so that we don't have to force CD this.textSelection.selected = true; } /** @hidden @internal */ focusSearchInput(opening) { if (opening) { this.dropdownContainer.nativeElement.focus(); } else { this.comboInput.nativeElement.focus(); } } /** @hidden @internal */ onClick(event) { super.onClick(event); if (this.comboInput.value.length === 0) { this.virtDir.scrollTo(0); } } setSelection(newSelection) { const newValueAsArray = newSelection ? Array.from(newSelection) : []; const oldValueAsArray = Array.from(this.selectionService.get(this.id) || []); const newItems = this.convertKeysToItems(newValueAsArray); const oldItems = this.convertKeysToItems(oldValueAsArray); const displayText = this.createDisplayText(this.convertKeysToItems(newValueAsArray), oldValueAsArray); const args = { newValue: newValueAsArray[0], oldValue: oldValueAsArray[0], newSelection: newItems[0], oldSelection: oldItems[0], displayText, owner: this, cancel: false }; if (args.newSelection !== args.oldSelection) { this.selectionChanging.emit(args); } // TODO: refactor below code as it sets the selection and the display text if (!args.cancel) { let argsSelection = this.isValid(args.newValue) ? args.newValue : []; argsSelection = Array.isArray(argsSelection) ? argsSelection : [argsSelection]; this.selectionService.select_items(this.id, argsSelection, true); this._value = argsSelection; if (this._updateInput) { this.comboInput.value = this._displayValue = this.searchValue = displayText !== args.displayText ? args.displayText : this.createDisplayText(super.selection, [args.oldValue]); } this._onChangeCallback(args.newValue); this._updateInput = true; } else if (this.isRemote) { this.registerRemoteEntries(newValueAsArray, false); } else { args.displayText = this.createDisplayText(oldItems, []); const oldSelectionArray = args.oldSelection ? [args.oldSelection] : []; this.comboInput.value = this._displayValue = this.searchValue = this.createDisplayText(oldSelectionArray, []); if (this.isRemote) { this.registerRemoteEntries(newValueAsArray, false); } } } createDisplayText(newSelection, oldSelection) { if (this.isRemote) { const selection = this.valueKey ? newSelection.map(item => item[this.valueKey]) : newSelection; return this.getRemoteSelection(selection, oldSelection); } if (this.displayKey !== null && this.displayKey !== undefined && newSelection.length > 0) { return newSelection.filter(e => e).map(e => e[this.displayKey])[0]?.toString() || ''; } return newSelection[0]?.toString() || ''; } getRemoteSelection(newSelection, oldSelection) { if (!newSelection.length) { this.registerRemoteEntries(oldSelection, false); return ''; } this.registerRemoteEntries(oldSelection, false); this.registerRemoteEntries(newSelection); return Object.keys(this._remoteSelection).map(e => this._remoteSelection[e])[0] || ''; } /** Contains key-value pairs of the selected valueKeys and their resp. displayKeys */ registerRemoteEntries(ids, add = true) { const selection = this.getValueDisplayPairs(ids)[0]; if (add && selection) { this._remoteSelection[selection[this.valueKey]] = selection[this.displayKey].toString(); } else { this._remoteSelection = {}; } } clearSelection(ignoreFilter) { let newSelection = this.selectionService.get_empty(); if (this.filteredData.length !== this.data.length && !ignoreFilter) { newSelection = this.selectionService.delete_items(this.id, this.selectionService.get_all_ids(this.filteredData, this.valueKey)); } if (this.selectionService.get(this.id).size > 0 || this.comboInput.value.trim()) { this.setSelection(newSelection); } } clearOnBlur() { if (this.isRemote) { const searchValue = this.searchValue || this.comboInput.value; const remoteValue = Object.keys(this._remoteSelection).map(e => this._remoteSelection[e])[0] || ''; if (searchValue !== remoteValue) { this.clear(); } return; } const filtered = this.filteredData.find(this.findMatch); // selecting null in primitive data returns undefined as the search text is '', but the item is null if (filtered === undefined && this.selectedItem !== null || !super.selection.length) { this.clear(); } } getElementVal(element) { const elementVal = this.displayKey ? element[this.displayKey] : element; return String(elementVal); } clear() { this.clearSelection(true); const oldSelection = this.selection; if (this.selection !== oldSelection) { this.comboInput.value = this._displayValue = this.searchValue = ''; } } isValid(value) { if (this.formGroupDirective && value === null) { return false; } if (this.required) { return value !== null && value !== '' && value !== undefined; } return value !== undefined; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxSimpleComboComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.2", type: IgxSimpleComboComponent, isStandalone: true, selector: "igx-simple-combo", outputs: { selectionChanging: "selectionChanging" }, host: { listeners: { "keydown.ArrowDown": "onArrowDown($event)", "keydown.Alt.ArrowDown": "onArrowDown($event)" } }, providers: [ IgxComboAPIService, { provide: IGX_COMBO_COMPONENT, useExisting: IgxSimpleComboComponent }, { provide: NG_VALUE_ACCESSOR, useExisting: IgxSimpleComboComponent, multi: true } ], viewQueries: [{ propertyName: "dropdown", first: true, predicate: IgxComboDropDownComponent, descendants: true, static: true }, { propertyName: "addItem", first: true, predicate: IgxComboAddItemComponent, descendants: true }, { propertyName: "textSelection", first: true, predicate: IgxTextSelectionDirective, descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<igx-input-group #inputGroup [type]=\"type\">\n\n <ng-container ngProjectAs=\"[igxLabel]\">\n <ng-content select=\"[igxLabel]\"></ng-content>\n </ng-container>\n\n <ng-container ngProjectAs=\"igx-prefix\">\n <ng-content select=\"igx-prefix,[igxPrefix]\"></ng-content>\n </ng-container>\n\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]=\"displayValue\" role=\"combobox\"\n aria-haspopup=\"listbox\" aria-autocomplete=\"list\" aria-readonly=\"false\"\n [attr.aria-expanded]=\"!this.dropdown.collapsed\" [attr.aria-controls]=\"this.dropdown.listId\"\n [attr.aria-labelledby]=\"this.ariaLabelledBy || this.label?.id || this.placeholder\"\n [attr.placeholder]=\"placeholder\" [disabled]=\"disabled\" [igxTextSelection]=\"!composing\"\n [attr.aria-label]=\"getAriaLabel()\"\n (input)=\"handleInputChange($event)\" (click)=\"handleInputClick()\"\n (keyup)=\"handleKeyUp($event)\" (keydown)=\"handleKeyDown($event)\" (blur)=\"onBlur()\" (paste)=\"handleInputChange($event)\"/>\n\n <ng-container ngProjectAs=\"igx-suffix\">\n <ng-content select=\"igx-suffix,[igxSuffix]\"></ng-content>\n </ng-container>\n\n @if (hasSelectedItem) {\n <igx-suffix [attr.aria-label]=\"resourceStrings.igx_combo_clearItems_placeholder\" class=\"igx-combo__clear-button\"\n (click)=\"handleClear($event)\" (keydown)=\"handleClearKeyDown($event)\" [tabindex]=\"disabled ? -1 : 0\" role=\"button\">\n @if (clearIconTemplate) {\n <ng-container *ngTemplateOutlet=\"clearIconTemplate\"></ng-container>\n }\n @if (!clearIconTemplate) {\n <igx-icon family=\"default\" name=\"input_clear\"></igx-icon>\n }\n </igx-suffix>\n }\n\n @if (showSearchCaseIcon) {\n <igx-suffix>\n <igx-icon family=\"default\" name=\"case_sensitive\" [active]=\"filteringOptions.caseSensitive\"\n (click)=\"toggleCaseSensitive()\">\n </igx-icon>\n </igx-suffix>\n }\n\n <igx-suffix class=\"igx-combo__toggle-button\" (click)=\"onClick($event)\" (keydown)=\"handleToggleKeyDown($event)\"\n [tabindex]=\"disabled ? -1 : 0\" role=\"button\">\n @if (toggleIconTemplate) {\n <ng-container *ngTemplateOutlet=\"toggleIconTemplate; context: {$implicit: collapsed}\"></ng-container>\n }\n @if (!toggleIconTemplate) {\n <igx-icon family=\"default\" [name]=\"toggleIcon\"></igx-icon>\n }\n </igx-suffix>\n\n</igx-input-group>\n\n<igx-combo-drop-down #igxComboDropDown class=\"igx-combo__drop-down\"\n [labelledBy]=\"this.ariaLabelledBy || this.label?.id || this.placeholder || ''\"\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.rem]=\"itemsMaxHeightInRem\" [igxDropDownItemNavigation]=\"dropdown\"\n [tabindex]=\"dropdown.collapsed ? -1 : 0\" [attr.id]=\"dropdown.id\"\n [attr.aria-activedescendant]=\"this.activeDescendant\"\n (focus)=\"dropdown.onFocus()\" (keydown)=\"handleItemKeyDown($event)\">\n <igx-combo-item [role]=\"item?.isHeader? 'group' : 'option'\" [singleMode]=\"true\"\n [itemHeight]=\"itemHeight\" (click)=\"handleItemClick()\" *igxFor=\"let item of data\n | comboFiltering:filterValue:displayKey:filteringOptions:filterFunction:disableFiltering\n | comboGrouping:groupKey:valueKey:groupSortingDirection:compareCollator;\n index as rowIndex; initialChunkSize: 10; containerSize: itemsMaxHeight || containerSize; itemSize: itemHeight || itemSize; scrollOrientation: 'vertical';\"\n [value]=\"item\" [isHeader]=\"item?.isHeader\" [index]=\"rowIndex\">\n @if (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 }\n <!-- if item is 'null' it should be displayed and !!(item?.isHeader) would resolve it to 'false' and not display it -->\n @if (!item?.isHeader) {\n <ng-container #listItem\n *ngTemplateOutlet=\"template; context: {$implicit: item, data: data, valueKey: valueKey, displayKey: displayKey};\">\n </ng-container>\n }\n </igx-combo-item>\n </div>\n\n @if (filteredData.length === 0 || isAddButtonVisible()) {\n <div class=\"igx-combo__add\">\n @if (filteredData.length === 0) {\n <div class=\"igx-combo__empty\">\n <ng-container *ngTemplateOutlet=\"emptyTemplate ? emptyTemplate : empty\">\n </ng-container>\n </div>\n }\n @if (isAddButtonVisible()) {\n <igx-combo-add-item #addItem [itemHeight]=\"itemHeight\"\n [tabindex]=\"dropdown.collapsed ? -1 : customValueFlag ? 1 : -1\" class=\"igx-combo__add-item\" role=\"button\"\n [attr.aria-label]=\"resourceStrings.igx_combo_addCustomValues_placeholder\" [index]=\"virtualScrollContainer.igxForOf.length\">\n <ng-container *ngTemplateOutlet=\"addItemTemplate ? addItemTemplate : addItemDefault\">\n </ng-container>\n </igx-combo-add-item>\n }\n </div>\n }\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 type=\"button\" igxButton=\"flat\" igxRipple>{{ resourceStrings.igx_combo_addCustomValues_placeholder }}</button>\n</ng-template>\n<ng-template #headerItemBase let-item let-key=\"valueKey\" let-groupKey=\"groupKey\">\n {{ item[key] }}\n</ng-template>\n", dependencies: [{ kind: "component", type: IgxInputGroupComponent, selector: "igx-input-group", inputs: ["resourceStrings", "suppressInputAutofocus", "type", "theme"] }, { kind: "directive", type: IgxInputDirective, selector: "[igxInput]", inputs: ["value", "disabled", "required"], exportAs: ["igxInput"] }, { kind: "directive", type: IgxTextSelectionDirective, selector: "[igxTextSelection]", inputs: ["igxTextSelection"], exportAs: ["igxTextSelection"] }, { kind: "directive", type: IgxSuffixDirective, selector: "igx-suffix,[igxSuffix],[igxEnd]" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: IgxIconComponent, selector: "igx-icon", inputs: ["ariaHidden", "family", "name", "active"] }, { kind: "component", type: IgxComboDropDownComponent, selector: "igx-combo-drop-down", inputs: ["singleMode"] }, { kind: "directive", type: IgxDropDownItemNavigationDirective, selector: "[igxDropDownItemNavigation]", inputs: ["igxDropDownItemNavigation"] }, { kind: "directive", type: IgxForOfDirective, selector: "[igxFor][igxForOf]", inputs: ["igxForOf", "igxForSizePropName", "igxForScrollOrientation", "igxForScrollContainer", "igxForContainerSize", "igxForInitialChunkSize", "igxForItemSize", "igxForTotalItemCount", "igxForTrackBy"], outputs: ["chunkLoad", "scrollbarVisibilityChanged", "contentSizeChange", "dataChanged", "beforeViewDestroyed", "chunkPreload"] }, { kind: "component", type: IgxComboItemComponent, selector: "igx-combo-item", inputs: ["itemHeight", "ariaLabel", "singleMode"] }, { kind: "component", type: IgxComboAddItemComponent, selector: "igx-combo-add-item" }, { kind: "directive", type: IgxButtonDirective, selector: "[igxButton]", inputs: ["selected", "igxButton", "igxLabel"], outputs: ["buttonSelected"] }, { kind: "directive", type: IgxRippleDirective, selector: "[igxRipple]", inputs: ["igxRippleTarget", "igxRipple", "igxRippleDuration", "igxRippleCentered", "igxRippleDisabled"] }, { kind: "pipe", type: IgxComboFilteringPipe, name: "comboFiltering" }, { kind: "pipe", type: IgxComboGroupingPipe, name: "comboGrouping" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxSimpleComboComponent, decorators: [{ type: Component, args: [{ selector: 'igx-simple-combo', providers: [ IgxComboAPIService, { provide: IGX_COMBO_COMPONENT, useExisting: IgxSimpleComboComponent }, { provide: NG_VALUE_ACCESSOR, useExisting: IgxSimpleComboComponent, multi: true } ], imports: [IgxInputGroupComponent, IgxInputDirective, IgxTextSelectionDirective, IgxSuffixDirective, NgTemplateOutlet, IgxIconComponent, IgxComboDropDownComponent, IgxDropDownItemNavigationDirective, IgxForOfDirective, IgxComboItemComponent, IgxComboAddItemComponent, IgxButtonDirective, IgxRippleDirective, IgxComboFilteringPipe, IgxComboGroupingPipe], template: "<igx-input-group #inputGroup [type]=\"type\">\n\n <ng-container ngProjectAs=\"[igxLabel]\">\n <ng-content select=\"[igxLabel]\"></ng-content>\n </ng-container>\n\n <ng-container ngProjectAs=\"igx-prefix\">\n <ng-content select=\"igx-prefix,[igxPrefix]\"></ng-content>\n </ng-container>\n\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]=\"displayValue\" role=\"combobox\"\n aria-haspopup=\"listbox\" aria-autocomplete=\"list\" aria-readonly=\"false\"\n [attr.aria-expanded]=\"!this.dropdown.collapsed\" [attr.aria-controls]=\"this.dropdown.listId\"\n [attr.aria-labelledby]=\"this.ariaLabelledBy || this.label?.id || this.placeholder\"\n [attr.placeholder]=\"placeholder\" [disabled]=\"disabled\" [igxTextSelection]=\"!composing\"\n [attr.aria-label]=\"getAriaLabel()\"\n (input)=\"handleInputChange($event)\" (click)=\"handleInputClick()\"\n (keyup)=\"handleKeyUp($event)\" (keydown)=\"handleKeyDown($event)\" (blur)=\"onBlur()\" (paste)=\"handleInputChange($event)\"/>\n\n <ng-container ngProjectAs=\"igx-suffix\">\n <ng-content select=\"igx-suffix,[igxSuffix]\"></ng-content>\n </ng-container>\n\n @if (hasSelectedItem) {\n <igx-suffix [attr.aria-label]=\"resourceStrings.igx_combo_clearItems_placeholder\" class=\"igx-combo__clear-button\"\n (click)=\"handleClear($event)\" (keydown)=\"handleClearKeyDown($event)\" [tabindex]=\"disabled ? -1 : 0\" role=\"button\">\n @if (clearIconTemplate) {\n <ng-container *ngTemplateOutlet=\"clearIconTemplate\"></ng-container>\n }\n @if (!clearIconTemplate) {\n <igx-icon family=\"default\" name=\"input_clear\"></igx-icon>\n }\n </igx-suffix>\n }\n\n @if (showSearchCaseIcon) {\n <igx-suffix>\n <igx-icon family=\"default\" name=\"case_sensitive\" [active]=\"filteringOptions.caseSensitive\"\n (click)=\"toggleCaseSensitive()\">\n </igx-icon>\n </igx-suffix>\n }\n\n <igx-suffix class=\"igx-combo__toggle-button\" (click)=\"onClick($event)\" (keydown)=\"handleToggleKeyDown($event)\"\n [tabindex]=\"disabled ? -1 : 0\" role=\"button\">\n @if (toggleIconTemplate) {\n <ng-container *ngTemplateOutlet=\"toggleIconTemplate; context: {$implicit: collapsed}\"></ng-container>\n }\n @if (!toggleIconTemplate) {\n <igx-icon family=\"default\" [name]=\"toggleIcon\"></igx-icon>\n }\n </igx-suffix>\n\n</igx-input-group>\n\n<igx-combo-drop-down #igxComboDropDown class=\"igx-combo__drop-down\"\n [labelledBy]=\"this.ariaLabelledBy || this.label?.id || this.placeholder || ''\"\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.rem]=\"itemsMaxHeightInRem\" [igxDropDownItemNavigation]=\"dropdown\"\n [tabindex]=\"dropdown.collapsed ? -1 : 0\" [attr.id]=\"dropdown.id\"\n [attr.aria-activedescendant]=\"this.activeDescendant\"\n (focus)=\"dropdown.onFocus()\" (keydown)=\"handleItemKeyDown($event)\">\n <igx-combo-item [role]=\"item?.isHeader? 'group' : 'option'\" [singleMode]=\"true\"\n [itemHeight]=\"itemHeight\" (click)=\"handleItemClick()\" *igxFor=\"let item of data\n | comboFiltering:filterValue:displayKey:filteringOptions:filterFunction:disableFiltering\n | comboGrouping:groupKey:valueKey:groupSortingDirection:compareCollator;\n index as rowIndex; initialChunkSize: 10; containerSize: itemsMaxHeight || containerSize; itemSize: itemHeight || itemSize; scrollOrientation: 'vertical';\"\n [value]=\"item\" [isHeader]=\"item?.isHeader\" [index]=\"rowIndex\">\n @if (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 }\n <!-- if item is 'null' it should be displayed and !!(item?.isHeader) would resolve it to 'false' and not display it -->\n @if (!item?.isHeader) {\n <ng-container #listItem\n *ngTemplateOutlet=\"template; context: {$implicit: item, data: data, valueKey: valueKey, displayKey: displayKey};\">\n </ng-container>\n }\n </igx-combo-item>\n </div>\n\n @if (filteredData.length === 0 || isAddButtonVisible()) {\n <div class=\"igx-combo__add\">\n @if (filteredData.length === 0) {\n <div class=\"igx-combo__empty\">\n <ng-container *ngTemplateOutlet=\"emptyTemplate ? emptyTemplate : empty\">\n </ng-container>\n </div>\n }\n @if (isAddButtonVisible()) {\n <igx-combo-add-item #addItem [itemHeight]=\"itemHeight\"\n [tabindex]=\"dropdown.collapsed ? -1 : customValueFlag ? 1 : -1\" class=\"igx-combo__add-item\" role=\"button\"\n [attr.aria-label]=\"resourceStrings.igx_combo_addCustomValues_placeholder\" [index]=\"virtualScrollContainer.igxForOf.length\">\n <ng-container *ngTemplateOutlet=\"addItemTemplate ? addItemTemplate : addItemDefault\">\n </ng-container>\n </igx-combo-add-item>\n }\n </div>\n }\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 type=\"button\" igxButton=\"flat\" igxRipple>{{ resourceStrings.igx_combo_addCustomValues_placeholder }}</button>\n</ng-template>\n<ng-template #headerItemBase let-item let-key=\"valueKey\" let-groupKey=\"groupKey\">\n {{ item[key] }}\n</ng-template>\n" }] }], ctorParameters: () => [], propDecorators: { dropdown: [{ type: ViewChild, args: [IgxComboDropDownComponent, { static: true }] }], addItem: [{ type: ViewChild, args: [IgxComboAddItemComponent] }], selectionChanging: [{ type: Output }], textSelection: [{ type: ViewChild, args: [IgxTextSelectionDirective, { static: true }] }], onArrowDown: [{ type: HostListener, args: ['keydown.ArrowDown', ['$event']] }, { type: HostListener, args: ['keydown.Alt.ArrowDown', ['$event']] }] } }); /* NOTE: Simple combo directives collection for ease-of-use import in standalone components scenario */ const IGX_SIMPLE_COMBO_DIRECTIVES = [ IgxSimpleComboComponent, IgxComboAddItemDirective, IgxComboClearIconDirective, IgxComboEmptyDirective, IgxComboFooterDirective, IgxComboHeaderDirective, IgxComboHeaderItemDirective, IgxComboItemDirective, IgxComboToggleIconDirective, IgxLabelDirective, IgxPrefixDirective, IgxSuffixDirective, IgxHintDirective ]; /** * @hidden * IMPORTANT: The following is NgModule exported for backwards-compatibility before standalone components */ class IgxSimpleComboModule { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxSimpleComboModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.0.2", ngImport: i0, type: IgxSimpleComboModule, imports: [IgxSimpleComboComponent, i2.IgxComboAddItemDirective, i2.IgxComboClearIconDirective, i2.IgxComboEmptyDirective, i2.IgxComboFooterDirective, i2.IgxComboHeaderDirective, i2.IgxComboHeaderItemDirective, i2.IgxComboItemDirective, i2.IgxComboToggleIconDirective, i3.IgxLabelDirective, i3.IgxPrefixDirective, i3.IgxSuffixDirective, i3.IgxHintDirective], exports: [IgxSimpleComboComponent, i2.IgxComboAddItemDirective, i2.IgxComboClearIconDirective, i2.IgxComboEmptyDirective, i2.IgxComboFooterDirective, i2.IgxComboHeaderDirective, i2.IgxComboHeaderItemDirective, i2.IgxComboItemDirective, i2.IgxComboToggleIconDirective, i3.IgxLabelDirective, i3.IgxPrefixDirective, i3.IgxSuffixDirective, i3.IgxHintDirective] }); } static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxSimpleComboModule, imports: [IgxSimpleComboComponent] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxSimpleComboModule, decorators: [{ type: NgModule, args: [{ imports: [ ...IGX_SIMPLE_COMBO_DIRECTIVES ], exports: [ ...IGX_SIMPLE_COMBO_DIRECTIVES ] }] }] }); /** * Generated bundle index. Do not edit. */ export { IGX_SIMPLE_COMBO_DIRECTIVES, IgxSimpleComboComponent, IgxSimpleComboModule }; //# sourceMappingURL=igniteui-angular-simple-combo.mjs.map