@ng-select/ng-select
Version:
Angular ng-select - All in One UI Select, Multiselect and Autocomplete
1,420 lines • 143 kB
JavaScript
/**
* @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;