Learn More... SQLsnap Logo. SQLsnap Screenshot. Buy Now or Learn More!

Add searchfield to a sencha touch 2 list MVC

May 17th, 2012

Adding a search field to your sencha touch 2 list is fairly straight forward, there is a good example (list-search) that comes with the sencha touch 2 download. Though to add the searchfield to a list in the MVC style can be a wee bit challenging. Here is a way you can do it! You will need a basic understanding of Sencha Touch 2 and it’s MVC structure.

First we will create a list with the search field. We will place the search field on the bottom toolbar. Like so. (see code below)

Ext.define('App.view.View', {
    extend: 'Ext.List',
    alias:'widget.contactlist',
    fullscreen: true,
    id: 'contactlist',
    config:{
        disableSelection:true,
        store:'Contacts',
        itemTpl:'{first_name} {last_name}',
        items:[{
            xtype:'toolbar',
            docked:'top',
            title:'Contact List'
        },{
            xtype:'toolbar',                                       //  bottom toolbar
            docked:'bottom',
            items:[{
                xtype: 'searchfield',                          //  here is the searchfield
                itemId:'contact_search',
                id:'contact_search',                         //   we will be using this id in the controller
                placeHolder: 'Search Contacts'
            }]
        }]
    }
});

An example Store to populate our list and to use for our search functionality could look as so. (see code below)

Ext.define('App.store.Contacts', {
    extend: 'Ext.data.Store',
    config: {
        model: 'App.model.Contacts',
        autoLoad :true,
        sorters: 'last_name',
        grouper : function(record) {
            return record.get('last_name')[0];
        },

        proxy: {
            type: 'ajax',
            url : 'contacts.json',  //  the json file that holds all our contact info.
            reader: {
                type: 'json',
                rootProperty:'contacts'}
        }
    }
});

An example Model too. (see code below)

Ext.define('App.model.Contacts', {
    extend: 'Ext.data.Model',
    config: {
        fields: [
            {name: 'first_name',  type: 'string'},
            {name: 'last_name',  type: 'string'}
        ]
    }
});

Here is the json that we will be using to populate our list and that we already defined as contacts.json in the Contacts store.(see code below)

{
    "contacts": [
    {
        "first_name": "Brandon",
        "last_name": "Beachy"
    },
    {
        "first_name": "Jair ",
        "last_name": "Jurrjens"
    },{
        "first_name": "Mike",
        "last_name": "Minor"
    }
    ]
}

Then inside your app’s controller we can implement the list-search code that came with the sencha touch 2 download. Take note of this.control() and the functions defined below it. (see code below)

Ext.define('App.controller.Main', {

    extend: 'Ext.app.Controller',
    init: function() {

        this.control({

            '#contact_search':{  //  the id or itemId we gave our searchfield
                scope: this,
                clearicontap: this.onSearchClearIconTap,
                keyup: this.onSearchKeyUp
            }

        });
    },
    onSearchKeyUp: function(field) {
        //get the store and the value of the field
        var value = field.getValue(),
        store = Ext.getCmp('contactlist').getStore();    //  getting the store that drives the contact list

        //first clear any current filters on thes tore
        store.clearFilter();

        //check if a value is set first, as if it isnt we dont have to do anything
        if (value) {
            //the user could have entered spaces, so we must split them so we can loop through them all
            var searches = value.split(' '),
            regexps = [],
            i;

            //loop them all
            for (i = 0; i < searches.length; i++) {
                //if it is nothing, continue
                if (!searches[i]) continue;

                //if found, create a new regular expression which is case insenstive
                regexps.push(new RegExp(searches[i], 'i'));
            }

            //now filter the store by passing a method
            //the passed method will be called for each record in the store
            store.filter(function(record) {
                var matched = [];

                //loop through each of the regular expressions
                for (i = 0; i < regexps.length; i++) {
                              var search = regexps[i],
             didMatch = record.get('first_name').match(search) ||
                                  record.get('last_name').match(search);
                            //if it matched the first or last name, push it into the matches array 

                               matched.push(didMatch);

                         }  //if nothing was found, return false (dont so in the store)               

              if (regexps.length > 1 && matched.indexOf(false) != -1) {
                              return false;
                          } else {
                             //else true true (show in the store)
                             return matched[0];
                            }
            });
        }
    },

    /**
     * Called when the user taps on the clear icon in the search field.
     * It simply removes the filter form the store
     */
    onSearchClearIconTap: function() {
        //call the clearFilter method on the store instance
        Ext.getCmp('contactlist').getStore().clearFilter();
    }

})

Then finally you can tie it all together with your app.js, an example of that could look like this. (see code below)

Ext.application({
     name: 'App',

     controllers: ['Main'],
     stores: ['Contacts'],
     models: ['Contacts'],
     views: ['View'],

      launch: function() {

         Ext.Viewport.add({
             xtype: 'contactlist'
         });

     }
});

  • Julien

    thanks a lot! that was very clear and works perfectly

  • anon

    Works perfect

  • User 1

    This was great

  • umwelt

    Instead of 

    [code] var searches = value.split(' '),  [/code]I had to use[code] var searches = value.split('&nsbp; '),  [/code]
    The rest works fine

  • Gluttony

    Thank you for this!

blog comments powered by Disqus
  • Newer Entries »