Em meu primeiro projeto baseado na estrutura Sencha Touch, fui solicitado a fornecer um campo de entrada de preenchimento automático com uma lista onde o usuário poderia selecionar um item da lista de códigos. Como previ, existem várias extensões que tratam desse problema de alguma forma, mas decidi criar outra.
Toda a solução é dividida em dois arquivos: AutoCompleteList , AutoCompleteTxtField
AutoCompleteList
Lista usada para mostrar itens da lista de códigos filtrados com plug-in de paginação e função de redefinição de filtro:
Ext.define('Solution.view.AutoCompleteList', {
extend: 'Ext.dataview.List',
xtype: 'vAutoCompleteList',
config: {
styleHtmlContent: true,
onItemDisclosure: false,
hidden: true,
height: '100px',
border: 3,
cls: 'autocomplete',
showAnimation: { type: 'fadeIn' },
hideAnimation: { type: 'fadeOut' },
emptyText: 'The list is empty',
plugins: [
{
xclass: 'Ext.plugin.ListPaging',
autoPaging: true,
loadMoreText: 'Get more records',
noMoreRecordsText: 'No more records'
}
],
//custom variable holds actual record codelist value (Foreign Key)
idFromRecord: null,
//reference to autocomplete textfield
autoCompleteTxtField: null,
listeners: {
itemtap: function (src, index, target, record, e, eOpts) {
var colName = this.getAutoCompleteTxtField().getName();
this.getAutoCompleteTxtField().setValue(record.get(colName));
src.hide();
}
}
},
resetProxyFilter: function () {
if (this.getStore().getProxy().getExtraParams().filter)
this.getStore().getProxy().getExtraParams().filter = null;
}
});
AutoCompleteTxtField
Ext.define('Solution.view.AutoCompleteTxtField', {
extend: 'Ext.field.Text',
xtype: 'vAutoCompleteTxtField',
config: {
//custom properties
filterName: null,
//reference to autocomplete list
autoCompleteList: null,
recordColFK: null,
//to override
hideListWhenEmptyText: true,
listeners: {
//custom event
valueSet: function (value) {
var me = this;
//set actual filter to list store
this.getAutoCompleteList().getStore().getProxy().setExtraParams({
'filter': this.getFilterName() + '|' + value
});
//page 1
this.getAutoCompleteList().getStore().loadPage(1, {
callback: function (records, operation, success) {
me.getAutoCompleteList().deselectAll();
//select record in list
if (null != me.getAutoCompleteList().getIdFromRecord()) {
for (var i = 0; i < records.length; i++) {
if (records[i].get(me.getRecordColFK()) == me.getAutoCompleteList().getIdFromRecord()) {
me.getAutoCompleteList().select(records[i]);
break;
}
}
}
}
}, this);
},
focus: function (src, e, eOpts) {
if (!src.getReadOnly())
this.fireEvent('keyup', src, e, eOpts);
},
keyup: function (src, e, eOpts) {
var me = this;
var queryString = src.getValue().trim();
if (queryString.length == 0) {
if (this.getHideListWhenEmptyText()) {
this.getAutoCompleteList().deselectAll();
this.getAutoCompleteList().hide();
}
return;
}
//filter check from previous request
var previousFilterParam = this.getAutoCompleteList().getStore().getProxy().getExtraParams() ?
this.getAutoCompleteList().getStore().getProxy().getExtraParams().filter :
null;
//set actual filter
this.getAutoCompleteList().getStore().getProxy().setExtraParams({
'filter': this.getFilterName() + '|' + queryString
});
//if not requesting next page, then reset the list store
if (this.getAutoCompleteList().getStore().getProxy().getExtraParams().filter != previousFilterParam) {
//reset paging = get 1.page
this.getAutoCompleteList().getStore().loadPage(1, {
callback: function (records, operation, success) {
me.getAutoCompleteList().deselectAll();
if (records.length > 0) {
me.getAutoCompleteList().show();
}
else {
me.getAutoCompleteList().hide();
}
//select record in list
if (null != me.getAutoCompleteList().getIdFromRecord()) {
for (var i = 0; i < records.length; i++) {
if (records[i].get(me.getRecordColFK()) == me.getAutoCompleteList().getIdFromRecord()) {
me.getAutoCompleteList().select(records[i]);
break;
}
}
}
}
}, this);
}
else {
//get next page
this.getAutoCompleteList().getStore().load({
callback: function (records, operation, success) {
if (records.length > 0) {
me.getAutoCompleteList().show();
//re-select record in list (required in some cases)
if (null != me.getAutoCompleteList().getIdFromRecord()) {
for (var i = 0; i < records.length; i++) {
if (records[i].get(me.getRecordColFK()) == me.getAutoCompleteList().getIdFromRecord()) {
me.getAutoCompleteList().select(records[i]);
break;
}
}
}
}
}
}, this);
}
},
clearicontap: function (src, e, eOpts) {
this.getAutoCompleteList().deselectAll();
this.getAutoCompleteList().hide();
}
}
}
});
É possível usar AutocompleteTxtField dentro de qualquer formulário e vincular o valor do registro a ele. Quando o usuário foca o AutocompleteTxtField e o registro do formulário contém uma chave estrangeira (como referência à lista de códigos), o registro referenciado (item) é selecionado automaticamente na lista.