ng-selector
Version:
Angular2 selector component based on selectize.js
410 lines (403 loc) • 13.5 kB
JavaScript
import { CommonModule } from '@angular/common';
import { Attribute, Component, Directive, EventEmitter, Input, NgModule, Output, ViewChild, forwardRef } from '@angular/core';
import { FormsModule, NG_VALIDATORS, NG_VALUE_ACCESSOR } from '@angular/forms';
import * as jqueryProxy from 'jquery';
import jqueryProxy__default from 'jquery';
import 'selectize';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
// rollup dirty fix : https://github.com/rollup/rollup/issues/1267
var jQuery = jqueryProxy__default || jqueryProxy;
var NgSelectorComponent = (function () {
function NgSelectorComponent(placeholder, idField, labelField, allowCreation) {
if (placeholder === void 0) { placeholder = ''; }
if (idField === void 0) { idField = 'id'; }
if (labelField === void 0) { labelField = 'label'; }
if (allowCreation === void 0) { allowCreation = true; }
this.placeholder = placeholder;
this.idField = idField;
this.labelField = labelField;
this.allowCreation = allowCreation;
this.plugins = new Array();
// async input options (function which provide data)
this.loadValues = new EventEmitter();
// rendering method to change display of item and options
this.renderer = new EventEmitter();
this._disabled = false;
this._mutiple = false;
this.onChange = function (_) { };
this.onTouched = function () { };
}
Object.defineProperty(NgSelectorComponent.prototype, "readonly", {
set: /**
* @param {?} disabled
* @return {?}
*/
function (disabled) {
this._disabled = disabled;
this.checkDisabled();
},
enumerable: true,
configurable: true
});
Object.defineProperty(NgSelectorComponent.prototype, "options", {
set: /**
* @param {?} values
* @return {?}
*/
function (values) {
this.optionsChanged(values);
},
enumerable: true,
configurable: true
});
Object.defineProperty(NgSelectorComponent.prototype, "multiple", {
get: /**
* @return {?}
*/
function () { return this._mutiple; },
set: /**
* @param {?} value
* @return {?}
*/
function (value) {
this._mutiple = value;
// this.selectize.maxItems = this.multiple ? null : 1,
if (this.selectize)
this.selectize.maxItems = this.checkMultipleFalsy();
},
enumerable: true,
configurable: true
});
/**
* @return {?}
*/
NgSelectorComponent.prototype.ngAfterViewInit = /**
* @return {?}
*/
function () {
var _this = this;
// initialize with default values
this.placeholder = this.placeholder || '';
this.idField = this.idField || 'id';
this.labelField = this.labelField || 'label';
this.multiple = this.multiple === undefined ? false : this.multiple;
this.allowCreation = this.allowCreation === undefined ? true : this.allowCreation;
var /** @type {?} */ render;
if (this.renderer.observers.length === 1) {
render = {
option: this.rendering('option'),
item: this.rendering('item'),
};
}
// prepare selectize compatible method to fetch data
var /** @type {?} */ load = null;
if (this.loadValues.observers.length === 1) {
load = function (query, callback) {
// TODO find a way to display it to user
// disabled async search if search string is below 3 characters long
if (query.length < 3) {
return callback([]);
}
_this.loadValues.emit({ query: query, result: callback });
};
}
var /** @type {?} */ plugins = [].concat(this.plugins);
// configure Selectize
this.selectize = (/** @type {?} */ (jQuery(this.selector.nativeElement))).selectize(/** @type {?} */ ({
valueField: this.idField,
labelField: this.labelField,
searchField: this.labelField,
placeholder: this.placeholder,
maxItems: this.checkMultipleFalsy(),
create: this.allowCreation,
selectOnTab: true,
persist: true,
load: load,
render: render,
plugins: plugins,
onChange: this.dataChanged.bind(this)
}))[0].selectize;
// force form-control on
jQuery(this.selector.nativeElement).siblings().find('.selectize-input').addClass('form-control');
// force refresh data when Selectize is initialized
this.optionsChanged(this.tmpOptions);
this.updateData(this.data);
this.checkDisabled();
};
/**
* @param {?} options
* @return {?}
*/
NgSelectorComponent.prototype.optionsChanged = /**
* @param {?} options
* @return {?}
*/
function (options) {
var _this = this;
if (!options || !Object.keys(options).length) {
return this.selectize && this.selectize.clearOptions();
}
if (this.selectize) {
Object.keys(this.selectize.options).forEach(function (id) {
if (!options.find(function (elem) { return elem[_this.idField] === _this.selectize.options[id][_this.idField]; })) {
_this.selectize.removeOption(id);
}
});
// this.tagsComponent.options = options;
options.forEach(function (option) {
var /** @type {?} */ value = option[_this.idField];
// check if option exist to call the right method ... sorry ... -_-
if (_this.selectize.options[value]) {
_this.selectize.updateOption(value, option);
}
else {
_this.selectize.addOption(option);
}
});
this.selectize.refreshOptions(false);
}
else {
this.tmpOptions = options;
}
};
/**
* @param {?} value
* @return {?}
*/
NgSelectorComponent.prototype.dataChanged = /**
* @param {?} value
* @return {?}
*/
function (value) {
var _this = this;
if (!value || !value.length) {
return this.onChange(this.multiple ? [] : null);
}
if (this.multiple) {
var /** @type {?} */ selectedValues = value
.map(function (id) { return _this.selectize.options[id]; })
.filter(function (item) { return !!item; })
.map(this.cleanOrder);
this.onChange(selectedValues);
}
else {
this.onChange(this.cleanOrder(this.selectize.options[value]));
}
};
/**
* @param {?} data
* @return {?}
*/
NgSelectorComponent.prototype.updateData = /**
* @param {?} data
* @return {?}
*/
function (data) {
var _this = this;
// component not initialized yet
if (!this.selectize)
return;
if (!data) {
this.selectize.clear();
return;
}
this.selectize.addOption(data);
if (Array.isArray(data)) {
this.selectize.setValue(data.map(function (item) { return item[_this.idField]; }));
}
else if (data && typeof data === 'object') {
this.selectize.setValue(data[this.idField]);
}
};
/**
* @return {?}
*/
NgSelectorComponent.prototype.checkDisabled = /**
* @return {?}
*/
function () {
if (!this.selectize)
return;
if (this._disabled === true) {
this.selectize.disable();
}
else if (this._disabled === false) {
this.selectize.enable();
}
};
/**
* @param {?} type
* @return {?}
*/
NgSelectorComponent.prototype.rendering = /**
* @param {?} type
* @return {?}
*/
function (type) {
var _this = this;
return function (i) {
var /** @type {?} */ html = i[_this.labelField];
_this.renderer.emit({ val: i, html: function (htmlContent) { return html = htmlContent; }, type: type });
return html;
};
};
/**
* @param {?} value
* @return {?}
*/
NgSelectorComponent.prototype.writeValue = /**
* @param {?} value
* @return {?}
*/
function (value) {
this.updateData(value);
};
/**
* @param {?} fn
* @return {?}
*/
NgSelectorComponent.prototype.registerOnChange = /**
* @param {?} fn
* @return {?}
*/
function (fn) {
this.onChange = fn;
};
/**
* @param {?} fn
* @return {?}
*/
NgSelectorComponent.prototype.registerOnTouched = /**
* @param {?} fn
* @return {?}
*/
function (fn) {
this.onTouched = fn;
};
/**
* @param {?} item
* @return {?}
*/
NgSelectorComponent.prototype.cleanOrder = /**
* @param {?} item
* @return {?}
*/
function (item) {
delete item.$order;
return item;
};
/**
* @return {?}
*/
NgSelectorComponent.prototype.checkMultipleFalsy = /**
* @return {?}
*/
function () {
return (this.multiple) ? null : 1;
};
NgSelectorComponent.decorators = [
{ type: Component, args: [{
selector: 'ng-selector',
template: "<select #selector></select>",
providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(function () { return NgSelectorComponent; }), multi: true }]
},] },
];
/** @nocollapse */
NgSelectorComponent.ctorParameters = function () { return [
{ type: undefined, decorators: [{ type: Attribute, args: ['placeholder',] },] },
{ type: undefined, decorators: [{ type: Attribute, args: ['id-field',] },] },
{ type: undefined, decorators: [{ type: Attribute, args: ['label-field',] },] },
{ type: undefined, decorators: [{ type: Attribute, args: ['allow-creation',] },] },
]; };
NgSelectorComponent.propDecorators = {
"selector": [{ type: ViewChild, args: ['selector',] },],
"readonly": [{ type: Input },],
"options": [{ type: Input },],
"plugins": [{ type: Input },],
"loadValues": [{ type: Output },],
"renderer": [{ type: Output },],
"multiple": [{ type: Input, args: ['multiple',] },],
};
return NgSelectorComponent;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var NgSelectorValidator = (function () {
function NgSelectorValidator() {
}
/**
* @param {?} c
* @return {?}
*/
NgSelectorValidator.prototype.validate = /**
* @param {?} c
* @return {?}
*/
function (c) {
return this.isEmpty(c.value) ? { required: { valid: false } } : null;
};
/**
* @param {?} value
* @return {?}
*/
NgSelectorValidator.prototype.isEmpty = /**
* @param {?} value
* @return {?}
*/
function (value) {
if (value === null || value === undefined) {
return true;
}
// empty array
if (Array.isArray(value) && value.length > 0) {
return false;
}
// all objects are valids
if (!Array.isArray(value) && typeof value === 'object' && Object.keys(value).length > 0) {
return false;
}
return true;
};
NgSelectorValidator.decorators = [
{ type: Directive, args: [{
selector: 'ng-selector[required][ngModel]',
providers: [{ provide: NG_VALIDATORS, useClass: NgSelectorValidator, multi: true }]
},] },
];
/** @nocollapse */
NgSelectorValidator.ctorParameters = function () { return []; };
return NgSelectorValidator;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var NgSelectorModule = (function () {
function NgSelectorModule() {
}
NgSelectorModule.decorators = [
{ type: NgModule, args: [{
imports: [
CommonModule,
FormsModule,
],
declarations: [
NgSelectorComponent,
NgSelectorValidator,
],
exports: [
NgSelectorComponent,
NgSelectorValidator,
]
},] },
];
/** @nocollapse */
NgSelectorModule.ctorParameters = function () { return []; };
return NgSelectorModule;
}());
export { NgSelectorModule, NgSelectorComponent, NgSelectorValidator };