Last Updated: February 25, 2016
·
4.179K
· muro_pp

Sencha Touch: Autocomplete Fieldtext with (code)List

In my very first project based on Sencha Touch framework I was asked to provide autocomplete input field with list where user could select an item from codelist. As I predicted, there are several extensions handling this issue in some way, but I decided to create another one.

Whole solution is splitted in two files:AutoCompleteList, AutoCompleteTxtField

AutoCompleteList

List used to show filtered codelist items with paging plugin and filter reset function:

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();
            }
        }
    }
});

It is possible to use AutocompleteTxtField inside any form and bind record's value to it. When user focuses the AutocompleteTxtField and the form record contains foreign key (as reference to codelist), then referenced record (item) is auto selected in list.

2 Responses
Add your response

Any examples on how to use it?

over 1 year ago ·

I think, the tip is quite self-explanatory.. the basic idea is: write some text inside the input and the list should be populate with data items containg inserted substring..

over 1 year ago ·