UNPKG

ngx-select2-ex

Version:

Angular(2+) version of the popular alternative to select inputs, Select2. Select2 classes are used in the template, so you can use any pre-existing styles for Select2 and it will look the same as the original.

1,374 lines (1,358 loc) 43.4 kB
import { Injectable, Component, Input, forwardRef, Pipe, HostBinding, ApplicationRef, ComponentFactoryResolver, Injector, Directive, ElementRef, HostListener, Renderer2, NgModule } from '@angular/core'; import { ReplaySubject } from 'rxjs/ReplaySubject'; import { BehaviorSubject } from 'rxjs/BehaviorSubject'; import { NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms'; import { CommonModule } from '@angular/common'; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class NgxSelect2ExOption { /** * @param {?} id * @param {?} value * @param {?=} disabled * @param {?=} selected */ constructor(id, value, disabled, selected) { this.id = id; this.value = value; this.disabled = !!disabled; this.selected = !!selected; } } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class NgxSelect2ExOptionHandler extends NgxSelect2ExOption { /** * @param {?} id * @param {?} value * @param {?=} disabled * @param {?=} selected * @param {?=} highlighted */ constructor(id, value, disabled, selected, highlighted) { super(id, value, !!disabled, !!selected); this.highlighted = !!highlighted; } /** * @param {?} optionHandler * @return {?} */ static copy(optionHandler) { return new NgxSelect2ExOptionHandler(optionHandler.id, optionHandler.value, optionHandler.disabled, optionHandler.selected, optionHandler.highlighted); } /** * @param {?} arrayOfOptionHandlers * @return {?} */ static copyArray(arrayOfOptionHandlers) { const /** @type {?} */ options = arrayOfOptionHandlers.map((option) => NgxSelect2ExOptionHandler.copy(option)); return [...options]; } } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class NgxSelect2ExLanguageInputs { /** * @param {?=} languageInputs */ constructor(languageInputs) { this.errorLoading = languageInputs && languageInputs.errorLoading ? languageInputs.errorLoading : () => `The results could not be loaded.`; this.inputTooLong = languageInputs && languageInputs.inputTooLong ? languageInputs.inputTooLong : (n) => `Please delete ${n} character`; this.inputTooShort = languageInputs && languageInputs.inputTooShort ? languageInputs.inputTooShort : (n) => `Please enter ${n} or more characters`; this.loadingMore = languageInputs && languageInputs.loadingMore ? languageInputs.loadingMore : () => `Loading more results…`; this.maximumSelected = languageInputs && languageInputs.maximumSelected ? languageInputs.maximumSelected : (n) => `You can only select ${n} item`; this.noResults = languageInputs && languageInputs.noResults ? languageInputs.noResults : () => `No results found`; this.searching = languageInputs && languageInputs.searching ? languageInputs.searching : () => `Searching…`; } } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class NgxSelect2ExService { constructor() { this.multi = null; this.disabled = false; this.theme = 'default'; this.minimumResultsForSearch = 0; this.minimumInputLength = null; this.maximumInputLength = null; this.language = new NgxSelect2ExLanguageInputs(); this.selectOnClose = false; this.closeOnSelect = true; this._options = new BehaviorSubject([]); this._dropdownPosition = new ReplaySubject(1); this._isOpen = new BehaviorSubject(false); this._isInFocus = new BehaviorSubject(false); this._selection = new BehaviorSubject([]); this._search = new BehaviorSubject(null); } /** * @return {?} */ get options() { return this._options.getValue(); } /** * @param {?} options * @return {?} */ set options(options) { this._options.next(NgxSelect2ExOptionHandler.copyArray(options)); this.selection = this.options; } /** * @return {?} */ getOptionsAsObservable() { return this._options.asObservable(); } /** * @param {?} options * @return {?} */ set selection(options) { options = NgxSelect2ExOptionHandler.copyArray(options); let /** @type {?} */ selection = options.filter((option) => option.selected); if (this.multi) { this._selection.next(selection); } else { let /** @type {?} */ selectedOption; if (selection.length === 0 && options.length) { selectedOption = NgxSelect2ExOptionHandler.copyArray(options).reverse().pop(); } else if (selection.length > 0) { selectedOption = selection.pop(); } options.forEach(o => o.selected = false); options[options.findIndex(o => o.id === selectedOption.id)].selected = true; this._options.next(options); selection = [selectedOption]; this._selection.next(selection); } } /** * @return {?} */ get selection() { return this._selection.getValue(); } /** * @return {?} */ getSelectionAsObservable() { return this._selection.asObservable(); } /** * @param {?} dropdownPosition * @return {?} */ set dropdownPosition(dropdownPosition) { this._dropdownPosition.next(dropdownPosition); } /** * @return {?} */ getDropdownPositionAsObservable() { return this._dropdownPosition.asObservable(); } /** * @param {?} isOpen * @return {?} */ set isOpen(isOpen) { this._isOpen.next(isOpen); } /** * @return {?} */ get isOpen() { return this._isOpen.getValue(); } /** * @return {?} */ getIsOpenAsObservable() { return this._isOpen.asObservable(); } /** * @param {?} isInFocus * @return {?} */ set isInFocus(isInFocus) { this._isInFocus.next(isInFocus); } /** * @return {?} */ get isInFocus() { return this._isInFocus.getValue(); } /** * @return {?} */ getIsInFocusAsObservable() { return this._isInFocus.asObservable(); } /** * @param {?} search * @return {?} */ set search(search) { this._search.next(search); } /** * @return {?} */ get search() { return this._search.getValue(); } /** * @return {?} */ getSearchAsObservable() { return this._search.asObservable(); } /** * @return {?} */ open() { this.isOpen = true; } /** * @return {?} */ close() { this.isOpen = false; } /** * @param {?} optionHandlerToSelect * @return {?} */ select(optionHandlerToSelect) { if (!this.multi) { this.options.forEach((option) => option.selected = false); } const /** @type {?} */ indexOfSelected = this.options.findIndex((option) => option.id === optionHandlerToSelect.id); if (indexOfSelected > -1) { const /** @type {?} */ options = NgxSelect2ExOptionHandler.copyArray(this.options); options[indexOfSelected].selected = true; this.options = options; } } /** * @param {?} optionHandlerToDeselect * @return {?} */ deselect(optionHandlerToDeselect) { if (!this.multi) { return; } else { const /** @type {?} */ indexOfDeselected = this.options.findIndex((option) => option.id === optionHandlerToDeselect.id); if (indexOfDeselected > -1) { const /** @type {?} */ options = NgxSelect2ExOptionHandler.copyArray(this.options); options[indexOfDeselected].selected = false; this.options = options; } } } /** * @return {?} */ clear() { const /** @type {?} */ options = NgxSelect2ExOptionHandler.copyArray(this.options); options.forEach((option) => option.selected = false); this._options.next(options); this._selection.next([]); } } NgxSelect2ExService.decorators = [ { type: Injectable }, ]; /** @nocollapse */ NgxSelect2ExService.ctorParameters = () => []; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class NgxSelect2ExComponent { /** * @param {?} ngxSelect2ExService */ constructor(ngxSelect2ExService) { this.ngxSelect2ExService = ngxSelect2ExService; this.options = null; this.disabled = null; this.multi = null; this.theme = null; this.minimumResultsForSearch = null; this.minimumInputLength = null; this.maximumInputLength = null; this.language = null; this.selectOnClose = false; this.closeOnSelect = true; this.allowClear = false; this.placeholder = null; this.selection = []; this.subscriptions = []; this.propagateChange = (_) => { }; } /** * @param {?} search * @return {?} */ set search(search) { this.ngxSelect2ExService.search = search; } /** * @return {?} */ get search() { return this.ngxSelect2ExService.search; } /** * @return {?} */ ngOnInit() { this.initStaticInputValues(); this.subscribeToSelection(); this.subscribeToIsOpen(); this.subscribeToIsInFocus(); } /** * @param {?} changes * @return {?} */ ngOnChanges(changes) { if (changes['options'] && changes['options'].currentValue.length && changes['options'].previousValue !== changes['options'].currentValue) { this.initOptions(changes['options'].currentValue); } if (changes['disabled'] !== undefined && changes['disabled'].previousValue !== changes['disabled'].currentValue) { this.ngxSelect2ExService.disabled = changes['disabled'].currentValue; } } /** * @return {?} */ ngOnDestroy() { this.unsubscribe(); } /** * @param {?} value * @return {?} */ writeValue(value) { this.initOptions(value); } /** * @param {?} fn * @return {?} */ registerOnChange(fn) { this.propagateChange = fn; } /** * @param {?} fn * @return {?} */ registerOnTouched(fn) { } /** * @param {?} isDisabled * @return {?} */ setDisabledState(isDisabled) { this.disabled = isDisabled; this.ngxSelect2ExService.disabled = isDisabled; } /** * @return {?} */ getContainerThemeClass() { return 'select2-container--' + this.ngxSelect2ExService.theme; } /** * @return {?} */ getStyleOfSearchListItem() { const /** @type {?} */ width = (!this.selection || !this.selection.length) && this.placeholder ? '100%' : null; return { 'width': width }; } /** * @param {?} search * @return {?} */ getStyleOfInlineInput(search) { if (!search && (!this.selection || !this.selection.length) && this.placeholder) { return { 'width': '100%' }; } const /** @type {?} */ width = search ? `${((search.length + 1) * 0.75)}em` : '0.75em'; return { 'width': width }; } /** * @return {?} */ getInlineInputPlaceholder() { return (!this.selection || !this.selection.length) && this.placeholder ? this.placeholder : ''; } /** * @return {?} */ clearSelection() { if (this.shouldShowClearSelectionButton() && (!this.multi && this.placeholder || this.multi) && !this.disabled) { this.ngxSelect2ExService.clear(); } } /** * @return {?} */ shouldShowClearSelectionButton() { return this.allowClear && this.selection && !!this.selection.length; } /** * @return {?} */ shouldShowPlaceholder() { return (!this.selection || !this.selection.length) && !!this.placeholder; } /** * @return {?} */ getTitleTooltipText() { if (this.selection && this.selection.length && this.selection[0].value) { return this.selection[0].value; } else if (this.placeholder) { return this.placeholder; } else { return ''; } } /** * @param {?} optionHandlerToDeselect * @return {?} */ deselect(optionHandlerToDeselect) { this.ngxSelect2ExService.deselect(optionHandlerToDeselect); } /** * @return {?} */ subscribeToSelection() { this.subscriptions.push(this.ngxSelect2ExService.getSelectionAsObservable() .subscribe((selection) => { this.selection = selection; this.propagateChange(this.selection); })); } /** * @return {?} */ subscribeToIsOpen() { this.subscriptions.push(this.ngxSelect2ExService.getIsOpenAsObservable() .subscribe((isOpen) => this.isOpen = isOpen)); } /** * @return {?} */ subscribeToIsInFocus() { this.subscriptions.push(this.ngxSelect2ExService.getIsInFocusAsObservable() .subscribe((isInFocus) => this.isInFocus = isInFocus)); } /** * @param {?} options * @return {?} */ initOptions(options) { if (this.isStringList(options)) { this.ngxSelect2ExService.options = options.map((option, index) => new NgxSelect2ExOptionHandler(index, option)); } else if (this.isOptionInterfaceList(options)) { this.ngxSelect2ExService.options = options.map((option) => new NgxSelect2ExOptionHandler(option.id, option.value, option.disabled, option.selected)); } else { throw new Error('Input for options array should be of type Array<string> or Array<INgxSelect2ExOption>.'); } } /** * @param {?} list * @return {?} */ isStringList(list) { return list && list.every((item) => { return typeof item === 'string'; }); } /** * @param {?} list * @return {?} */ isOptionInterfaceList(list) { return list && list.every((item) => { return 'id' in item && 'value' in item; }); } /** * @param {?} changes * @param {?} fieldName * @return {?} */ defaultChangeListener(changes, fieldName) { if (changes[fieldName] && changes[fieldName].previousValue !== changes[fieldName].currentValue) { this.ngxSelect2ExService[fieldName] = changes[fieldName].currentValue; } } /** * @return {?} */ initStaticInputValues() { this.defaultInputSetter('multi'); this.defaultInputSetter('theme'); this.defaultInputSetter('minimumResultsForSearch'); this.defaultInputSetter('minimumInputLength'); this.defaultInputSetter('maximumInputLength', this.minimumInputLength && this.maximumInputLength && this.maximumInputLength < this.minimumInputLength ? this.minimumInputLength : this.maximumInputLength); this.defaultInputSetter('language', new NgxSelect2ExLanguageInputs(this.language)); this.defaultInputSetter('selectOnClose'); this.defaultInputSetter('closeOnSelect'); } /** * @param {?} inputField * @param {?=} optionalValue * @return {?} */ defaultInputSetter(inputField, optionalValue) { if (this[inputField] !== null) { this.ngxSelect2ExService[inputField] = optionalValue ? optionalValue : this[inputField]; } } /** * @return {?} */ unsubscribe() { this.subscriptions.forEach((subscription) => subscription.unsubscribe()); } } NgxSelect2ExComponent.decorators = [ { type: Component, args: [{ selector: 'app-ngx-select2-ex', template: `<span appNgxSelect2Ex [service]="ngxSelect2ExService" class="select2 select2-container" [class.select2-container--below]="!disabled" [class.select2-container--open]="isOpen" [ngClass]="getContainerThemeClass()" [class.select2-container--focus]="isInFocus" [class.select2-container--disabled]="disabled" dir="ltr"> <span class="selection"> <span class="select2-selection" [class.select2-selection--single]="!multi" [class.select2-selection--multiple]="multi" role="combobox" aria-haspopup="true" [attr.aria-expanded]="isOpen" [tabindex]="multi ? -1 : 0" aria-labelledby="select2-container" aria-owns="select2-results"> <span *ngIf="!multi" class="select2-selection__rendered" id="select2-selection-container" [title]="getTitleTooltipText()"> <span *ngIf="shouldShowPlaceholder()" class="select2-selection__placeholder">{{placeholder}}</span> <span *ngIf="shouldShowClearSelectionButton()" class="select2-selection__clear" (click)="clearSelection()">×</span> {{selection[0]?.value}} </span> <span *ngIf="!multi" class="select2-selection__arrow" role="presentation"> <b role="presentation"></b> </span> <ul *ngIf="multi" class="select2-selection__rendered"> <span *ngIf="shouldShowClearSelectionButton()" class="select2-selection__clear" (click)="clearSelection()">×</span> <li *ngFor="let selectionItem of selection" class="select2-selection__choice" [title]="selectionItem.value"> <span class="select2-selection__choice__remove" role="presentation" (click)="deselect(selectionItem)">×</span> {{selectionItem.value}} </li> <li class="select2-search select2-search--inline" [ngStyle]="getStyleOfSearchListItem()"> <input class="select2-search__field" type="search" tabindex="0" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" role="textbox" aria-autocomplete="list" [placeholder]="getInlineInputPlaceholder()" [ngStyle]="getStyleOfInlineInput(search)" [(ngModel)]="search"></li> </ul> </span> </span> <span class="dropdown-wrapper" aria-hidden="true"></span> </span> `, styles: [`.select2-container{display:block}`], providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NgxSelect2ExComponent), multi: true }, NgxSelect2ExService ] },] }, ]; /** @nocollapse */ NgxSelect2ExComponent.ctorParameters = () => [ { type: NgxSelect2ExService, }, ]; NgxSelect2ExComponent.propDecorators = { "options": [{ type: Input },], "disabled": [{ type: Input },], "multi": [{ type: Input },], "theme": [{ type: Input },], "minimumResultsForSearch": [{ type: Input },], "minimumInputLength": [{ type: Input },], "maximumInputLength": [{ type: Input },], "language": [{ type: Input },], "selectOnClose": [{ type: Input },], "closeOnSelect": [{ type: Input },], "allowClear": [{ type: Input },], "placeholder": [{ type: Input },], }; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class NgxSelect2OptionFilterPipe { /** * @param {?} options * @param {?} filter * @param {?} minimumResultsForSearch * @param {?=} minimumInputLength * @param {?=} maximumInputLength * @return {?} */ transform(options, filter, minimumResultsForSearch, minimumInputLength = null, maximumInputLength = null) { return this.filterOptions(options, filter, minimumResultsForSearch, minimumInputLength, maximumInputLength); } /** * @param {?} options * @param {?} filter * @param {?} minimumResultsForSearch * @param {?=} minimumInputLength * @param {?=} maximumInputLength * @return {?} */ filterOptions(options, filter, minimumResultsForSearch, minimumInputLength = null, maximumInputLength = null) { if (options.length < minimumResultsForSearch) { return options; } else if (minimumInputLength !== null && maximumInputLength !== null) { return this.rangeInputFilteringHandler(options, filter, minimumInputLength, maximumInputLength); } else if (minimumInputLength !== null) { return this.minimumInputFilteringHandler(options, filter, minimumInputLength); } else if (maximumInputLength !== null) { return this.maximumInputFilteringHandler(options, filter, maximumInputLength); } else { return this.doFiltering(options, filter); } } /** * @param {?} options * @param {?} filter * @param {?} minimumInputLength * @param {?} maximumInputLength * @return {?} */ rangeInputFilteringHandler(options, filter, minimumInputLength, maximumInputLength) { if (this.isfilterTextBiggerThanMinimumInputLength(filter, minimumInputLength) && this.isfilterTextSmallerThanMaximumInputLength(filter, maximumInputLength)) { return this.doFiltering(options, filter); } else { return /** @type {?} */ ([]); } } /** * @param {?} options * @param {?} filter * @param {?} minimumInputLength * @return {?} */ minimumInputFilteringHandler(options, filter, minimumInputLength) { if (this.isfilterTextBiggerThanMinimumInputLength(filter, minimumInputLength)) { return this.doFiltering(options, filter); } else { return /** @type {?} */ ([]); } } /** * @param {?} options * @param {?} filter * @param {?} maximumInputLength * @return {?} */ maximumInputFilteringHandler(options, filter, maximumInputLength) { if (!filter || this.isfilterTextSmallerThanMaximumInputLength(filter, maximumInputLength)) { return this.doFiltering(options, filter); } else { return /** @type {?} */ ([]); } } /** * @param {?} filter * @param {?} minimumInputLength * @return {?} */ isfilterTextBiggerThanMinimumInputLength(filter, minimumInputLength) { return filter && minimumInputLength <= filter.length; } /** * @param {?} filter * @param {?} maximumInputLength * @return {?} */ isfilterTextSmallerThanMaximumInputLength(filter, maximumInputLength) { return filter && filter.length <= maximumInputLength; } /** * @param {?} options * @param {?} filter * @return {?} */ doFiltering(options, filter) { if (filter) { return options.filter((option) => option.value.toLowerCase().includes(filter.toLowerCase())); } else { return options; } } } NgxSelect2OptionFilterPipe.decorators = [ { type: Pipe, args: [{ name: 'ngxSelect2OptionFilter' },] }, ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class NgxSelect2ExDropdownComponent { /** * @param {?} filterPipe */ constructor(filterPipe) { this.filterPipe = filterPipe; this.multi = null; this.minimumInputLength = null; this.maximumInputLength = null; this.display = 'block'; this.position = 'absolute'; this.options = []; this.subscriptions = []; } /** * @return {?} */ ngOnInit() { this.subscribeToOptions(); this.subscribeToDropdownPositionChanges(); this.subscribeToSearchChanges(); } /** * @return {?} */ ngOnDestroy() { this.unsubscribe(); this.selectOnClose(); } /** * @param {?} hoveredOption * @return {?} */ onOptionHover(hoveredOption) { if (!hoveredOption.disabled) { this.options.forEach((option) => { option.highlighted = option.id === hoveredOption.id; }); } } /** * @param {?} clickedOption * @return {?} */ onOptionClick(clickedOption) { if (clickedOption.disabled) { return; } if (!clickedOption.selected) { this.service.select(clickedOption); } else { this.service.deselect(clickedOption); } this.service.search = null; } /** * @return {?} */ getContainerThemeClass() { return 'select2-container--' + this.theme; } /** * @return {?} */ shouldHideSearchBox() { return this.options.length < this.minimumResultsForSearch || this.multi; } /** * @return {?} */ getNoResultsMessage() { return this.language.noResults(); } /** * @return {?} */ getInputTooShortMessage() { return this.language.inputTooShort(this.minimumInputLength); } /** * @return {?} */ getInputTooLongMessage() { return this.language.inputTooLong((this.search ? this.search.length : 0) - this.maximumInputLength); } /** * @return {?} */ shouldShowNoResultsMessage() { return this.search && !this.filterPipe.filterOptions(this.options, this.search, this.minimumResultsForSearch).length && !this.shouldShowInputTooShortMessage() && !this.shouldShowInputTooLongMessage() && (this.multi || !this.shouldHideSearchBox()); } /** * @return {?} */ shouldShowInputTooShortMessage() { return this.minimumInputLength !== null && (!this.search || this.search && this.search.length < this.minimumInputLength) && !this.filterPipe.filterOptions(this.options, this.search, this.minimumResultsForSearch, this.minimumInputLength).length && !this.shouldHideSearchBox(); } /** * @return {?} */ shouldShowInputTooLongMessage() { return this.maximumInputLength !== null && this.search && this.maximumInputLength < this.search.length && !this.filterPipe.filterOptions(this.options, this.search, this.minimumResultsForSearch, null, this.maximumInputLength).length && !this.shouldHideSearchBox(); } /** * @return {?} */ subscribeToOptions() { this.subscriptions.push(this.service.getOptionsAsObservable().subscribe((options) => this.options = options, error => console.error(error))); } /** * @return {?} */ subscribeToDropdownPositionChanges() { this.subscriptions.push(this.service.getDropdownPositionAsObservable().subscribe((dropdownPosition) => this.initDropdownPosition(dropdownPosition))); } /** * @return {?} */ subscribeToSearchChanges() { this.subscriptions.push(this.service.getSearchAsObservable().subscribe((search) => this.search = search)); } /** * @param {?} dropdownPosition * @return {?} */ initDropdownPosition(dropdownPosition) { this.top = dropdownPosition.top + 'px'; this.left = dropdownPosition.left + 'px'; this.width = dropdownPosition.width + 'px'; } /** * @return {?} */ selectOnClose() { const /** @type {?} */ highlightedOption = this.options.find((option) => option.highlighted); if (highlightedOption && this.service.selectOnClose) { this.service.select(highlightedOption); } } /** * @return {?} */ unsubscribe() { this.subscriptions.forEach((subscription) => subscription.unsubscribe()); } } NgxSelect2ExDropdownComponent.decorators = [ { type: Component, args: [{ selector: 'app-ngx-select2-ex-dropdown', template: `<span class="select2-container" [ngClass]="getContainerThemeClass()" [class.select2-container--open]="true"> <span id="select2-dropdown" class="select2-dropdown select2-dropdown--below" dir="ltr"> <span *ngIf="!multi" class="select2-search select2-search--dropdown" [class.select2-search--hide]="shouldHideSearchBox()"> <input appNgxSelect2ExDropdownSearchField class="select2-search__field" type="search" tabindex="0" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" role="textbox" [(ngModel)]="search"> </span> <span class="select2-results"> <ul class="select2-results__options" role="tree" id="select2-results" aria-expanded="true" aria-hidden="false"> <li *ngFor="let option of options | ngxSelect2OptionFilter: search:minimumResultsForSearch:minimumInputLength:maximumInputLength" class="select2-results__option" [class.select2-results__option--highlighted]="option.highlighted" role="treeitem" [attr.aria-selected]="option.selected" [attr.aria-disabled]="option.disabled ? option.disabled : null" (mouseover)="onOptionHover(option)" (mousedown)="onOptionClick(option)"> {{option.value}} </li> <li *ngIf="shouldShowNoResultsMessage()" role="treeitem" aria-live="assertive" class="select2-results__option select2-results__message"> {{getNoResultsMessage()}} </li> <li *ngIf="shouldShowInputTooShortMessage()" role="treeitem" aria-live="assertive" class="select2-results__option select2-results__message"> {{getInputTooShortMessage()}} </li> <li *ngIf="shouldShowInputTooLongMessage()" role="treeitem" aria-live="assertive" class="select2-results__option select2-results__message"> {{getInputTooLongMessage()}} </li> </ul> </span> </span> </span> `, styles: [`.select2-container{display:block}`] },] }, ]; /** @nocollapse */ NgxSelect2ExDropdownComponent.ctorParameters = () => [ { type: NgxSelect2OptionFilterPipe, }, ]; NgxSelect2ExDropdownComponent.propDecorators = { "service": [{ type: Input },], "multi": [{ type: Input },], "theme": [{ type: Input },], "minimumResultsForSearch": [{ type: Input },], "minimumInputLength": [{ type: Input },], "maximumInputLength": [{ type: Input },], "language": [{ type: Input },], "display": [{ type: HostBinding, args: ['style.display',] },], "position": [{ type: HostBinding, args: ['style.position',] },], "top": [{ type: HostBinding, args: ['style.top',] },], "left": [{ type: HostBinding, args: ['style.left',] },], "right": [{ type: HostBinding, args: ['style.right',] },], "width": [{ type: HostBinding, args: ['style.width',] },], }; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class NgxSelect2ExDropdownInjectionService { /** * @param {?} applicationRef * @param {?} componentFactoryResolver * @param {?} injector */ constructor(applicationRef, componentFactoryResolver, injector) { this.applicationRef = applicationRef; this.componentFactoryResolver = componentFactoryResolver; this.injector = injector; } /** * @return {?} */ getRootViewContainer() { if (this._container) { return this._container; } const /** @type {?} */ rootComponents = this.applicationRef['components']; if (rootComponents.length) { return rootComponents[0]; } throw new Error('View Container not found! ngUpgrade needs to manually set this via setRootViewContainer.'); } /** * @param {?} container * @return {?} */ setRootViewContainer(container) { this._container = container; } /** * @param {?} componentRef * @return {?} */ getComponentRootNode(componentRef) { return /** @type {?} */ ((/** @type {?} */ (componentRef.hostView)).rootNodes[0]); } /** * @return {?} */ getRootViewContainerNode() { return this.getComponentRootNode(this.getRootViewContainer()); } /** * @param {?} component * @param {?} options * @return {?} */ projectComponentInputs(component, options) { if (options) { const /** @type {?} */ props = Object.getOwnPropertyNames(options); for (const /** @type {?} */ prop of props) { component.instance[prop] = options[prop]; } } return component; } /** * @template T * @param {?} componentClass * @param {?=} options * @param {?=} location * @return {?} */ appendComponent(componentClass, options = {}, location = this.getRootViewContainerNode()) { const /** @type {?} */ componentFactory = this.componentFactoryResolver.resolveComponentFactory(componentClass); const /** @type {?} */ componentRef = componentFactory.create(this.injector); const /** @type {?} */ appRef = this.applicationRef; const /** @type {?} */ componentRootNode = this.getComponentRootNode(componentRef); // project the options passed to the component instance this.projectComponentInputs(componentRef, options); appRef.attachView(componentRef.hostView); componentRef.onDestroy(() => { appRef.detachView(componentRef.hostView); }); location.appendChild(componentRootNode); return componentRef; } } NgxSelect2ExDropdownInjectionService.decorators = [ { type: Injectable }, ]; /** @nocollapse */ NgxSelect2ExDropdownInjectionService.ctorParameters = () => [ { type: ApplicationRef, }, { type: ComponentFactoryResolver, }, { type: Injector, }, ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @return {?} */ function _window() { // return the global native browser window object return window; } class WindowRef { constructor() { } /** * @return {?} */ get nativeWindow() { return _window(); } } WindowRef.decorators = [ { type: Injectable }, ]; /** @nocollapse */ WindowRef.ctorParameters = () => []; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class NgxSelect2ExDirective { /** * @param {?} el * @param {?} renderer * @param {?} ngxSelect2ExDropdownInjectionService * @param {?} winRef */ constructor(el, renderer, ngxSelect2ExDropdownInjectionService, winRef) { this.el = el; this.renderer = renderer; this.ngxSelect2ExDropdownInjectionService = ngxSelect2ExDropdownInjectionService; this.winRef = winRef; this.subscriptions = []; } /** * @return {?} */ ngOnInit() { this.updateDropdownPosition(); this.subscribeToSearchChanges(); } /** * @return {?} */ ngOnDestroy() { this.unsubscribe(); } /** * @param {?} targetElement * @return {?} */ onClick(targetElement) { const /** @type {?} */ dropdown = this.compRef ? this.compRef.location.nativeElement : null; const /** @type {?} */ clickedClearButton = targetElement.className === 'select2-selection__clear'; const /** @type {?} */ clickedDisabledOption = targetElement.hasAttribute('aria-disabled'); const /** @type {?} */ clickedNoOptionListItem = targetElement.className.includes('select2-results__message'); const /** @type {?} */ clickedSearchField = targetElement.className.includes('select2-search__field'); const /** @type {?} */ clickedRemoveChoice = targetElement.className.includes('select2-selection__choice__remove'); const /** @type {?} */ clickedDropdown = dropdown && dropdown.contains(targetElement); const /** @type {?} */ clickedInside = this.el.nativeElement.contains(targetElement) || clickedDropdown; if (clickedInside && !this.service.isOpen) { this.service.isInFocus = false; if (!this.service.disabled) { this.openDropdown(); } } else if (clickedInside && this.service.isOpen) { if (clickedDisabledOption || clickedNoOptionListItem || clickedSearchField || clickedClearButton) { this.service.isInFocus = false; } else { if (this.service.closeOnSelect || !clickedDropdown) { this.service.isInFocus = true; if (!clickedRemoveChoice) { this.closeDropdown(); } } } } else if (!clickedInside && this.service.isOpen) { this.service.isInFocus = false; this.closeDropdown(); } else if (!clickedInside && !this.service.isOpen) { this.service.isInFocus = false; } if (clickedInside) { if (!this.service.disabled) { this.setFocusForSearchField(this.compRef ? this.compRef.location.nativeElement : null); } if (this.service.multi && !clickedNoOptionListItem) { this.service.search = null; } } } /** * @return {?} */ resize() { this.updateDropdownPosition(); } /** * @return {?} */ openDropdown() { this.compRef = this.ngxSelect2ExDropdownInjectionService.appendComponent(NgxSelect2ExDropdownComponent, { service: this.service, multi: this.service.multi, theme: this.service.theme, minimumResultsForSearch: this.service.minimumResultsForSearch, minimumInputLength: this.service.minimumInputLength, maximumInputLength: this.service.maximumInputLength, language: this.service.language }); this.service.isOpen = true; this.updateDropdownPosition(); } /** * @return {?} */ closeDropdown() { if (this.compRef) { this.compRef.destroy(); this.compRef = null; } this.service.isOpen = false; } /** * @param {?} targetElement * @return {?} */ setFocusForSearchField(targetElement) { const /** @type {?} */ inlineSearchField = this.el.nativeElement ? this.el.nativeElement.getElementsByClassName('select2-search__field') : null; if (inlineSearchField && inlineSearchField.length) { inlineSearchField[0].focus(); } } /** * @return {?} */ subscribeToSearchChanges() { this.subscriptions.push(this.service.getSearchAsObservable().subscribe((search) => { if (this.service.multi) { if (search && !this.service.isOpen) { if (!this.service.disabled) { this.openDropdown(); } } this.updateDropdownPosition(); } })); } /** * @return {?} */ updateDropdownPosition() { this.renderer.setStyle(this.el.nativeElement, 'width', '100%'); const /** @type {?} */ boundingClientRect = this.el.nativeElement.getBoundingClientRect(); const /** @type {?} */ offsetTop = boundingClientRect.bottom + this.winRef.nativeWindow.scrollY; const /** @type {?} */ dropdownPosition = { top: offsetTop, left: boundingClientRect.left, width: boundingClientRect.width }; this.service.dropdownPosition = dropdownPosition; this.renderer.setStyle(this.el.nativeElement, 'width', `${boundingClientRect.width}px`); } /** * @return {?} */ unsubscribe() { this.subscriptions.forEach((subscription) => subscription.unsubscribe()); } } NgxSelect2ExDirective.decorators = [ { type: Directive, args: [{ selector: '[appNgxSelect2Ex]', providers: [WindowRef] },] }, ]; /** @nocollapse */ NgxSelect2ExDirective.ctorParameters = () => [ { type: ElementRef, }, { type: Renderer2, }, { type: NgxSelect2ExDropdownInjectionService, }, { type: WindowRef, }, ]; NgxSelect2ExDirective.propDecorators = { "service": [{ type: Input },], "onClick": [{ type: HostListener, args: ['document:mouseup', ['$event.target'],] },], "resize": [{ type: HostListener, args: ['window:resize',] },], }; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class NgxSelect2ExDropdownSearchFieldDirective { /** * @param {?} el */ constructor(el) { this.el = el; } /** * @return {?} */ ngOnInit() { this.setFocusForDropdownSearchField(); } /** * @return {?} */ setFocusForDropdownSearchField() { this.el.nativeElement.focus(); } } NgxSelect2ExDropdownSearchFieldDirective.decorators = [ { type: Directive, args: [{ selector: '[appNgxSelect2ExDropdownSearchField]' },] }, ]; /** @nocollapse */ NgxSelect2ExDropdownSearchFieldDirective.ctorParameters = () => [ { type: ElementRef, }, ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class NgxSelect2ExModule { } NgxSelect2ExModule.decorators = [ { type: NgModule, args: [{ imports: [ CommonModule, FormsModule ], declarations: [ NgxSelect2ExComponent, NgxSelect2ExDropdownComponent, NgxSelect2ExDirective, NgxSelect2ExDropdownSearchFieldDirective, NgxSelect2OptionFilterPipe ], exports: [NgxSelect2ExComponent], entryComponents: [NgxSelect2ExDropdownComponent], providers: [ NgxSelect2ExDropdownInjectionService, NgxSelect2OptionFilterPipe ] },] }, ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * Generated bundle index. Do not edit. */ export { NgxSelect2ExModule, NgxSelect2ExDropdownComponent as ɵc, NgxSelect2ExComponent as ɵa, NgxSelect2ExDropdownSearchFieldDirective as ɵh, NgxSelect2ExDirective as ɵe, NgxSelect2OptionFilterPipe as ɵd, NgxSelect2ExDropdownInjectionService as ɵg, NgxSelect2ExService as ɵb, WindowRef as ɵf }; //# sourceMappingURL=ngx-select2-ex.js.map