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

382 lines
11 KiB
JavaScript
Raw Normal View History

2018-02-10 15:18:01 +00:00
import ngModule from '../../module';
import Component from '../../lib/component';
import copyObject from '../../lib/copy';
2017-09-13 12:59:58 +00:00
import './style.scss';
2017-09-20 09:50:53 +00:00
class Autocomplete extends Component {
2017-11-09 09:11:59 +00:00
constructor($element, $scope, $http, $timeout, $filter) {
2017-09-20 09:50:53 +00:00
super($element);
2017-09-13 12:59:58 +00:00
this.$element = $element;
this.$scope = $scope;
this.$http = $http;
this.$timeout = $timeout;
2017-11-09 09:11:59 +00:00
this.$filter = $filter;
2017-09-13 12:59:58 +00:00
this._showDropDown = false;
this.finding = false;
this.findMore = false;
this._value = null;
this._field = null;
2017-09-20 09:50:53 +00:00
this._preLoad = false;
2017-09-13 12:59:58 +00:00
this.maxRow = 10;
this.showField = 'name';
this.valueField = 'id';
2017-11-09 09:11:59 +00:00
this.items = copyObject(this.data) || [];
2017-09-20 11:52:53 +00:00
this.displayValueMultiCheck = [];
this._multiField = [];
this.readonly = true;
this.removeLoadMore = false;
2018-01-24 07:42:57 +00:00
this.form = null;
this.findForm = false;
2017-09-13 12:59:58 +00:00
}
get showDropDown() {
return this._showDropDown;
}
2017-09-13 12:59:58 +00:00
set showDropDown(value) {
2017-09-20 09:50:53 +00:00
if (value && this.url && !this._preLoad) {
this._preLoad = true;
this.getItems();
}
if (value && !this.width) {
let rectangle = this.$element[0].getBoundingClientRect();
this.width = Math.round(rectangle.width) - 10;
}
2017-09-13 12:59:58 +00:00
this._showDropDown = value;
}
get displayValue() {
return this._value;
}
set displayValue(value) {
2017-09-20 11:52:53 +00:00
let val = (value === undefined || value === '') ? null : value;
if (this.multiple && val) {
let index = this.displayValueMultiCheck.indexOf(val);
if (index === -1)
this.displayValueMultiCheck.push(val);
else
this.displayValueMultiCheck.splice(index, 1);
this._value = this.displayValueMultiCheck.join(', ');
} else {
this._value = val;
}
2017-09-13 12:59:58 +00:00
if (value === null) {
this.field = null;
2017-09-20 11:52:53 +00:00
if (this.multiple && this.items.length) {
this.displayValueMultiCheck = [];
this.items.map(item => {
item.checked = false;
return item;
});
}
2017-09-13 12:59:58 +00:00
}
}
get field() {
2017-09-20 11:52:53 +00:00
return this.multiple ? this._multiField : this._field;
2017-09-13 12:59:58 +00:00
}
2017-09-13 12:59:58 +00:00
set field(value) {
2017-10-03 05:10:37 +00:00
if (!angular.equals(value, this.field)) {
this.finding = true;
if (value && value.hasOwnProperty(this.valueField)) {
this._field = value[this.valueField];
if (this.multiple) {
this.setMultiField(value[this.valueField]);
}
2018-01-24 07:42:57 +00:00
this.setDirtyForm();
2017-10-03 05:10:37 +00:00
} else {
this.setValue(value);
}
2017-09-20 09:50:53 +00:00
2017-10-03 05:10:37 +00:00
if (value && value.hasOwnProperty(this.showField))
this.displayValue = value[this.showField];
2017-09-20 09:50:53 +00:00
2017-10-03 05:10:37 +00:00
this.finding = false;
2017-09-20 11:52:53 +00:00
2017-10-03 05:10:37 +00:00
if (this.onChange)
this.onChange({item: this._field});
}
2017-09-20 09:50:53 +00:00
}
set initialData(value) {
2017-10-03 05:10:37 +00:00
if (value && value.hasOwnProperty(this.valueField)) {
this._field = value[this.valueField];
if (this.multiple) {
this._multiField = [value[this.valueField]];
2017-10-03 05:10:37 +00:00
}
if (value.hasOwnProperty(this.showField)) {
this.displayValue = value[this.showField];
}
2017-09-20 09:50:53 +00:00
}
}
2017-09-20 11:52:53 +00:00
setMultiField(val) {
if (val && typeof val === 'object' && val[this.valueField]) {
val = val[this.valueField];
}
if (val === null) {
this._multiField = [];
} else {
let index = this._multiField.indexOf(val);
if (index === -1) {
this._multiField.push(val);
} else {
this._multiField.splice(index, 1);
}
}
}
2017-09-20 09:50:53 +00:00
setValue(value) {
if (value) {
let data = this.items;
if (data && data.length)
for (let i = 0; i < data.length; i++)
if (data[i][this.valueField] === value) {
this.showItem(data[i]);
return;
}
this.requestItem(value);
} else {
this._field = null;
2017-09-20 11:52:53 +00:00
this.setMultiField(null);
2017-09-20 09:50:53 +00:00
this.displayValue = '';
}
}
requestItem(value) {
if (!value) return;
let where = {};
where[this.valueField] = value;
let filter = {
fields: this.getRequestFields(),
where: where
};
let json = JSON.stringify(filter);
this.$http.get(`${this.url}?filter=${json}`).then(
json => this.onItemRequest(json.data),
json => this.onItemRequest(null)
);
}
2017-09-20 09:50:53 +00:00
onItemRequest(data) {
if (data && data.length > 0)
this.showItem(data[0]);
else
this.showItem(null);
}
showItem(item) {
this.displayValue = item ? item[this.showField] : '';
this.field = item;
}
getRequestFields() {
let fields = {};
fields[this.valueField] = true;
fields[this.showField] = true;
if (this._selectFields)
for (let field of this._selectFields)
fields[field] = true;
return fields;
2017-09-13 12:59:58 +00:00
}
getOrder() {
return this.order ? this.order : `${this.showField} ASC`;
}
2017-09-13 12:59:58 +00:00
findItems(search) {
2017-11-09 09:11:59 +00:00
if (this.url && search && !this.finding) {
2017-09-14 11:40:55 +00:00
this.maxRow = false;
let filter = {};
if (this.filterSearch) {
let toSearch = this.filterSearch.replace(/search/g, search);
filter = this.$scope.$eval(toSearch);
} else {
filter = {where: {name: {regexp: search}}};
if (this.filter && this.filter.where) {
Object.assign(filter.where, this.filter.where);
}
}
filter.order = this.getOrder();
2017-09-13 12:59:58 +00:00
let json = JSON.stringify(filter);
this.finding = true;
this.$http.get(`${this.url}?filter=${json}`).then(
json => {
2017-09-20 11:52:53 +00:00
this.items = [];
json.data.forEach(
el => {
if (this.multiple) {
el.checked = this.field.indexOf(el[this.valueField]) !== -1;
}
this.items.push(el);
}
);
2017-09-13 12:59:58 +00:00
this.finding = false;
},
() => {
this.finding = false;
}
);
2017-11-09 09:11:59 +00:00
} else if (search && !this.url && this.data) {
this.items = this.$filter('filter')(this.data, search);
2017-09-13 12:59:58 +00:00
} else if (!search && !this.finding) {
2017-09-14 11:40:55 +00:00
this.maxRow = 10;
2017-09-13 12:59:58 +00:00
this.items = [];
this.getItems();
}
}
2017-09-13 12:59:58 +00:00
getItems() {
2017-11-09 09:11:59 +00:00
if (this.url === undefined) {
this.items = copyObject(this.data);
this.maxRow = false;
this.removeLoadMore = true;
} else {
let filter = {};
if (!this.finding) {
this.finding = true;
2017-09-13 12:59:58 +00:00
2017-11-09 09:11:59 +00:00
if (this.maxRow) {
if (this.items) {
filter.skip = this.items.length;
}
filter.limit = this.maxRow;
filter.order = this.getOrder();
2017-11-09 09:11:59 +00:00
}
if (this.filter) {
Object.assign(filter, this.filter);
2017-10-11 10:47:02 +00:00
}
2017-09-13 12:59:58 +00:00
2017-11-09 09:11:59 +00:00
let json = JSON.stringify(filter);
2017-09-13 12:59:58 +00:00
2017-11-09 09:11:59 +00:00
this.removeLoadMore = false;
2017-11-09 09:11:59 +00:00
this.$http.get(`${this.url}?filter=${json}`).then(
json => {
if (json.data.length) {
json.data.forEach(
el => {
if (this.multiple) {
el.checked = this.field.indexOf(el[this.valueField]) !== -1;
}
this.items.push(el);
2017-10-11 10:47:02 +00:00
}
2017-11-09 09:11:59 +00:00
);
if (filter.skip === 0 && this.maxRow && json.data.length < this.maxRow) {
this.removeLoadMore = true;
2017-09-20 11:52:53 +00:00
}
2017-11-09 09:11:59 +00:00
} else {
this.maxRow = false;
2017-09-13 12:59:58 +00:00
}
2017-11-09 09:11:59 +00:00
this.finding = false;
},
() => {
this.finding = false;
}
2017-11-09 09:11:59 +00:00
);
}
2017-10-11 10:47:02 +00:00
}
2017-09-13 12:59:58 +00:00
}
2018-01-24 07:42:57 +00:00
_parentForm() {
this.findForm = true;
let formScope = this.$scope;
while (formScope && !formScope.form && formScope.$id > 1) {
formScope = formScope.$parent;
}
this.form = formScope ? formScope.form || null : null;
}
setDirtyForm() {
if (!this.form && !this.findForm) {
this._parentForm();
}
if (this.form) {
this.form.$setDirty();
}
}
2017-09-13 12:59:58 +00:00
$onInit() {
this.findMore = this.url && this.maxRow;
2017-09-20 09:50:53 +00:00
this.mouseFocus = false;
this.focused = false;
2017-09-13 12:59:58 +00:00
this.$element.bind('mouseover', e => {
this.$timeout(() => {
2017-09-20 09:50:53 +00:00
this.mouseFocus = true;
this.showDropDown = this.focused;
2017-09-13 12:59:58 +00:00
});
});
this.$element.bind('mouseout', () => {
this.$timeout(() => {
2017-09-20 09:50:53 +00:00
this.mouseFocus = false;
this.showDropDown = this.focused;
2017-09-13 12:59:58 +00:00
});
});
2017-09-14 11:40:55 +00:00
this.$element.bind('focusin', e => {
this.$timeout(() => {
2017-09-20 09:50:53 +00:00
this.focused = true;
2017-09-14 11:40:55 +00:00
this.showDropDown = true;
});
});
this.$element.bind('focusout', e => {
this.$timeout(() => {
2017-09-20 09:50:53 +00:00
this.focused = false;
this.showDropDown = this.mouseFocus;
2017-09-14 11:40:55 +00:00
});
2017-09-20 09:50:53 +00:00
});
2017-09-14 11:40:55 +00:00
}
$onDestroy() {
this.$element.unbind('mouseover');
this.$element.unbind('mouseout');
this.$element.unbind('focusin');
this.$element.unbind('focusout');
2017-09-13 12:59:58 +00:00
}
2017-11-09 09:11:59 +00:00
$onChanges(objectChange) {
if (objectChange.data && objectChange.data.currentValue && objectChange.data.currentValue.length) {
this.items = copyObject(objectChange.data.currentValue);
this.maxRow = false;
this.removeLoadMore = true;
}
}
2017-09-13 12:59:58 +00:00
}
2017-11-09 09:11:59 +00:00
Autocomplete.$inject = ['$element', '$scope', '$http', '$timeout', '$filter'];
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: '@?',
showField: '@?',
valueField: '@?',
selectFields: '@?',
initialData: '<?',
onChange: '&?',
data: '<?',
field: '=',
2017-09-20 09:50:53 +00:00
label: '@',
2017-10-11 10:47:02 +00:00
multiple: '@?',
order: '@?',
filter: '<?',
filterSearch: '@?'
2017-09-20 09:50:53 +00:00
},
transclude: {
tplItem: '?tplItem'
2017-09-13 12:59:58 +00:00
}
});