Sencha Touch: Autocompletar texto de campo con lista (c贸digo)

En mi primer proyecto basado en el marco Sencha Touch, se me pidi贸 que proporcionara un campo de entrada de autocompletado con una lista donde el usuario pod铆a seleccionar un elemento de la lista de c贸digos. Como predije, hay varias extensiones que manejan este problema de alguna manera, pero decid铆 crear otra.

La soluci贸n completa se divide en dos archivos: AutoCompleteList , AutoCompleteTxtField

AutoCompleteList

Lista utilizada para mostrar elementos de lista de c贸digos filtrados con complemento de paginaci贸n y funci贸n de restablecimiento 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();
}
}
}
});

Es posible utilizar AutocompleteTxtField dentro de cualquier formulario y vincular el valor del registro a 茅l. Cuando el usuario enfoca AutocompleteTxtField y el registro de formulario contiene una clave externa (como referencia a la lista de c贸digos), el registro (elemento) referenciado se selecciona autom谩ticamente en la lista.