salix/client/core/src/components/autocomplete/autocomplete.js

257 lines
6.5 KiB
JavaScript
Raw Normal View History

2018-02-10 15:18:01 +00:00
import ngModule from '../../module';
import Input from '../../lib/input';
2017-09-13 12:59:58 +00:00
import './style.scss';
2018-03-09 13:15:30 +00:00
/**
* Input with option selector.
*
* @property {String} valueField The data field name that should be shown
* @property {String} showFiled The data field name that should be used as value
* @property {Array} data Static data for the autocomplete
* @property {Object} intialData A initial data to avoid the server request used to get the selection
* @property {Boolean} multiple Wether to allow multiple selection
*/
export default class Autocomplete extends Input {
2018-03-09 13:15:30 +00:00
constructor($element, $scope, $http, $transclude) {
super($element, $scope);
2017-09-13 12:59:58 +00:00
this.$http = $http;
2018-03-09 13:15:30 +00:00
this.$transclude = $transclude;
this._field = undefined;
this._selection = null;
this.valueField = 'id';
2018-03-09 13:15:30 +00:00
this.showField = 'name';
2017-09-20 11:52:53 +00:00
this._multiField = [];
this.readonly = true;
2018-01-24 07:42:57 +00:00
this.form = null;
2018-03-09 13:15:30 +00:00
this.input = this.element.querySelector('.mdl-textfield__input');
2017-09-13 12:59:58 +00:00
2018-03-09 13:15:30 +00:00
componentHandler.upgradeElement(
this.element.querySelector('.mdl-textfield'));
2017-09-13 12:59:58 +00:00
}
2018-03-09 13:15:30 +00:00
/**
* @type {any} The autocomplete value.
*/
get field() {
return this._field;
2017-09-13 12:59:58 +00:00
}
2018-03-09 13:15:30 +00:00
set field(value) {
if (angular.equals(value, this._field))
return;
2017-09-13 12:59:58 +00:00
2018-03-09 13:15:30 +00:00
this._field = value;
this.refreshSelection();
2017-09-20 11:52:53 +00:00
2018-03-09 13:15:30 +00:00
if (this.onChange)
2018-04-04 13:03:13 +00:00
this.onChange({value});
2018-03-09 13:15:30 +00:00
}
2017-09-20 11:52:53 +00:00
2018-03-09 13:15:30 +00:00
/**
* @type {Object} The selected data object, you can use this property
* to prevent requests to display the initial value.
*/
get selection() {
return this._selection;
2017-09-13 12:59:58 +00:00
}
2018-03-09 13:15:30 +00:00
set selection(value) {
this._selection = value;
this.refreshDisplayed();
2017-09-13 12:59:58 +00:00
}
2018-03-09 13:15:30 +00:00
selectionIsValid(selection) {
return selection
&& selection[this.valueField] == this._field
&& selection[this.showField] != null;
}
2017-09-20 09:50:53 +00:00
2018-03-09 13:15:30 +00:00
refreshSelection() {
if (this.selectionIsValid(this._selection))
return;
2017-09-20 09:50:53 +00:00
2018-03-09 13:15:30 +00:00
let value = this._field;
2017-09-20 11:52:53 +00:00
2018-03-09 13:15:30 +00:00
if (value && this.valueField && this.showField) {
if (this.selectionIsValid(this.initialData)) {
this.selection = this.initialData;
return;
2017-10-03 05:10:37 +00:00
}
2017-09-20 09:50:53 +00:00
2018-03-09 13:15:30 +00:00
let data = this.data;
2017-09-20 11:52:53 +00:00
2018-03-09 13:15:30 +00:00
if (!data && this.$.dropDown)
data = this.$.dropDown.$.model.data;
2017-09-20 09:50:53 +00:00
2018-03-09 13:15:30 +00:00
if (data)
2017-09-20 09:50:53 +00:00
for (let i = 0; i < data.length; i++)
if (data[i][this.valueField] === value) {
2018-03-09 13:15:30 +00:00
this.selection = data[i];
2017-09-20 09:50:53 +00:00
return;
}
2018-03-09 13:15:30 +00:00
if (this.url) {
this.requestSelection(value);
return;
}
} else
this.selection = null;
2017-09-20 09:50:53 +00:00
}
2018-03-09 13:15:30 +00:00
requestSelection(value) {
2017-09-20 09:50:53 +00:00
let where = {};
2018-03-09 13:15:30 +00:00
if (this.multiple)
where[this.valueField] = {inq: this.field};
else
where[this.valueField] = value;
2017-09-20 09:50:53 +00:00
let filter = {
2018-03-09 13:15:30 +00:00
fields: this.getFields(),
2017-09-20 09:50:53 +00:00
where: where
};
2018-03-09 13:15:30 +00:00
let json = encodeURIComponent(JSON.stringify(filter));
2017-09-20 09:50:53 +00:00
this.$http.get(`${this.url}?filter=${json}`).then(
2018-03-09 13:15:30 +00:00
json => this.onSelectionRequest(json.data),
() => this.onSelectionRequest(null)
2017-09-20 09:50:53 +00:00
);
}
2018-03-09 13:15:30 +00:00
onSelectionRequest(data) {
if (data && data.length > 0) {
if (this.multiple)
this.selection = data;
else
this.selection = data[0];
} else
this.selection = null;
2017-09-20 09:50:53 +00:00
}
2018-03-09 13:15:30 +00:00
refreshDisplayed() {
let display = '';
if (this._selection && this.showField) {
if (this.multiple && Array.isArray(this._selection)) {
for (var item of this._selection) {
if (display.length > 0) display += ', ';
display += item[this.showField];
}
} else {
display = this._selection[this.showField];
}
}
this.input.value = display;
this.mdlUpdate();
2017-09-20 09:50:53 +00:00
}
2018-03-09 13:15:30 +00:00
getFields() {
let fields = [];
fields.push(this.valueField);
fields.push(this.showField);
2017-09-20 09:50:53 +00:00
2018-03-09 13:15:30 +00:00
if (this.selectFields)
for (let field of this.selectFields)
fields.push(field);
2017-09-20 09:50:53 +00:00
return fields;
2017-09-13 12:59:58 +00:00
}
2018-03-09 13:15:30 +00:00
mdlUpdate() {
let field = this.element.querySelector('.mdl-textfield');
let mdlField = field.MaterialTextfield;
if (mdlField) mdlField.updateClasses_();
}
2018-03-09 13:15:30 +00:00
setValue(value) {
this.field = value;
if (this.form) this.form.$setDirty();
2017-09-13 12:59:58 +00:00
}
2018-03-09 13:15:30 +00:00
onDropDownSelect(value) {
this.setValue(value);
this.field = value;
2017-09-13 12:59:58 +00:00
}
2018-03-09 13:15:30 +00:00
onClearClick(event) {
event.preventDefault();
this.setValue(null);
2018-01-24 07:42:57 +00:00
}
2018-03-09 13:15:30 +00:00
onKeyDown(event) {
if (event.defaultPrevented) return;
2017-09-13 12:59:58 +00:00
2018-03-09 13:15:30 +00:00
switch (event.keyCode) {
case 38: // Up
case 40: // Down
case 13: // Enter
this.showDropDown();
break;
default:
if (event.key.length == 1)
this.showDropDown(event.key);
else
return;
}
2017-09-13 12:59:58 +00:00
2018-03-09 13:15:30 +00:00
event.preventDefault();
2017-09-14 11:40:55 +00:00
}
2018-03-09 13:15:30 +00:00
onMouseDown(event) {
event.preventDefault();
this.showDropDown();
2017-09-13 12:59:58 +00:00
}
2018-03-09 13:15:30 +00:00
showDropDown(search) {
Object.assign(this.$.dropDown.$.model, {
url: this.url,
staticData: this.data
});
2017-11-09 09:11:59 +00:00
2018-03-09 13:15:30 +00:00
Object.assign(this.$.dropDown, {
valueField: this.valueField,
showField: this.showField,
selectFields: this.getFields(),
where: this.where,
order: this.order,
parent: this.input,
multiple: this.multiple,
limit: this.limit,
$transclude: this.$transclude
});
this.$.dropDown.show(search);
}
2017-09-13 12:59:58 +00:00
}
2018-03-09 13:15:30 +00:00
Autocomplete.$inject = ['$element', '$scope', '$http', '$transclude'];
2017-09-13 12:59:58 +00:00
2018-02-10 15:18:01 +00:00
ngModule.component('vnAutocomplete', {
2017-09-13 12:59:58 +00:00
template: require('./autocomplete.html'),
controller: Autocomplete,
bindings: {
url: '@?',
2018-03-09 13:15:30 +00:00
data: '<?',
2017-09-13 12:59:58 +00:00
showField: '@?',
valueField: '@?',
2018-03-09 13:15:30 +00:00
selectFields: '<?',
2018-04-04 13:03:13 +00:00
disabled: '<?',
2018-03-09 13:15:30 +00:00
where: '@?',
order: '@?',
2018-03-09 13:15:30 +00:00
label: '@',
initialData: '<?',
field: '=?',
limit: '<?',
showFilter: '<?',
selection: '<?',
multiple: '<?',
onChange: '&?'
2017-09-20 09:50:53 +00:00
},
transclude: {
tplItem: '?tplItem'
2018-03-09 13:15:30 +00:00
},
require: {
form: '?^form'
2017-09-13 12:59:58 +00:00
}
});