ui autocomplete usage
This commit is contained in:
@@ -51,14 +51,12 @@ class AssignedUserFieldView extends UserWithAvatarFieldView {
|
||||
}
|
||||
|
||||
getEmptyAutocompleteResult() {
|
||||
return {
|
||||
list: [
|
||||
{
|
||||
id: this.getUser().id,
|
||||
name: this.getUser().get('name'),
|
||||
}
|
||||
]
|
||||
};
|
||||
return [
|
||||
{
|
||||
id: this.getUser().id,
|
||||
name: this.getUser().get('name'),
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
import BaseFieldView from 'views/fields/base';
|
||||
import RecordModal from 'helpers/record-modal';
|
||||
import Autocomplete from 'ui/autocomplete';
|
||||
|
||||
/**
|
||||
* A link-multiple field (for has-many relations).
|
||||
@@ -518,69 +519,16 @@ class LinkMultipleFieldView extends BaseFieldView {
|
||||
if (this.isEditMode() || this.isSearchMode()) {
|
||||
this.$element = this.$el.find('input.main-element');
|
||||
|
||||
const $element = this.$element;
|
||||
|
||||
if (!this.autocompleteDisabled) {
|
||||
// Does not work well with autocompleteOnEmpty.
|
||||
/*this.$element.on('blur', () => {
|
||||
setTimeout(() => this.$element.autocomplete('clear'), 300);
|
||||
});*/
|
||||
|
||||
const minChar = this.autocompleteOnEmpty ? 0 : 1;
|
||||
|
||||
this.$element.autocomplete({
|
||||
lookup: (q, callback) => {
|
||||
Promise.resolve(this.getAutocompleteUrl(q))
|
||||
.then(url => {
|
||||
Espo.Ajax
|
||||
.getRequest(url, {q: q})
|
||||
.then(response => {
|
||||
callback(this._transformAutocompleteResult(response));
|
||||
});
|
||||
});
|
||||
},
|
||||
minChars: minChar,
|
||||
paramName: 'q',
|
||||
noCache: true,
|
||||
const autocomplete = new Autocomplete(this.$element.get(0), {
|
||||
minChars: this.autocompleteOnEmpty ? 0 : 1,
|
||||
focusOnSelect: true,
|
||||
handleFocusMode: 3,
|
||||
autoSelectFirst: true,
|
||||
triggerSelectOnValidInput: false,
|
||||
beforeRender: $c => {
|
||||
if (this.$element.hasClass('input-sm')) {
|
||||
$c.addClass('small');
|
||||
}
|
||||
|
||||
// Prevent an issue that suggestions are shown and not hidden
|
||||
// when clicking outside the window and then focusing back on the document.
|
||||
if (this.$element.get(0) !== document.activeElement) {
|
||||
setTimeout(() => this.$element.autocomplete('hide'), 30);
|
||||
}
|
||||
},
|
||||
formatResult: suggestion => {
|
||||
// noinspection JSUnresolvedReference
|
||||
return this.getHelper().escapeString(suggestion.name);
|
||||
},
|
||||
transformResult: response => {
|
||||
response = JSON.parse(response);
|
||||
|
||||
const list = [];
|
||||
|
||||
response.list.forEach((item) => {
|
||||
list.push({
|
||||
id: item.id,
|
||||
name: item.name || item.id,
|
||||
data: item.id,
|
||||
value: item.name || item.id,
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
suggestions: list
|
||||
};
|
||||
},
|
||||
onSelect: s => {
|
||||
forceHide: true,
|
||||
onSelect: item => {
|
||||
this.getModelFactory().create(this.foreignScope, model => {
|
||||
// noinspection JSUnresolvedReference
|
||||
model.set(s.attributes);
|
||||
model.set(item.attributes);
|
||||
|
||||
this.select([model])
|
||||
|
||||
@@ -588,23 +536,20 @@ class LinkMultipleFieldView extends BaseFieldView {
|
||||
this.$element.focus();
|
||||
});
|
||||
},
|
||||
lookupFunction: query => {
|
||||
return Espo.Ajax.getRequest(this.getAutocompleteUrl(query), {q: query})
|
||||
.then(/** {list: Record[]} */response => {
|
||||
return response.list.map(item => ({
|
||||
value: item.name,
|
||||
attributes: item,
|
||||
}));
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
this.$element.attr('autocomplete', 'espo-' + this.name);
|
||||
|
||||
this.once('render', () => {
|
||||
$element.autocomplete('dispose');
|
||||
});
|
||||
|
||||
this.once('remove', () => {
|
||||
$element.autocomplete('dispose');
|
||||
});
|
||||
this.once('render remove', () => autocomplete.dispose());
|
||||
}
|
||||
|
||||
$element.on('change', () => {
|
||||
$element.val('');
|
||||
});
|
||||
|
||||
this.renderLinks();
|
||||
|
||||
if (this.isEditMode()) {
|
||||
@@ -1123,25 +1068,6 @@ class LinkMultipleFieldView extends BaseFieldView {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_transformAutocompleteResult(response) {
|
||||
const list = [];
|
||||
|
||||
response.list.forEach(item => {
|
||||
list.push({
|
||||
id: item.id,
|
||||
name: item.name || item.id,
|
||||
data: item.id,
|
||||
value: item.name || item.id,
|
||||
attributes: item,
|
||||
});
|
||||
});
|
||||
|
||||
return {suggestions: list};
|
||||
}
|
||||
|
||||
actionCreateLink() {
|
||||
const viewName = this.getMetadata().get(['clientDefs', this.foreignScope, 'modalViews', 'edit']) ||
|
||||
'views/modals/edit';
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
import BaseFieldView from 'views/fields/base';
|
||||
import RecordModal from 'helpers/record-modal';
|
||||
import Select from 'ui/select';
|
||||
import Autocomplete from 'ui/autocomplete';
|
||||
|
||||
/**
|
||||
* A link-parent field (belongs-to-parent relation).
|
||||
@@ -498,82 +499,40 @@ class LinkParentFieldView extends BaseFieldView {
|
||||
e.currentTarget.value = this.model.get(this.nameName) || '';
|
||||
}
|
||||
}, 100);
|
||||
|
||||
if (!this.autocompleteDisabled) {
|
||||
setTimeout(() => this.$elementName.autocomplete('clear'), 300);
|
||||
}
|
||||
});
|
||||
|
||||
if (!this.autocompleteDisabled) {
|
||||
this.$elementName.autocomplete({
|
||||
serviceUrl: (q) => {
|
||||
return this.getAutocompleteUrl(q);
|
||||
},
|
||||
minChars: this.autocompleteOnEmpty ? 0 : 1,
|
||||
paramName: 'q',
|
||||
triggerSelectOnValidInput: false,
|
||||
const autocomplete = new Autocomplete(this.$elementName.get(0), {
|
||||
name: this.name,
|
||||
focusOnSelect: true,
|
||||
handleFocusMode: 2,
|
||||
autoSelectFirst: true,
|
||||
noCache: true,
|
||||
beforeRender: ($c) => {
|
||||
if (this.$elementName.hasClass('input-sm')) {
|
||||
$c.addClass('small');
|
||||
}
|
||||
},
|
||||
formatResult: (/** Record */suggestion) => {
|
||||
return this.getHelper().escapeString(suggestion.name);
|
||||
},
|
||||
transformResult: (response) => {
|
||||
response = JSON.parse(response);
|
||||
const list = [];
|
||||
|
||||
response.list.forEach(item => {
|
||||
list.push({
|
||||
id: item.id,
|
||||
name: item.name || item.id,
|
||||
data: item.id,
|
||||
value: item.name || item.id,
|
||||
attributes: item,
|
||||
});
|
||||
});
|
||||
|
||||
return {suggestions: list};
|
||||
},
|
||||
onSelect: (/** Record */s) => {
|
||||
this.getModelFactory().create(this.foreignScope, (model) => {
|
||||
model.set(s.attributes);
|
||||
forceHide: true,
|
||||
minChars: this.autocompleteOnEmpty ? 0 : 1,
|
||||
onSelect: item => {
|
||||
this.getModelFactory().create(this.foreignScope, model => {
|
||||
model.set(item.attributes);
|
||||
|
||||
this.select(model);
|
||||
this.$elementName.focus();
|
||||
});
|
||||
},
|
||||
lookupFunction: query => {
|
||||
return Promise.resolve(this.getAutocompleteUrl(query))
|
||||
.then(url => Espo.Ajax.getRequest(url, {q: query}))
|
||||
.then(/** {list: Record[]} */response => {
|
||||
return response.list.map(item => ({
|
||||
value: item.name,
|
||||
attributes: item,
|
||||
}));
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
this.$elementName.off('focus.autocomplete');
|
||||
|
||||
this.$elementName.on('focus', () => {
|
||||
if (this.$elementName.val()) {
|
||||
this.$elementName.get(0).select();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.$elementName.autocomplete('onFocus');
|
||||
});
|
||||
|
||||
this.$elementName.attr('autocomplete', 'espo-' + this.name);
|
||||
this.once('render remove', () => autocomplete.dispose());
|
||||
|
||||
Select.init(this.$elementType, {});
|
||||
}
|
||||
|
||||
const $elementName = this.$elementName;
|
||||
|
||||
this.once('render', () => {
|
||||
$elementName.autocomplete('dispose');
|
||||
});
|
||||
|
||||
this.once('remove', () => {
|
||||
$elementName.autocomplete('dispose');
|
||||
});
|
||||
}
|
||||
|
||||
if (this.isSearchMode()) {
|
||||
|
||||
+49
-105
@@ -30,6 +30,7 @@
|
||||
|
||||
import BaseFieldView from 'views/fields/base';
|
||||
import RecordModal from 'helpers/record-modal';
|
||||
import Autocomplete from 'ui/autocomplete';
|
||||
|
||||
/**
|
||||
* A link field (belongs-to relation).
|
||||
@@ -604,10 +605,6 @@ class LinkFieldView extends BaseFieldView {
|
||||
e.currentTarget.value = this.model.get(this.nameName);
|
||||
}
|
||||
}, 100);
|
||||
|
||||
if (!this.autocompleteDisabled) {
|
||||
setTimeout(() => this.$elementName.autocomplete('clear'), 300);
|
||||
}
|
||||
});
|
||||
|
||||
const $elementName = this.$elementName;
|
||||
@@ -623,111 +620,54 @@ class LinkFieldView extends BaseFieldView {
|
||||
});
|
||||
}
|
||||
|
||||
this.$elementName.autocomplete({
|
||||
beforeRender: $c => {
|
||||
if (this.$elementName.hasClass('input-sm')) {
|
||||
$c.addClass('small');
|
||||
}
|
||||
|
||||
// Prevent an issue that suggestions are shown and not hidden
|
||||
// when clicking outside the window and then focusing back on the document.
|
||||
if (this.$elementName.get(0) !== document.activeElement) {
|
||||
setTimeout(() => this.$elementName.autocomplete('hide'), 30);
|
||||
}
|
||||
},
|
||||
lookup: (q, callback) => {
|
||||
if (!this.autocompleteOnEmpty && q.length === 0) {
|
||||
isEmptyQueryResult = true;
|
||||
|
||||
const emptyResult = this.getEmptyAutocompleteResult();
|
||||
|
||||
if (emptyResult) {
|
||||
callback(this._transformAutocompleteResult(emptyResult));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
isEmptyQueryResult = false;
|
||||
|
||||
Promise.resolve(this.getAutocompleteUrl(q))
|
||||
.then(url => {
|
||||
Espo.Ajax
|
||||
.getRequest(url, {q: q})
|
||||
.then(response => {
|
||||
callback(this._transformAutocompleteResult(response));
|
||||
});
|
||||
});
|
||||
},
|
||||
minChars: 0,
|
||||
triggerSelectOnValidInput: false,
|
||||
const autocomplete = new Autocomplete(this.$elementName.get(0), {
|
||||
name: this.name,
|
||||
handleFocusMode: 2,
|
||||
autoSelectFirst: true,
|
||||
noCache: true,
|
||||
formatResult: suggestion => {
|
||||
// noinspection JSUnresolvedReference
|
||||
return this.getHelper().escapeString(suggestion.name);
|
||||
},
|
||||
onSelect: s => {
|
||||
this.getModelFactory().create(this.foreignScope, (model) => {
|
||||
// noinspection JSUnresolvedReference
|
||||
model.set(s.attributes);
|
||||
|
||||
forceHide: true,
|
||||
onSelect: item => {
|
||||
this.getModelFactory().create(this.foreignScope, model => {
|
||||
model.set(item.attributes);
|
||||
this.select(model);
|
||||
|
||||
this.$elementName.focus();
|
||||
});
|
||||
},
|
||||
lookupFunction: query => {
|
||||
if (!this.autocompleteOnEmpty && query.length === 0) {
|
||||
isEmptyQueryResult = true;
|
||||
|
||||
const emptyResult = this.getEmptyAutocompleteResult();
|
||||
|
||||
if (emptyResult) {
|
||||
return Promise.resolve(this._transformAutocompleteResult({list: emptyResult}));
|
||||
}
|
||||
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
|
||||
isEmptyQueryResult = false;
|
||||
|
||||
return Promise.resolve(this.getAutocompleteUrl(query))
|
||||
.then(url => Espo.Ajax.getRequest(url, {q: query}))
|
||||
.then(response => this._transformAutocompleteResult(response));
|
||||
},
|
||||
});
|
||||
|
||||
this.$elementName.off('focus.autocomplete');
|
||||
|
||||
this.$elementName.on('focus', () => {
|
||||
if (this.$elementName.val()) {
|
||||
this.$elementName.get(0).select();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.$elementName.autocomplete('onFocus');
|
||||
});
|
||||
|
||||
this.$elementName.attr('autocomplete', 'espo-' + this.name);
|
||||
|
||||
this.once('render', () => {
|
||||
$elementName.autocomplete('dispose');
|
||||
});
|
||||
|
||||
this.once('remove', () => {
|
||||
$elementName.autocomplete('dispose');
|
||||
});
|
||||
this.once('render remove', () => autocomplete.dispose());
|
||||
|
||||
if (this.isSearchMode()) {
|
||||
const $elementOneOf = this.$el.find('input.element-one-of');
|
||||
|
||||
// noinspection JSCheckFunctionSignatures
|
||||
$elementOneOf.autocomplete({
|
||||
beforeRender: $c => {
|
||||
if (this.$elementName.hasClass('input-sm')) {
|
||||
$c.addClass('small');
|
||||
}
|
||||
},
|
||||
serviceUrl: () => {
|
||||
return this.getAutocompleteUrl();
|
||||
},
|
||||
const autocomplete = new Autocomplete($elementOneOf.get(0), {
|
||||
minChars: 1,
|
||||
paramName: 'q',
|
||||
noCache: true,
|
||||
formatResult: suggestion => {
|
||||
// noinspection JSUnresolvedReference
|
||||
return this.getHelper().escapeString(suggestion.name);
|
||||
},
|
||||
transformResult: response => {
|
||||
return this._transformAutocompleteResult(JSON.parse(response));
|
||||
},
|
||||
onSelect: s => {
|
||||
focusOnSelect: true,
|
||||
handleFocusMode: 3,
|
||||
autoSelectFirst: true,
|
||||
forceHide: true,
|
||||
onSelect: item => {
|
||||
this.getModelFactory().create(this.foreignScope, model => {
|
||||
// noinspection JSUnresolvedReference
|
||||
model.set(s.attributes);
|
||||
model.set(item.attributes);
|
||||
|
||||
this.selectOneOf([model]);
|
||||
|
||||
@@ -735,17 +675,18 @@ class LinkFieldView extends BaseFieldView {
|
||||
setTimeout(() => $elementOneOf.focus(), 50);
|
||||
});
|
||||
},
|
||||
lookupFunction: query => {
|
||||
return Espo.Ajax.getRequest(this.getAutocompleteUrl(query), {q: query})
|
||||
.then(/** {list: Record[]} */response => {
|
||||
return response.list.map(item => ({
|
||||
value: item.name,
|
||||
attributes: item,
|
||||
}));
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
$elementOneOf.attr('autocomplete', 'espo-' + this.name);
|
||||
|
||||
this.once('render', () => {
|
||||
$elementOneOf.autocomplete('dispose');
|
||||
});
|
||||
|
||||
this.once('remove', () => {
|
||||
$elementOneOf.autocomplete('dispose');
|
||||
});
|
||||
this.once('render remove', () => autocomplete.dispose());
|
||||
|
||||
this.$el.find('select.search-type').on('change', () => {
|
||||
this.trigger('change');
|
||||
@@ -789,7 +730,7 @@ class LinkFieldView extends BaseFieldView {
|
||||
});
|
||||
});
|
||||
|
||||
return {suggestions: list};
|
||||
return list;
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
@@ -1286,6 +1227,9 @@ class LinkFieldView extends BaseFieldView {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Record[]|undefined}
|
||||
*/
|
||||
getEmptyAutocompleteResult() {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -204,9 +204,6 @@ class VarcharFieldView extends BaseFieldView {
|
||||
|
||||
responseParsed.list.forEach(item => {
|
||||
list.push({
|
||||
//id: item.id,
|
||||
//name: item.name || item.id,
|
||||
//data: item.id,
|
||||
value: item.name || item.id,
|
||||
attributes: item,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user