Sencha Touch: Autocomplete Fieldtext com (código) Lista

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.