UNPKG

@ng-select/ng-select

Version:

Angular ng-select - All in One UI Select, Multiselect and Autocomplete

1,420 lines 143 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import * as tslib_1 from "tslib"; import { Component, forwardRef, ChangeDetectorRef, Input, Output, EventEmitter, ContentChild, TemplateRef, ViewEncapsulation, HostListener, HostBinding, ViewChild, ElementRef, ChangeDetectionStrategy, Inject, ContentChildren, QueryList, InjectionToken, Attribute } from '@angular/core'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { takeUntil, startWith, tap, debounceTime, map, filter } from 'rxjs/operators'; import { Subject, merge } from 'rxjs'; import { NgOptionTemplateDirective, NgLabelTemplateDirective, NgHeaderTemplateDirective, NgFooterTemplateDirective, NgOptgroupTemplateDirective, NgNotFoundTemplateDirective, NgTypeToSearchTemplateDirective, NgLoadingTextTemplateDirective, NgMultiLabelTemplateDirective, NgTagTemplateDirective, NgLoadingSpinnerTemplateDirective } from './ng-templates.directive'; import { ConsoleService } from './console.service'; import { isDefined, isFunction, isPromise, isObject } from './value-utils'; import { ItemsList } from './items-list'; import { KeyCode } from './ng-select.types'; import { newId } from './id'; import { NgDropdownPanelComponent } from './ng-dropdown-panel.component'; import { NgOptionComponent } from './ng-option.component'; import { NgSelectConfig } from './config.service'; import { NgDropdownPanelService } from './ng-dropdown-panel.service'; /** @type {?} */ export var SELECTION_MODEL_FACTORY = new InjectionToken('ng-select-selection-model'); var NgSelectComponent = /** @class */ (function () { function NgSelectComponent(classes, autoFocus, config, newSelectionModel, _elementRef, _cd, _console) { var _this = this; this.classes = classes; this.autoFocus = autoFocus; this._cd = _cd; this._console = _console; this.markFirst = true; this.dropdownPosition = 'auto'; this.loading = false; this.closeOnSelect = true; this.hideSelected = false; this.selectOnTab = false; this.bufferAmount = 4; this.selectableGroup = false; this.selectableGroupAsModel = true; this.searchFn = null; this.trackByFn = null; this.clearOnBackspace = true; this.labelForId = null; this.inputAttrs = {}; this.readonly = false; this.searchWhileComposing = true; this.minTermLength = 0; this.keyDownFn = (/** * @param {?} _ * @return {?} */ function (_) { return true; }); this.multiple = false; this.addTag = false; this.searchable = true; this.clearable = true; this.isOpen = false; // output events this.blurEvent = new EventEmitter(); this.focusEvent = new EventEmitter(); this.changeEvent = new EventEmitter(); this.openEvent = new EventEmitter(); this.closeEvent = new EventEmitter(); this.searchEvent = new EventEmitter(); this.clearEvent = new EventEmitter(); this.addEvent = new EventEmitter(); this.removeEvent = new EventEmitter(); this.scroll = new EventEmitter(); this.scrollToEnd = new EventEmitter(); this.viewPortItems = []; this.searchTerm = null; this.dropdownId = newId(); this.escapeHTML = true; this._items = []; this._defaultLabel = 'label'; this._pressedKeys = []; this._isComposing = false; this._destroy$ = new Subject(); this._keyPress$ = new Subject(); this._onChange = (/** * @param {?} _ * @return {?} */ function (_) { }); this._onTouched = (/** * @return {?} */ function () { }); this.clearItem = (/** * @param {?} item * @return {?} */ function (item) { /** @type {?} */ var option = _this.selectedItems.find((/** * @param {?} x * @return {?} */ function (x) { return x.value === item; })); _this.unselect(option); }); this.trackByOption = (/** * @param {?} _ * @param {?} item * @return {?} */ function (_, item) { if (_this.trackByFn) { return _this.trackByFn(item.value); } return item; }); this._mergeGlobalConfig(config); this.itemsList = new ItemsList(this, newSelectionModel()); this.element = _elementRef.nativeElement; } Object.defineProperty(NgSelectComponent.prototype, "items", { get: /** * @return {?} */ function () { return this._items; }, set: /** * @param {?} value * @return {?} */ function (value) { this._itemsAreUsed = true; this._items = value; }, enumerable: true, configurable: true }); ; ; Object.defineProperty(NgSelectComponent.prototype, "compareWith", { get: /** * @return {?} */ function () { return this._compareWith; }, set: /** * @param {?} fn * @return {?} */ function (fn) { if (!isFunction(fn)) { throw Error('`compareWith` must be a function.'); } this._compareWith = fn; }, enumerable: true, configurable: true }); Object.defineProperty(NgSelectComponent.prototype, "clearSearchOnAdd", { get: /** * @return {?} */ function () { return isDefined(this._clearSearchOnAdd) ? this._clearSearchOnAdd : this.closeOnSelect; }, set: /** * @param {?} value * @return {?} */ function (value) { this._clearSearchOnAdd = value; }, enumerable: true, configurable: true }); ; ; Object.defineProperty(NgSelectComponent.prototype, "disabled", { get: /** * @return {?} */ function () { return this.readonly || this._disabled; }, enumerable: true, configurable: true }); ; Object.defineProperty(NgSelectComponent.prototype, "filtered", { get: /** * @return {?} */ function () { return (!!this.searchTerm && this.searchable || this._isComposing); }, enumerable: true, configurable: true }); ; Object.defineProperty(NgSelectComponent.prototype, "selectedItems", { get: /** * @return {?} */ function () { return this.itemsList.selectedItems; }, enumerable: true, configurable: true }); Object.defineProperty(NgSelectComponent.prototype, "selectedValues", { get: /** * @return {?} */ function () { return this.selectedItems.map((/** * @param {?} x * @return {?} */ function (x) { return x.value; })); }, enumerable: true, configurable: true }); Object.defineProperty(NgSelectComponent.prototype, "hasValue", { get: /** * @return {?} */ function () { return this.selectedItems.length > 0; }, enumerable: true, configurable: true }); Object.defineProperty(NgSelectComponent.prototype, "currentPanelPosition", { get: /** * @return {?} */ function () { if (this.dropdownPanel) { return this.dropdownPanel.currentPosition; } return undefined; }, enumerable: true, configurable: true }); /** * @return {?} */ NgSelectComponent.prototype.ngOnInit = /** * @return {?} */ function () { this._handleKeyPresses(); this._setInputAttributes(); }; /** * @param {?} changes * @return {?} */ NgSelectComponent.prototype.ngOnChanges = /** * @param {?} changes * @return {?} */ function (changes) { if (changes.multiple) { this.itemsList.clearSelected(); } if (changes.items) { this._setItems(changes.items.currentValue || []); } if (changes.isOpen) { this._manualOpen = isDefined(changes.isOpen.currentValue); } }; /** * @return {?} */ NgSelectComponent.prototype.ngAfterViewInit = /** * @return {?} */ function () { if (!this._itemsAreUsed) { this.escapeHTML = false; this._setItemsFromNgOptions(); } if (isDefined(this.autoFocus)) { this.focus(); } }; /** * @return {?} */ NgSelectComponent.prototype.ngOnDestroy = /** * @return {?} */ function () { this._destroy$.next(); this._destroy$.complete(); }; /** * @param {?} $event * @return {?} */ NgSelectComponent.prototype.handleKeyDown = /** * @param {?} $event * @return {?} */ function ($event) { /** @type {?} */ var keyCode = KeyCode[$event.which]; if (keyCode) { if (this.keyDownFn($event) === false) { return; } this.handleKeyCode($event); } else if ($event.key && $event.key.length === 1) { this._keyPress$.next($event.key.toLocaleLowerCase()); } }; /** * @param {?} $event * @return {?} */ NgSelectComponent.prototype.handleKeyCode = /** * @param {?} $event * @return {?} */ function ($event) { switch ($event.which) { case KeyCode.ArrowDown: this._handleArrowDown($event); break; case KeyCode.ArrowUp: this._handleArrowUp($event); break; case KeyCode.Space: this._handleSpace($event); break; case KeyCode.Enter: this._handleEnter($event); break; case KeyCode.Tab: this._handleTab($event); break; case KeyCode.Esc: this.close(); $event.preventDefault(); break; case KeyCode.Backspace: this._handleBackspace(); break; } }; /** * @param {?} $event * @return {?} */ NgSelectComponent.prototype.handleMousedown = /** * @param {?} $event * @return {?} */ function ($event) { /** @type {?} */ var target = (/** @type {?} */ ($event.target)); if (target.tagName !== 'INPUT') { $event.preventDefault(); } if (target.classList.contains('ng-clear-wrapper')) { this.handleClearClick(); return; } if (target.classList.contains('ng-arrow-wrapper')) { this.handleArrowClick(); return; } if (target.classList.contains('ng-value-icon')) { return; } if (!this.focused) { this.focus(); } if (this.searchable) { this.open(); } else { this.toggle(); } }; /** * @return {?} */ NgSelectComponent.prototype.handleArrowClick = /** * @return {?} */ function () { if (this.isOpen) { this.close(); } else { this.open(); } }; /** * @return {?} */ NgSelectComponent.prototype.handleClearClick = /** * @return {?} */ function () { if (this.hasValue) { this.itemsList.clearSelected(true); this._updateNgModel(); } this._clearSearch(); this.focus(); this.clearEvent.emit(); this._onSelectionChanged(); }; /** * @return {?} */ NgSelectComponent.prototype.clearModel = /** * @return {?} */ function () { if (!this.clearable) { return; } this.itemsList.clearSelected(); this._updateNgModel(); }; /** * @param {?} value * @return {?} */ NgSelectComponent.prototype.writeValue = /** * @param {?} value * @return {?} */ function (value) { this.itemsList.clearSelected(); this._handleWriteValue(value); this._cd.markForCheck(); }; /** * @param {?} fn * @return {?} */ NgSelectComponent.prototype.registerOnChange = /** * @param {?} fn * @return {?} */ function (fn) { this._onChange = fn; }; /** * @param {?} fn * @return {?} */ NgSelectComponent.prototype.registerOnTouched = /** * @param {?} fn * @return {?} */ function (fn) { this._onTouched = fn; }; /** * @param {?} state * @return {?} */ NgSelectComponent.prototype.setDisabledState = /** * @param {?} state * @return {?} */ function (state) { this._disabled = state; this._cd.markForCheck(); }; /** * @return {?} */ NgSelectComponent.prototype.toggle = /** * @return {?} */ function () { if (!this.isOpen) { this.open(); } else { this.close(); } }; /** * @return {?} */ NgSelectComponent.prototype.open = /** * @return {?} */ function () { if (this.disabled || this.isOpen || this.itemsList.maxItemsSelected || this._manualOpen) { return; } if (!this._isTypeahead && !this.addTag && this.itemsList.noItemsToSelect) { return; } this.isOpen = true; this.itemsList.markSelectedOrDefault(this.markFirst); this.openEvent.emit(); if (!this.searchTerm) { this.focus(); } this.detectChanges(); }; /** * @return {?} */ NgSelectComponent.prototype.close = /** * @return {?} */ function () { if (!this.isOpen || this._manualOpen) { return; } this.isOpen = false; this._clearSearch(); this.itemsList.unmarkItem(); this._onTouched(); this.closeEvent.emit(); this._cd.markForCheck(); }; /** * @param {?} item * @return {?} */ NgSelectComponent.prototype.toggleItem = /** * @param {?} item * @return {?} */ function (item) { if (!item || item.disabled || this.disabled) { return; } if (this.multiple && item.selected) { this.unselect(item); } else { this.select(item); } this._onSelectionChanged(); }; /** * @param {?} item * @return {?} */ NgSelectComponent.prototype.select = /** * @param {?} item * @return {?} */ function (item) { if (!item.selected) { this.itemsList.select(item); if (this.clearSearchOnAdd) { this._clearSearch(); } this._updateNgModel(); if (this.multiple) { this.addEvent.emit(item.value); } } if (this.closeOnSelect || this.itemsList.noItemsToSelect) { this.close(); } }; /** * @return {?} */ NgSelectComponent.prototype.focus = /** * @return {?} */ function () { this.searchInput.nativeElement.focus(); }; /** * @return {?} */ NgSelectComponent.prototype.blur = /** * @return {?} */ function () { this.searchInput.nativeElement.blur(); }; /** * @param {?} item * @return {?} */ NgSelectComponent.prototype.unselect = /** * @param {?} item * @return {?} */ function (item) { if (!item) { return; } this.itemsList.unselect(item); this.focus(); this._updateNgModel(); this.removeEvent.emit(item); }; /** * @return {?} */ NgSelectComponent.prototype.selectTag = /** * @return {?} */ function () { var _this = this; var _a; /** @type {?} */ var tag; if (isFunction(this.addTag)) { tag = ((/** @type {?} */ (this.addTag)))(this.searchTerm); } else { tag = this._primitive ? this.searchTerm : (_a = {}, _a[this.bindLabel] = this.searchTerm, _a); } /** @type {?} */ var handleTag = (/** * @param {?} item * @return {?} */ function (item) { return _this._isTypeahead || !_this.isOpen ? _this.itemsList.mapItem(item, null) : _this.itemsList.addItem(item); }); if (isPromise(tag)) { tag.then((/** * @param {?} item * @return {?} */ function (item) { return _this.select(handleTag(item)); })).catch((/** * @return {?} */ function () { })); } else if (tag) { this.select(handleTag(tag)); } }; /** * @return {?} */ NgSelectComponent.prototype.showClear = /** * @return {?} */ function () { return this.clearable && (this.hasValue || this.searchTerm) && !this.disabled; }; Object.defineProperty(NgSelectComponent.prototype, "showAddTag", { get: /** * @return {?} */ function () { if (!this._validTerm) { return false; } /** @type {?} */ var term = this.searchTerm.toLowerCase().trim(); return this.addTag && (!this.itemsList.filteredItems.some((/** * @param {?} x * @return {?} */ function (x) { return x.label.toLowerCase() === term; })) && (!this.hideSelected && this.isOpen || !this.selectedItems.some((/** * @param {?} x * @return {?} */ function (x) { return x.label.toLowerCase() === term; })))) && !this.loading; }, enumerable: true, configurable: true }); /** * @return {?} */ NgSelectComponent.prototype.showNoItemsFound = /** * @return {?} */ function () { /** @type {?} */ var empty = this.itemsList.filteredItems.length === 0; return ((empty && !this._isTypeahead && !this.loading) || (empty && this._isTypeahead && this._validTerm && !this.loading)) && !this.showAddTag; }; /** * @return {?} */ NgSelectComponent.prototype.showTypeToSearch = /** * @return {?} */ function () { /** @type {?} */ var empty = this.itemsList.filteredItems.length === 0; return empty && this._isTypeahead && !this._validTerm && !this.loading; }; /** * @return {?} */ NgSelectComponent.prototype.onCompositionStart = /** * @return {?} */ function () { this._isComposing = true; }; /** * @param {?} term * @return {?} */ NgSelectComponent.prototype.onCompositionEnd = /** * @param {?} term * @return {?} */ function (term) { this._isComposing = false; if (this.searchWhileComposing) { return; } this.filter(term); }; /** * @param {?} term * @return {?} */ NgSelectComponent.prototype.filter = /** * @param {?} term * @return {?} */ function (term) { if (this._isComposing && !this.searchWhileComposing) { return; } this.searchTerm = term; if (this._isTypeahead && this._validTerm) { this.typeahead.next(term); } if (!this._isTypeahead) { this.itemsList.filter(this.searchTerm); if (this.isOpen) { this.itemsList.markSelectedOrDefault(this.markFirst); } } this.searchEvent.emit({ term: term, items: this.itemsList.filteredItems.map((/** * @param {?} x * @return {?} */ function (x) { return x.value; })) }); this.open(); }; /** * @param {?} $event * @return {?} */ NgSelectComponent.prototype.onInputFocus = /** * @param {?} $event * @return {?} */ function ($event) { if (this.focused) { return; } this.element.classList.add('ng-select-focused'); this.focusEvent.emit($event); this.focused = true; }; /** * @param {?} $event * @return {?} */ NgSelectComponent.prototype.onInputBlur = /** * @param {?} $event * @return {?} */ function ($event) { this.element.classList.remove('ng-select-focused'); this.blurEvent.emit($event); if (!this.isOpen && !this.disabled) { this._onTouched(); } this.focused = false; }; /** * @param {?} item * @return {?} */ NgSelectComponent.prototype.onItemHover = /** * @param {?} item * @return {?} */ function (item) { if (item.disabled) { return; } this.itemsList.markItem(item); }; /** * @return {?} */ NgSelectComponent.prototype.detectChanges = /** * @return {?} */ function () { if (!((/** @type {?} */ (this._cd))).destroyed) { this._cd.detectChanges(); } }; /** * @private * @param {?} items * @return {?} */ NgSelectComponent.prototype._setItems = /** * @private * @param {?} items * @return {?} */ function (items) { /** @type {?} */ var firstItem = items[0]; this.bindLabel = this.bindLabel || this._defaultLabel; this._primitive = isDefined(firstItem) ? !isObject(firstItem) : this._primitive || this.bindLabel === this._defaultLabel; this.itemsList.setItems(items); if (items.length > 0 && this.hasValue) { this.itemsList.mapSelectedItems(); } if (this.isOpen && isDefined(this.searchTerm) && !this._isTypeahead) { this.itemsList.filter(this.searchTerm); } if (this._isTypeahead || this.isOpen) { this.itemsList.markSelectedOrDefault(this.markFirst); } }; /** * @private * @return {?} */ NgSelectComponent.prototype._setItemsFromNgOptions = /** * @private * @return {?} */ function () { var _this = this; /** @type {?} */ var mapNgOptions = (/** * @param {?} options * @return {?} */ function (options) { _this.items = options.map((/** * @param {?} option * @return {?} */ function (option) { return ({ $ngOptionValue: option.value, $ngOptionLabel: option.elementRef.nativeElement.innerHTML, disabled: option.disabled }); })); _this.itemsList.setItems(_this.items); if (_this.hasValue) { _this.itemsList.mapSelectedItems(); } _this.detectChanges(); }); /** @type {?} */ var handleOptionChange = (/** * @return {?} */ function () { /** @type {?} */ var changedOrDestroyed = merge(_this.ngOptions.changes, _this._destroy$); merge.apply(void 0, tslib_1.__spread(_this.ngOptions.map((/** * @param {?} option * @return {?} */ function (option) { return option.stateChange$; })))).pipe(takeUntil(changedOrDestroyed)) .subscribe((/** * @param {?} option * @return {?} */ function (option) { /** @type {?} */ var item = _this.itemsList.findItem(option.value); item.disabled = option.disabled; item.label = option.label || item.label; _this._cd.detectChanges(); })); }); this.ngOptions.changes .pipe(startWith(this.ngOptions), takeUntil(this._destroy$)) .subscribe((/** * @param {?} options * @return {?} */ function (options) { _this.bindLabel = _this._defaultLabel; mapNgOptions(options); handleOptionChange(); })); }; /** * @private * @param {?} value * @return {?} */ NgSelectComponent.prototype._isValidWriteValue = /** * @private * @param {?} value * @return {?} */ function (value) { var _this = this; if (!isDefined(value) || (this.multiple && value === '') || Array.isArray(value) && value.length === 0) { return false; } /** @type {?} */ var validateBinding = (/** * @param {?} item * @return {?} */ function (item) { if (!isDefined(_this.compareWith) && isObject(item) && _this.bindValue) { _this._console.warn("Binding object(" + JSON.stringify(item) + ") with bindValue is not allowed."); return false; } return true; }); if (this.multiple) { if (!Array.isArray(value)) { this._console.warn('Multiple select ngModel should be array.'); return false; } return value.every((/** * @param {?} item * @return {?} */ function (item) { return validateBinding(item); })); } else { return validateBinding(value); } }; /** * @private * @param {?} ngModel * @return {?} */ NgSelectComponent.prototype._handleWriteValue = /** * @private * @param {?} ngModel * @return {?} */ function (ngModel) { var _this = this; if (!this._isValidWriteValue(ngModel)) { return; } /** @type {?} */ var select = (/** * @param {?} val * @return {?} */ function (val) { var _a; /** @type {?} */ var item = _this.itemsList.findItem(val); if (item) { _this.itemsList.select(item); } else { /** @type {?} */ var isValObject = isObject(val); /** @type {?} */ var isPrimitive = !isValObject && !_this.bindValue; if ((isValObject || isPrimitive)) { _this.itemsList.select(_this.itemsList.mapItem(val, null)); } else if (_this.bindValue) { item = (_a = {}, _a[_this.bindLabel] = null, _a[_this.bindValue] = val, _a); _this.itemsList.select(_this.itemsList.mapItem(item, null)); } } }); if (this.multiple) { ((/** @type {?} */ (ngModel))).forEach((/** * @param {?} item * @return {?} */ function (item) { return select(item); })); } else { select(ngModel); } }; /** * @private * @return {?} */ NgSelectComponent.prototype._handleKeyPresses = /** * @private * @return {?} */ function () { var _this = this; if (this.searchable) { return; } this._keyPress$ .pipe(takeUntil(this._destroy$), tap((/** * @param {?} letter * @return {?} */ function (letter) { return _this._pressedKeys.push(letter); })), debounceTime(200), filter((/** * @return {?} */ function () { return _this._pressedKeys.length > 0; })), map((/** * @return {?} */ function () { return _this._pressedKeys.join(''); }))) .subscribe((/** * @param {?} term * @return {?} */ function (term) { /** @type {?} */ var item = _this.itemsList.findByLabel(term); if (item) { if (_this.isOpen) { _this.itemsList.markItem(item); _this._cd.markForCheck(); } else { _this.select(item); } } _this._pressedKeys = []; })); }; /** * @private * @return {?} */ NgSelectComponent.prototype._setInputAttributes = /** * @private * @return {?} */ function () { var e_1, _a; /** @type {?} */ var input = this.searchInput.nativeElement; /** @type {?} */ var attributes = tslib_1.__assign({ type: 'text', autocorrect: 'off', autocapitalize: 'off', autocomplete: this.labelForId ? 'off' : this.dropdownId }, this.inputAttrs); try { for (var _b = tslib_1.__values(Object.keys(attributes)), _c = _b.next(); !_c.done; _c = _b.next()) { var key = _c.value; input.setAttribute(key, attributes[key]); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_1) throw e_1.error; } } }; /** * @private * @return {?} */ NgSelectComponent.prototype._updateNgModel = /** * @private * @return {?} */ function () { var e_2, _a; /** @type {?} */ var model = []; try { for (var _b = tslib_1.__values(this.selectedItems), _c = _b.next(); !_c.done; _c = _b.next()) { var item = _c.value; if (this.bindValue) { /** @type {?} */ var value = null; if (item.children) { /** @type {?} */ var groupKey = this.groupValue ? this.bindValue : (/** @type {?} */ (this.groupBy)); value = item.value[groupKey || (/** @type {?} */ (this.groupBy))]; } else { value = this.itemsList.resolveNested(item.value, this.bindValue); } model.push(value); } else { model.push(item.value); } } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_2) throw e_2.error; } } /** @type {?} */ var selected = this.selectedItems.map((/** * @param {?} x * @return {?} */ function (x) { return x.value; })); if (this.multiple) { this._onChange(model); this.changeEvent.emit(selected); } else { this._onChange(isDefined(model[0]) ? model[0] : null); this.changeEvent.emit(selected[0]); } this._cd.markForCheck(); }; /** * @private * @return {?} */ NgSelectComponent.prototype._clearSearch = /** * @private * @return {?} */ function () { if (!this.searchTerm) { return; } this._changeSearch(null); this.itemsList.resetFilteredItems(); }; /** * @private * @param {?} searchTerm * @return {?} */ NgSelectComponent.prototype._changeSearch = /** * @private * @param {?} searchTerm * @return {?} */ function (searchTerm) { this.searchTerm = searchTerm; if (this._isTypeahead) { this.typeahead.next(searchTerm); } }; /** * @private * @return {?} */ NgSelectComponent.prototype._scrollToMarked = /** * @private * @return {?} */ function () { if (!this.isOpen || !this.dropdownPanel) { return; } this.dropdownPanel.scrollTo(this.itemsList.markedItem); }; /** * @private * @return {?} */ NgSelectComponent.prototype._scrollToTag = /** * @private * @return {?} */ function () { if (!this.isOpen || !this.dropdownPanel) { return; } this.dropdownPanel.scrollToTag(); }; /** * @private * @return {?} */ NgSelectComponent.prototype._onSelectionChanged = /** * @private * @return {?} */ function () { if (this.isOpen && this.multiple && this.appendTo) { // Make sure items are rendered. this._cd.detectChanges(); this.dropdownPanel.adjustPosition(); } }; /** * @private * @param {?} $event * @return {?} */ NgSelectComponent.prototype._handleTab = /** * @private * @param {?} $event * @return {?} */ function ($event) { if (this.isOpen === false && !this.addTag) { return; } if (this.selectOnTab) { if (this.itemsList.markedItem) { this.toggleItem(this.itemsList.markedItem); $event.preventDefault(); } else if (this.showAddTag) { this.selectTag(); $event.preventDefault(); } else { this.close(); } } else { this.close(); } }; /** * @private * @param {?} $event * @return {?} */ NgSelectComponent.prototype._handleEnter = /** * @private * @param {?} $event * @return {?} */ function ($event) { if (this.isOpen || this._manualOpen) { if (this.itemsList.markedItem) { this.toggleItem(this.itemsList.markedItem); } else if (this.showAddTag) { this.selectTag(); } } else if (this.openOnEnter) { this.open(); } else { return; } $event.preventDefault(); }; /** * @private * @param {?} $event * @return {?} */ NgSelectComponent.prototype._handleSpace = /** * @private * @param {?} $event * @return {?} */ function ($event) { if (this.isOpen || this._manualOpen) { return; } this.open(); $event.preventDefault(); }; /** * @private * @param {?} $event * @return {?} */ NgSelectComponent.prototype._handleArrowDown = /** * @private * @param {?} $event * @return {?} */ function ($event) { if (this._nextItemIsTag(+1)) { this.itemsList.unmarkItem(); this._scrollToTag(); } else { this.itemsList.markNextItem(); this._scrollToMarked(); } this.open(); $event.preventDefault(); }; /** * @private * @param {?} $event * @return {?} */ NgSelectComponent.prototype._handleArrowUp = /** * @private * @param {?} $event * @return {?} */ function ($event) { if (!this.isOpen) { return; } if (this._nextItemIsTag(-1)) { this.itemsList.unmarkItem(); this._scrollToTag(); } else { this.itemsList.markPreviousItem(); this._scrollToMarked(); } $event.preventDefault(); }; /** * @private * @param {?} nextStep * @return {?} */ NgSelectComponent.prototype._nextItemIsTag = /** * @private * @param {?} nextStep * @return {?} */ function (nextStep) { /** @type {?} */ var nextIndex = this.itemsList.markedIndex + nextStep; return this.addTag && this.searchTerm && this.itemsList.markedItem && (nextIndex < 0 || nextIndex === this.itemsList.filteredItems.length); }; /** * @private * @return {?} */ NgSelectComponent.prototype._handleBackspace = /** * @private * @return {?} */ function () { if (this.searchTerm || !this.clearable || !this.clearOnBackspace || !this.hasValue) { return; } if (this.multiple) { this.unselect(this.itemsList.lastSelectedItem); } else { this.clearModel(); } }; Object.defineProperty(NgSelectComponent.prototype, "_isTypeahead", { get: /** * @private * @return {?} */ function () { return this.typeahead && this.typeahead.observers.length > 0; }, enumerable: true, configurable: true }); Object.defineProperty(NgSelectComponent.prototype, "_validTerm", { get: /** * @private * @return {?} */ function () { /** @type {?} */ var term = this.searchTerm && this.searchTerm.trim(); return term && term.length >= this.minTermLength; }, enumerable: true, configurable: true }); /** * @private * @param {?} config * @return {?} */ NgSelectComponent.prototype._mergeGlobalConfig = /** * @private * @param {?} config * @return {?} */ function (config) { this.placeholder = this.placeholder || config.placeholder; this.notFoundText = this.notFoundText || config.notFoundText; this.typeToSearchText = this.typeToSearchText || config.typeToSearchText; this.addTagText = this.addTagText || config.addTagText; this.loadingText = this.loadingText || config.loadingText; this.clearAllText = this.clearAllText || config.clearAllText; this.virtualScroll = isDefined(this.virtualScroll) ? this.virtualScroll : isDefined(config.disableVirtualScroll) ? !config.disableVirtualScroll : false; this.openOnEnter = isDefined(this.openOnEnter) ? this.openOnEnter : config.openOnEnter; this.appendTo = this.appendTo || config.appendTo; this.bindValue = this.bindValue || config.bindValue; this.appearance = this.appearance || config.appearance; }; NgSelectComponent.decorators = [ { type: Component, args: [{ selector: 'ng-select', template: "<div\n (mousedown)=\"handleMousedown($event)\"\n [class.ng-appearance-outline]=\"appearance === 'outline'\"\n [class.ng-has-value]=\"hasValue\"\n class=\"ng-select-container\">\n\n <div class=\"ng-value-container\">\n <div class=\"ng-placeholder\">{{placeholder}}</div>\n\n <ng-container *ngIf=\"!multiLabelTemplate && selectedItems.length > 0\">\n <div [class.ng-value-disabled]=\"item.disabled\" class=\"ng-value\" *ngFor=\"let item of selectedItems; trackBy: trackByOption\">\n <ng-template #defaultLabelTemplate>\n <span class=\"ng-value-icon left\" (click)=\"unselect(item);\" aria-hidden=\"true\">\u00D7</span>\n <span class=\"ng-value-label\" [ngItemLabel]=\"item.label\" [escape]=\"escapeHTML\"></span>\n </ng-template>\n\n <ng-template\n [ngTemplateOutlet]=\"labelTemplate || defaultLabelTemplate\"\n [ngTemplateOutletContext]=\"{ item: item.value, clear: clearItem, label: item.label }\">\n </ng-template>\n </div>\n </ng-container>\n\n <ng-template *ngIf=\"multiLabelTemplate && selectedValues.length > 0\"\n [ngTemplateOutlet]=\"multiLabelTemplate\"\n [ngTemplateOutletContext]=\"{ items: selectedValues, clear: clearItem }\">\n </ng-template>\n\n <div class=\"ng-input\">\n <input #searchInput\n [attr.id]=\"labelForId\"\n [attr.tabindex]=\"tabIndex\"\n [readOnly]=\"!searchable || itemsList.maxItemsSelected\"\n [disabled]=\"disabled\"\n [value]=\"searchTerm ? searchTerm : ''\"\n (input)=\"filter(searchInput.value)\"\n (compositionstart)=\"onCompositionStart()\"\n (compositionend)=\"onCompositionEnd(searchInput.value)\"\n (focus)=\"onInputFocus($event)\"\n (blur)=\"onInputBlur($event)\"\n (change)=\"$event.stopPropagation()\"\n role=\"combobox\"\n [attr.aria-expanded]=\"isOpen\"\n [attr.aria-owns]=\"isOpen ? dropdownId : null\"\n [attr.aria-activedescendant]=\"isOpen ? itemsList?.markedItem?.htmlId : null\">\n </div>\n </div>\n\n <ng-container *ngIf=\"loading\">\n <ng-template #defaultLoadingSpinnerTemplate>\n <div class=\"ng-spinner-loader\"></div>\n </ng-template>\n\n <ng-template\n [ngTemplateOutlet]=\"loadingSpinnerTemplate || defaultLoadingSpinnerTemplate\">\n </ng-template>\n </ng-container>\n\n <span *ngIf=\"showClear()\" class=\"ng-clear-wrapper\" title=\"{{clearAllText}}\">\n <span class=\"ng-clear\" aria-hidden=\"true\">\u00D7</span>\n </span>\n\n <span class=\"ng-arrow-wrapper\">\n <span class=\"ng-arrow\"></span>\n </span>\n</div>\n\n<ng-dropdown-panel *ngIf=\"isOpen\"\n class=\"ng-dropdown-panel\"\n [virtualScroll]=\"virtualScroll\"\n [bufferAmount]=\"bufferAmount\"\n [appendTo]=\"appendTo\"\n [position]=\"dropdownPosition\"\n [headerTemplate]=\"headerTemplate\"\n [footerTemplate]=\"footerTemplate\"\n [filterValue]=\"searchTerm\"\n [items]=\"itemsList.filteredItems\"\n [markedItem]=\"itemsList.markedItem\"\n (update)=\"viewPortItems = $event\"\n (scroll)=\"scroll.emit($event)\"\n (scrollToEnd)=\"scrollToEnd.emit($event)\"\n (outsideClick)=\"close()\"\n [class.ng-select-multiple]=\"multiple\"\n [ngClass]=\"appendTo ? classes : null\"\n [id]=\"dropdownId\">\n\n <ng-container>\n <div class=\"ng-option\" [attr.role]=\"item.children ? 'group' : 'option'\" (click)=\"toggleItem(item)\" (mouseover)=\"onItemHover(item)\"\n *ngFor=\"let item of viewPortItems; trackBy: trackByOption\"\n [class.ng-option-disabled]=\"item.disabled\"\n [class.ng-option-selected]=\"item.selected\"\n [class.ng-optgroup]=\"item.children\"\n [class.ng-option]=\"!item.children\"\n [class.ng-option-child]=\"!!item.parent\"\n [class.ng-option-marked]=\"item === itemsList.markedItem\"\n [attr.aria-selected]=\"item.selected\"\n [attr.id]=\"item?.htmlId\">\n\n <ng-template #defaultOptionTemplate>\n <span class=\"ng-option-label\" [ngItemLabel]=\"item.label\" [escape]=\"escapeHTML\"></span>\n </ng-template>\n\n <ng-template\n [ngTemplateOutlet]=\"item.children ? (optgroupTemplate || defaultOptionTemplate) : (optionTemplate || defaultOptionTemplate)\"\n [ngTemplateOutletContext]=\"{ item: item.value, item$:item, index: item.index, searchTerm: searchTerm }\">\n </ng-template>\n </div>\n\n <div class=\"ng-option\" [class.ng-option-marked]=\"!itemsList.markedItem\" (mouseover)=\"itemsList.unmarkItem()\" role=\"option\" (click)=\"selectTag()\" *ngIf=\"showAddTag\">\n <ng-template #defaultTagTemplate>\n <span><span class=\"ng-tag-label\">{{addTagText}}</span>\"{{searchTerm}}\"</span>\n </ng-template>\n\n <ng-template\n [ngTemplateOutlet]=\"tagTemplate || defaultTagTemplate\"\n [ngTemplateOutletContext]=\"{ searchTerm: searchTerm }\">\n </ng-template>\n </div>\n </ng-container>\n\n <ng-container *ngIf=\"showNoItemsFound()\">\n <ng-template #defaultNotFoundTemplate>\n <div class=\"ng-option ng-option-disabled\">{{notFoundText}}</div>\n </ng-template>\n\n <ng-template\n [ngTemplateOutlet]=\"notFoundTemplate || defaultNotFoundTemplate\"\n [ngTemplateOutletContext]=\"{ searchTerm: searchTerm }\">\n </ng-template>\n </ng-container>\n\n <ng-container *ngIf=\"showTypeToSearch()\">\n <ng-template #defaultTypeToSearchTemplate>\n <div class=\"ng-option ng-option-disabled\">{{typeToSearchText}}</div>\n </ng-template>\n\n <ng-template\n [ngTemplateOutlet]=\"typeToSearchTemplate || defaultTypeToSearchTemplate\">\n </ng-template>\n </ng-container>\n\n <ng-container *ngIf=\"loading && itemsList.filteredItems.length === 0\">\n <ng-template #defaultLoadingTextTemplate>\n <div class=\"ng-option ng-option-disabled\">{{loadingText}}</div>\n </ng-template>\n\n <ng-template\n [ngTemplateOutlet]=\"loadingTextTemplate || defaultLoadingTextTemplate\"\n [ngTemplateOutletContext]=\"{ searchTerm: searchTerm }\">\n </ng-template>\n </ng-container>\n\n</ng-dropdown-panel>\n", providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef((/** * @return {?} */ function () { return NgSelectComponent; })), multi: true }, NgDropdownPanelService], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, host: { 'role': 'listbox', 'class': 'ng-select', '[class.ng-select-single]': '!multiple', }, styles: [".ng-select{position:relative;display:block;box-sizing:border-box}.ng-select div,.ng-select input,.ng-select span{box-sizing:border-box}.ng-select [hidden]{display:none}.ng-select.ng-select-searchable .ng-select-container .ng-value-container .ng-input{opacity:1}.ng-select.ng-select-opened .ng-select-container{z-index:1001}.ng-select.ng-select-disabled .ng-select-container .ng-value-container .ng-placeholder,.ng-select.ng-select-disabled .ng-select-container .ng-value-container .ng-value{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:default}.ng-select.ng-select-disabled .ng-arrow-wrapper{cursor:default}.ng-select.ng-select-filtered .ng-placeholder{display:none}.ng-select .ng-select-container{color:#333;cursor:default;display:-webkit-box;display:flex;outline:0;overflow:hidden;position:relative;width:100%}.ng-select .ng-select-container .ng-value-container{display:-webkit-box;display:flex;-webkit-box-flex:1;flex:1}.ng-select .ng-select-container .ng-value-container .ng-input{opacity:0}.ng-select .ng-select-container .ng-value-container .ng-input>input{box-sizing:content-box;background:none;border:0;box-shadow:none;outline:0;cursor:default;width:100%}.ng-select .ng-select-container .ng-value-container .ng-input>input::-ms-clear{display:none}.ng-select .ng-select-container .ng-value-container .ng-input>input[readonly]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:0;padding:0}.ng-select.ng-select-single.ng-select-filtered .ng-select-container .ng-value-container .ng-value{visibility:hidden}.ng-select.ng-select-single .ng-select-container .ng-value-container,.ng-select.ng-select-single .ng-select-container .ng-value-container .ng-value{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ng-select.ng-select-single .ng-select-container .ng-value-container .ng-value .ng-value-icon{display:none}.ng-select.ng-select-single .ng-select-container .ng-value-container .ng-input{position:absolute;left:0;width:100%}.ng-select.ng-select-multiple.ng-select-disabled>.ng-select-container .ng-value-container .ng-value .ng-value-icon{display:none}.ng-select.ng-select-multiple .ng-select-container .ng-value-container{flex-wrap:wrap}.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value{white-space:nowrap}.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value.ng-value-disabled .ng-value-icon{display:none}.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value .ng-value-icon{cursor:pointer}.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-input{-webkit-box-flex:1;