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