This is the fourth part of my tutorial on how to create a Sencha Touch 2 application. In this article, we are going to complete the following tasks:
- Add the delete note feature to the Note Editor View.
- Implement the navigation back to the Notes List Container View when the Home button in the Note Editor View is tapped.
- Modify the Notes List Container View so it renders the notes grouped by date.
![]() | ![]() |
Deleting Records from a Sencha Touch Data Store
The Delete Note workflow begins when a user taps the Delete Button on the Note Editor View:

This Button needs a tap handler, which we will add to the NoteEditor Class, in the NoteEditor.js file:
var deleteButton = {
xtype: "button",
iconCls: "trash",
iconMask: true,
handler: this.onDeleteButtonTap,
scope: this
};
As we did with the Save Button, we are using the handler and scope configs to map the function that will handle tap events on the Button, as well as to pass the View as the scope for the handler function.
Of course, we need to add the onDeleteButtonTap() function to the NoteEditor Class:
onDeleteButtonTap: function () {
console.log("deleteNoteCommand");
this.fireEvent("deleteNoteCommand", this);
}
This is the same pattern we’ve used to emit events from the Views throughout the application. We capture the event triggered from a control in the View, and create a View event that is in turn captured by the Controller.
Over in the Notes Controller, we are going to map a handler function to the deleteNoteCommand event fired by the Note Editor View. We will do this in the control config, under the noteEditor key:
control: {
notesListContainer: {
// The commands fired by the notes list container.
newNoteCommand: "onNewNoteCommand",
editNoteCommand: "onEditNoteCommand"
},
noteEditor: {
// The commands fired by the note editor.
saveNoteCommand: "onSaveNoteCommand",
deleteNoteCommand: "onDeleteNoteCommand"
}
}
Now we can implement the onDeleteNoteCommand() function like so:
onDeleteNoteCommand: function () {
console.log("onDeleteNoteCommand");
var noteEditor = this.getNoteEditor();
var currentNote = noteEditor.getRecord();
var notesStore = Ext.getStore("Notes");
notesStore.remove(currentNote);
notesStore.sync();
this.activateNotesList();
}
Here, we acquire references to the Note Editor, the note loaded into the editor, and the Notes Store. Remember that the getNoteEditor() function is a routine the framework created for us when we declared the editor in the refs config:
refs: {
// We're going to lookup our views by xtype.
notesListContainer: "noteslistcontainer",
noteEditor: "noteeditor"
}
Our next steps in onDeleteNoteCommand() are to remove the current note from the store and make the changes permanent:
notesStore.remove(currentNote); notesStore.sync();
Finally, we activate the Notes List Container View:
this.activateNotesList();
Another quick check on the emulator should confirm that at this point we are able to delete notes.
Navigating Back To the Main View
In order to navigate from the Note Editor View back to the Notes List Container View without making any changes to a note, we need to add a tap handler for the Home Button in the Note Editor Class:
var backButton = {
xtype: "button",
ui: "back",
text: "Home",
handler: this.onBackButtonTap,
scope: this
};
We will define the onBackButtonTap() function as follows:
onBackButtonTap: function () {
console.log("backToHomeCommand");
this.fireEvent("backToHomeCommand", this);
}
In the Controller, we will map this event to the onBackToHomeCommand() handler function:
control: {
notesListContainer: {
// The commands fired by the notes list container.
newNoteCommand: "onNewNoteCommand",
editNoteCommand: "onEditNoteCommand"
},
noteEditor: {
// The commands fired by the note editor.
saveNoteCommand: "onSaveNoteCommand",
deleteNoteCommand: "onDeleteNoteCommand",
backToHomeCommand: "onBackToHomeCommand"
}
}
And the onBackToHomeCommand() function will look like this:
onBackToHomeCommand: function () {
console.log("onBackToHomeCommand");
this.activateNotesList();
}
At this point, we can use the emulator to check that a tap on the Home Button activates the Notes List Container View.
Setting Up Grouping in a Sencha Touch List
One important usability detail we are missing is the ability to render the cached notes grouped by date. It’s amazing how easily we can accomplish this in Sencha Touch. Let’s first define a grouper config for the Notes Store:
Ext.define("NotesApp.store.Notes", {
extend: "Ext.data.Store",
requires:"Ext.data.proxy.LocalStorage",
config: {
model: "NotesApp.model.Note",
proxy: {
type: 'localstorage',
id: 'notes-app-store'
},
sorters: [{ property: 'dateCreated', direction: 'DESC'}],
grouper: {
sortProperty: "dateCreated",
direction: "DESC",
groupFn: function (record) {
if (record && record.data.dateCreated) {
return record.data.dateCreated.toDateString();
} else {
return '';
}
}
}
}
});
As of this writing, groupers are not explained very well in Sencha Touch’s documentation. However, it is not difficult to make sense of this config’s properties. The groupFn config is the function used to generate the label for the group. In our case, the label will be the date the notes were taken:

The sortProperty config defines the value that will be used to sort the groups. If you do not include this config, the fields will be sorted based on the value returned by the function defined with the groupFn config. The direction config specifies the direction to sort the groups.
The last change needed to implement grouping consists of adding the grouped config to the NotesList Class:
Ext.define("NotesApp.view.NotesList", {
extend: "Ext.dataview.List",
alias: "widget.noteslist",
config:{
scrollable:'vertical'
},
config: {
loadingText: "Loading Notes...",
emptyText: "</pre>
<div class="\"notes-list-empty-text\"">No notes found.</div>
<pre>
",
onItemDisclosure: true,
grouped: true,
itemTpl: "</pre>
<div class="\"list-item-title\"">{title}</div>
<div class="\"list-item-narrative\"">{narrative}</div>
<pre>
"
}
});
When we set the grouped config to true, the List will use the groups defined in its store, through the grouper config, to render its items appropriately.
Let’s check how the list looks after we turned on grouping. Start the emulator and confirm that the notes list has date groups similar to the following screenshot:

Summary
We just finished building all the features of the Note Editor View by adding both, the ability to delete notes, and the ability to navigate back to the Notes List Container View when the Home Button is tapped.
We also modified the Notes List so the notes are rendered in groups based on the date the notes were saved. This makes it easier for our users to find their notes.
In the next chapter of this series we are going to create a version of the app where the Notes List and Notes Editor Views are defined using config objects, instead of initialize functions.
Stay tuned! ![]()
Downloads
Download the source code for this article: NotesApp-ST2-Part4.zip
The Entire Series
- How to Create a Sencha Touch 2 App, Part 1
- How to Create a Sencha Touch 2 App, Part 2
- How to Create a Sencha Touch 2 App, Part 3
- How to Create a Sencha Touch 2 App, Part 4
- How to Create a Sencha Touch 2 App, Part 5
Want To Learn More?
My Sencha Touch books will teach you how to create an application from scratch.



Hi Jorge,
This has been an exceptional help in learning Sencha Touch MVC applications.
Hope you keep posting many more topics in Sencha Touch, specially Custom Styling using SASS and COMPASS…
Thank you. I appreciate the feedback.
This tutorial did help a lot
What I am struggling with in st2 is how to communicate with sever side data.
Could you use this example to store notes on sever side (Jason file or database) instead of this localstorages? Thanks
Thanks. Yes, you can change the store’s proxy so it sends the notes to the server.
I changed the store’s proxy as following: (uncommend your type&id), but it can’t save physically.
proxy: {
//type: ‘localstorage’,
//id: ‘notes-app-store’
type: ‘ajax’,
url: ‘data/notes.json’,
reader: {
type: ‘json’
}
},
The store is not able to save directly to the file. Remember, the store is on the client side, and your json file is on the server side. You will need to create a server-side handler that (1) sends the contents of the json file to the client, and (2) receives data sent by the store and updates the json file.
Hi Jorge, your explanation gets rid of my confusions. I need to create server scripts like php to do this.
it’s nice of you. I hope your future posts cover server-side topics as there are quite few references out there in ST documentations
Jorge,
Is there any way to update that notes data via proxy ‘jsonp’ (cross domain)?
I can fact that data from data base via php file, which generate the json file, but I have a problem with updating the changed note. I mean the note is updated in the store, but I’d like to be able to update the data in database.
Thanks again Jorge, huge huge help.
How can I reference the fields in the editor view?
I’m using Ext.ComponentQuery.query(‘togglefield’)[].setValue(0); which works but it would be better to get by name.
Hi Jorge,
When we are on the NotesListContainer page, if I pull the NotesList with my mouse in the downwards direction there comes a void in between the toolbar and the NotesList. Can this be avoided??
Can we change the look and feel of the tabpanels etc according to our needs, I mean is it possible at least??
Thanks and Regards
It’s all possible. You can change the CSS to accomplish what you need.
Hi,
I wanted to ask if it is possible to make an accordion in Sencha Touch 2 .
I yes then could you just hint how to proceed with it.
Thanks & Regards
Hi Jorge,
How setting different handlers for the “disclosure” and “itemtap” events on a list ?
var servidoresList = {
xtype: “servidoreslist”,
store: Ext.getStore(“Servidores”),
listeners: {
disclose: {
fn: this.onServidoresListDisclose,
scope: this
},
itemtap: {
fn: this.onItemTap,
scope: this
}
};
Thanks and Regards
Yes, Jose, that is possible.
Hi,
First of all thank you for your great tutorial. I have faced a wired issue.
When I add a few notes, then I remove them and refresh the browser. I get the following error. I would appreciate it, if you could help me on the issue.
‘undefined’ is not an object (evaluating ‘record.isModel’)
Thanks
Reza
Hi Jorge,
In your example i changed the title toolbar in file NoteEditor.js as follows
var topToolbar = {
xtype: ‘toolbar’
docked: “top”,
title: this.record.get (‘title’),
items: [
backButton
]
};
and I get the following error:
Uncaught TypeError: Can not call method ‘get’ of undefined
can you help me?
Thanks and Regards
Hey Jorge,
I have made a view with a toolbar(which has a button firing a tap event) and a panel.
When I try to set the height of the panel in the controller through the following code:
onToggleList: function()
{
console.log(“In controller”);
this.getAccordionPanel().getComponent(‘p’).setHeight(’0′);
}
it gives me an error “Uncaught TypeError: Cannot call method ‘setHeight’ of undefined”
where p is the id of the panel.
Can you tell how I can access the height when getComponent() is not working??
Thanks $ Regards
Is there any way to upload updated notes to database on the server from packaged app?
I did as Jorge told me. Using php server-size function you can populate notes into database
Hey Jorge,
Brilliant tutorial sir helped me lot.Right now i am wondering how can we integrate sms gateway to my sencha touch 2.0 app.I have gone through the following links and dont find it helpful because the link provided phonegap’s SMS class link but now its deprecated.
http://www.sencha.com/forum/showthread.php?131445-It-is-possible-to-send-SMS-Messages-from-a-Sencha-Touch-App
http://stackoverflow.com/questions/3193997/send-sms-through-phonegap-on-android
So can you show us by a tutorial or code snippet to achieve this.
Thank you. I’ll try to carve out some time for an example with SMS.
This is by far the most documented tutorial I have come across the internet.
I need a book that teacher sencha designer or architect or sencha 2 itself.
George please start writing one for us. If you know any good one, pls recommend.
We dont want to start building and fine out that another version of sencha3 is out.
Thank you. I’m updating the book to ST2. I will let you know when it’s ready.
Firstly many thanks for this excellent tutorial. Once I delete a note I can still add new notes and edit them afterwards, but if I refresh the browser it hangs on loading and I get the following error:
Store.js:904TypeError: ‘undefined’ is not an object (evaluating ‘record.isModel’)
Looks like removing a record breaks to the store? This happens in both Safari and Chrome. Any help would be appreciated.
Also, for further articles, it would be great to see how to customise the default themes and work with Compass/Sass. I’d also like to see how that’s done using Sencha Architect 2.
Thanks again.
hi, jorge
can you answer me a question unrelevant to this notes app issue. How can i do in ST2 to tap a image to fullscreen and tap again to restore it to original size? (just like we operate in iPhone image rol)l
Thanks a lot for the tutorial. It was really helpfull and well explained. A very nice start for the Sencha Touch technology.
Really nice job, thanks a lot!!!!!!
You’re welcome. Nice to see that the tutorial is helpful.
This give me a whole ST’s technoloy. It was really wonderful. Very Very nice job and thanks a lot.
You’re welcome!
Hi Jorge,
on click of list view item the disclose is not working i am using sench touch 2
onNotesListDisclose: function (list, record, target, index, evt, options) {
console.log(“editNoteCommand”);
this.fireEvent(‘editNoteCommand’, this, record);
},
This function is not at all calling please help with this issue
Thanks
Ram, I cannot reproduce the issue on my side. Please review your code again.
Ext.define(“NotesApp.view.NotesListContainer”, {
extend: “Ext.Container”,
alias: “widget.noteslistcontainer”,
initialize: function () {
this.callParent(arguments);
var newButton = {
xtype: “button”,
text: ‘New’,
ui: ‘action’,
handler: this.onNewButtonTap,
scope: this
};
var topToolbar = {
xtype: “toolbar”,
title: ‘My Notes’,
docked: “top”,
items: [
{ xtype: 'spacer' },
newButton
]
};
var notesList = {
xtype: “noteslist”,
store: Ext.getStore(“Notes”),
listeners: {
disclose: { fn: this.onNotesListDisclose, scope: this }
}
};
this.add([topToolbar, notesList]);
},
onNewButtonTap: function () {
console.log(“newNoteCommand”);
this.fireEvent(“newNoteCommand”, this);
},
onNotesListDisclose: function (list, record, target, index, evt, options) {
console.log(“editNoteCommand”);
this.fireEvent(‘editNoteCommand’, this, record);
},
config: {
layout: {
type: ‘fit’
}
}
});
here is the NotesListContainer am i missing something on click of list view the disclose is not calling the function onNotesListDisclose
Thank …
question…..
delete in Ext.Msg.confirm use how ???
I’m not sure what you’re asking.
Sorry, I’m not little to say that in English
And launches the delete confirmation window, select yes, you want to make the deletion.
onDeleteNoteCommand: function() {
console.debug(“onDeleteNoteCommand”);
Ext.Msg.confirm(“Warning”, “Are you sure Delete?”, function(btn, text) {
if(btn == ‘yes’) {
var noteEditor = this.getNoteEditorView(); // this error how??
var currentNote = noteEditor.getRecord();
var notesStore = Ext.getStore(“Notes”);
notesStore.remove(currentNote);
notesStore.sync();
this.activateNotesList(); // this error ??
}
});
},
Hi jorge,
You have written every function inside initialize function which will call the controller js file
can you please give some example how to call a function of controller written inside
config
{
xtype:’button’,
text:’test Call me’,
flex:1,
listeners: {
tap: function () {
console.log(“test callmeTapped”);
this.fireEvent(“backToHomeCommand”, this);
}
}
},
This function is not calling the controller js file
Ram, you don’t call controller functions from your views. You fire events, which the controller listens to. To see how you can do this from the config object, check out Part 5 of this tutorial: How to Create a Sencha Touch 2 App, Part 5
It is really a nice article, did help me a lot. can you make a sample about routes of controller
thanks a lot.
Thank you, Terence. I will try to write about routes as soon as possible.
I am receiving the same error as a few other people. “Uncaught TypeError: Cannot read property ‘isModel’ of undefined “. This error occurs when at least 2 notes are added, then one is deleted, and the page is refreshed. The only way to rectify this is to clear the browser cache, which removes all other notes too. Any idea why this is happening? I assume it is something to do with an entry not being deleted in the local-storage.
After looking into it, it seems that the store.remove(record) method is removing the model from the localstore, but is not removing the Id from the proxy itself, so when the Store is loaded on the page refresh, it is trying to lookup an Id that does not exist.
Hi.,
i wish to connecting mysql database using sencha touch tutorial in android native application..please explain step by step example..because am a beginer for android and sencha-touch.
Thank you. I will try to address connections to mysql in future posts.
Hi, Great thanks to your tutorial…. I have built my application based on your Part5….
But, my problem is i want to load two views . First view contains list of values coming from url dynamically.
second view contains the details of the particular item clicked which loads it from other url.
Now the first list is coming perfectly but, second view is not getting dynamic data of particular item.
I have declared a global variable , and i am reassigning the global variable value in first container with value of a whatever the clicked item. now the global variable contains the clicked item value. when i am giving this global variable in second url value this not displaying the clicked item value rather it is displaying the starting static global variable value. now how to pass the reassigned global variable value to second url…..
my url pattern is…
first url: http://localhost/……collection?&format=xml
second url: http://localhost/……collection(value=’123′)?&format=xml
Any help will be highly appreciated….
Thanks. Post a link to your code so we can take a look.
Hi Jorge,
Thanks for your reply…
As per my understanding ,I think that there is one problem with this type of approach for dynamic data .
Since all the containers are loading initially in app.js, the dynamic URLs in next containers are not taking the clicked item value of the first list for displaying the details.
Can we do something so that Containers are loaded one after other and not initially…
Kindly reply me with suggestive answers… Thanks in advance…
Yes. Don’t load them initially. Add them to the viewport as they are needed.
Hi Sir,
My store is containing URL.
According to my requirement i want to reload the Store at certain place.
Is there any way to reload the Store so that i can load dynamic value to the store in Controller file.
Reply me soon sir…its urgent.Thanks in advance…
Regards,
Gangadhar
Hi Sir,
Anyway I tried in my own way and the problem got solved.
the other problem is i want to load Google map into application .
The map should load according to store’s location.
As there are different locations, the map should load dynamically when i click on Map button from Employee details container.
Can you please help me with some code how to load Map when i click on Map button. The Control goes to Controller when i click on Map button. So, the actual logic will be in Controller file.
Thanks in advance…..
Jorge man am so greatfull for all your posts they really helped me alot….But i wish you can just help with using the same app but using a mysql database….i’ve done all your examples and they are are the best sencha touch 2 examples google can find..please help me with the mysql part..thank you
Hang in there Patrick. I will be writing about connecting the application to a server soon. Thank you for being a loyal reader.
Mr. Jorge, let me thank you for all your work you don’t know the important that have this tutorial for me know. Thanks for your time and sharing your skills! ^^
Hi, Mr. Jorge, Well this type I write you because I have a real big problem, When I build the app seems like the models and stores not exist, on the list of notes I can’t see anything, and into New Note view any field show, but this happens just after build. Please can help me?
I don’t wan’t bother you, but please I need to know what I suppose to do.
Check your references to the sencha touch css and js files. They are either missing or pointing to the wrong folder.
How I know if they are either missing or pointing to the wrong folder? Sorry for my little knowledge
Hi,
Please teach me how to set up the Sencha Touch Framework in detailed tutorial thanks
Hi Jorge
The tutorial is good and everything is working fine,but when i type in narrative field and try to save it a alert msg should fire but its showing the following error,please tell me how to solve this
Uncaught Error: [ERROR][NotesApp.controller.Notes#onSaveNoteCommand] Using Ext.Msg without requiring Ext.MessageBox
Regards,
Girish
Add the requires to the NoteEditor. It should en up looking like this:
requires: ['Ext.Toolbar', 'Ext.form.FieldSet', 'Ext.form.Text', 'Ext.field.TextArea', 'Ext.MessageBox'],
Hi Jorge,
Thanks jorge now its working fine..Please share if u have some more tutorials..once again thanks for this tutorial.
Regards,
Girish
And launches the delete confirmation window, select yes, you want to make the deletion.
onDeleteNoteCommand: function() {
console.debug(“onDeleteNoteCommand”);
Ext.Msg.confirm(“Warning”, “Are you sure Delete?”, function(btn, text) {
if(btn == ‘yes’) {
var noteEditor = this.getNoteEditorView(); // this error how??
var currentNote = noteEditor.getRecord();
var notesStore = Ext.getStore(“Notes”);
notesStore.remove(currentNote);
notesStore.sync();
this.activateNotesList(); // this error ??
}
});
},
Remember that you are inside the confirm’s callback function and “this” no longer holds a reference to the controller.
“Code” for me please.
onDeleteNoteCommand: function() {
console.debug(“onDeleteNoteCommand”);
var me = this;
Ext.Msg.confirm(“Warning”, “Are you sure Delete?”, function(btn, text) {
if(btn == ‘yes’) {
var noteEditor = me.getNoteEditorView();
var currentNote = noteEditor.getRecord();
var notesStore = Ext.getStore(“Notes”);
notesStore.remove(currentNote);
notesStore.sync();
me.activateNotesList();
}
});
},
OMG !!! Thank you so much Jorge.
Next issue, I want create Log-in page and check name,password
Code me
Ext.application({
name: “NotesApp”,
models: ["Note"],
stores: ["Notes"],
launch: function() {
Ext.create(‘Ext.form.Panel’, {
fullscreen: true,
items: [{
xtype: 'fieldset',
title: 'Register',
items: [{
xtype: 'textfield',
label: 'Name',
name: 'name',
type: 'string'
}, {
xtype: 'passwordfield',
label: 'Password',
name: 'password'
},
{
xtype: 'button',
text: 'OK',
ui: 'confirm',
handler: function() {
if(name == 'name'){
Ext.Msg.alert('', 'Login Successful!');}
else {Ext.Msg.alert('Error', 'Both username and password are required.');}
}
}]
}]
});
}
});
Help me again!! Please
pls how do i create a PHP for submission of a form in sencha touch 2….please i nid it
Good job on the article, the grouper piece was a huge help
Hello there, thak’s a lot for this tutorial, it did clarify the sencha touch framework to me.
I have one question which is : can i use sencha touch effects such as animateActiveItem in other framework like bootstrap twitter or zurb foundation?
Thank’s a lot, knowing this is hugely crucial to me
Best regards
You can, but you are better off using jQuery, as bootstrap already uses it for its components.
Hello Jorge,
I have a problem after build app native with this example. From browser I can save the record, close browser and then rerun browser, record still there. But with Android app after using command line. sencha app build native. The app running inside my device. I can save record, but after I stop the app, rerun the app again record has been gone.
Do you have any ideas?
Thanks a lot,
Trung.
Hi Jorge,
I works fine after I drop folders into an Android www and build the application with Eclipse, not use command line from sencha. Is it bug from sencha?
Thanks,
Trung.
Hi,
I have a requirement wherein i want to generate controls dynamically reading the values from json.My json would have values for UI components.Please help me out with this if you have some demos tutorials for same.
Thanks
Howdy I am so excited I found your webpage, I really found you by accident, while I was researching
on Yahoo for something else, Anyways I am here now and would just like to say thanks a lot for a remarkable post and
a all round enjoyable blog (I also love the theme/design), I don’t have time to read through it all at the moment but I have saved it and also added in your RSS feeds, so when I have time I will be back to read much more, Please do keep up the excellent work.
Hi Jorge,
Thank you very much for this nice tutorials series
I learned more with these than I did with the Sencha doc (which is a bit confusing and poor to my sense..).
I have a question about “sorters”, how to dynamically change the sorter property (currently “dateCreated”) ? With a “filters/criteria” box for example ?
Thank you
Hi Jorge,
I admire and appreciate your effort in creating such a beautifully explained tutorial. Thanks a lot for the effort. Now could not resist asking one question here on store and grouper config.
I think grouping the notes is view related stuff. So the grouper config in “view” (here NoteList) should be sufficient. Why there is a “grouper” config for “store” (here Notes) and a “grouped” config in view?
Thanks!