This is the last of a four-part series on how to write a Sencha Touch application. If you’re new to the series, here are the links to the previous installments:
- Writing a Sencha Touch Application, Part 1
- Writing a Sencha Touch Application, Part 2
- Writing a Sencha Touch Application, Part 3
In part 3 of this tutorial we worked on the Note Editor and added the ability to create notes. It is time now to let our users edit and delete notes. Let’s work on the edit note feature first.
Disclosure events in a Sencha Touch List
When the person using the application touches a note’s disclosure button in the Notes List view, the selected note should be displayed in the Edit Note view:

We can complete this feature by implementing the onItemDisclosure handler of the notes list. Here’s the code:
NotesApp.views.notesList = new Ext.List({
id: 'notesList',
store: 'NotesStore',
onItemDisclosure: function (record) {
var selectedNote = record;
NotesApp.views.noteEditor.load(selectedNote);
NotesApp.views.viewport.setActiveItem('noteEditor', { type: 'slide', direction: 'left' });
},
itemTpl: '
<div class="list-item-title">{title}</div>' +
'<div class="list-item-narrative">{narrative}</div>',
listeners: {
'render': function (thisComponent) {
thisComponent.getStore().load();
}
}
});
The handler function accepts the selected note as a parameter. What we need to do in the handler is load the note in the editor utilizing the editor’s load() method, and then, make the Note Editor view active via a call to the viewport’s setActiveItem().
Very cool. At this point we can switch over to the emulator, where we should be able to edit notes.
Removing records from a data store
Deleting notes is also very easy. The Trash button on the Note Editor view’s bottom toolbar will trigger this function. We need to change the button’ handler like so:
NotesApp.views.noteEditorBottomToolbar = new Ext.Toolbar({
dock: 'bottom',
items: [
{ xtype: 'spacer' },
{
iconCls: 'trash',
iconMask: true,
handler: function () {
var currentNote = NotesApp.views.noteEditor.getRecord();
var notesList = NotesApp.views.notesList;
var notesStore = notesList.getStore();
if (notesStore.findRecord('id', currentNote.data.id)) {
notesStore.remove(currentNote);
}
notesStore.sync();
notesList.refresh();
NotesApp.views.viewport.setActiveItem('notesListContainer', { type: 'slide', direction: 'right' });
}
}
]
});
After acquiring references to the current note, the notes list and the notes data store, we use the store’s findRecord() function to find and remove the note loaded on the editor.
Next, we call sync() on the store to make the removal permanent, and proceed to re-render the notes list and make the Notes List view active.
This procedure is similar to the one we followed when we implemented the Save Note feature, although in this case we’re deleting the note, not saving it.
A quick check on the emulator should confirm that we can now delete notes.
Grouping items in a Sencha Touch List
One last thing we want to do is, in the Notes List view, render the notes grouped by date. This will make it easier for our users to work with their notes.
First, we need to tell our notesList Ext.List that it needs to render its items grouped. We can do this using the grouped config option like so:
NotesApp.views.notesList = new Ext.List({
id: 'notesList',
store: 'NotesStore',
grouped: true,
emptyText: '<div style="margin: 5px;">No notes cached.</div>',
onItemDisclosure: function (record) {
var selectedNote = record;
NotesApp.views.noteEditor.load(selectedNote);
NotesApp.views.viewport.setActiveItem('noteEditor', { type: 'slide', direction: 'left' });
},
itemTpl: '<div class="list-item-title">{title}</div>' +
'<div class="list-item-narrative">{narrative}</div>',
listeners: {
'render': function (thisComponent) {
thisComponent.getStore().load();
}
}
});
Then, we need to override the getGroupString() function of the NotesStore:
Ext.regStore('NotesStore', {
model: 'Note',
sorters: [{
property: 'date',
direction: 'DESC'
}],
proxy: {
type: 'localstorage',
id: 'notes-app-store'
},
getGroupString: function (record) {
if (record && record.data.date) {
return record.get('date').toDateString();
} else {
return '';
}
}
});
You can define the grouping behavior of the store using the groupField property and the getGoupString() function.
The getGroupString() function returns the string to group on, based on the store’s data model’s properties. By default, getGroupString() returns the value of the groupField property. In our case we want to use the value of the note’s date as the group’s header, but we want to format the value as a date.
If we check the emulator, the notes taken the same day should render under the same group header:

We made it!
This is pretty much it. A very simple Sencha Touch application and an easy way to learn some of the features of the Sencha Touch framework.
I hope you take this app to the next level as you learn more about the framework. ![]()
And don’t forget to leave a comment letting me know the Sencha Touch topics about which you would like me to write.
Download the Notes App: Notes-App-v1.0.zip
Here’s the rest of the series:

Great tutorial
I found it really useful and informative – would love to see a tutorial on turning it into a true phone app with integrated database
Thank you, Dave.
it was Very helpfull for me, i got too much knowledge about sencha touch fremwork by this example if some other example like database integrate with senha touch application or php integegrate application you have or if you have ebook of sencha touch please send me at vikas.sama83@gmail.com thanks……….
Thanks. Very Helpful.
Please keep go on.
Great tutorial!
These tutorials have been very knowledgeable! Hope this isn’t the end of the Sencha Tutorial Series. I think you are actually on to something here.
Thanks everybody! Please let me know what other topics you would like me to write about.
I think it would be really useful to make some topics about another simple sencha touch application – RSS reader
Also its interesting to read about sencha touch customization – custom buttons and custom app design
thanks
Thanks. Yes, that would be very interesting, I will consider your suggestions.
Localstore with associations! it would be great.
Great series of articles. Would love to see more like this.
This is an excellent tutorial! However, I wonder how would you modify it to use remote store (ajax or rest proxy) instead of local store? I tried to modify proxy property of the store:
proxy : {
type : ‘ajax’,
url : ‘/notes.php’,
reader : { type : ‘json’ }
}, (…)
where “notes.php” is simple script on the that returns JSON encoded list of notes from the database.
Now, list of notes gets populated, as well as edit note form. But when you try to save changes (Save button), or add new note, nothing happens. Notes app sends empty POST request to server (notes.php script)?
Any suggestions? Thanks!
Thanks, this is a very nice tutorial. How would you save the notes on a server and not only locally?
Best,
Stenlo
Looks like I will need to write about saving to a server.
Yessss, please do!
I too would love to see saving to the server! Thanks for the nice tutorial. Jumping into this platform was very overwhelming without explanations and baby stepping from the start.
Thanks for this great tutorial. My suggestion:
Part 5, which shows how to break the whole Script in separate parts (like mainapp, list, editor…) and how to give it a good structure in filesystem.
(reference: http://www.sencha.com/learn/Tutorial:Writing_a_Big_Application_in_Ext)
Very well done. Complete with Create, Read, Update and Delete operations on data store. I learned a lot. Thanks.
Well done.
I agree with Klaus that breaking it up into the Sencha recommended directories would be a nice next step.
It would also be great if you could add pointers to more general discussions of the various topic areas you introduce: e.g., models/stores/dataviews; navigation; verification and validation, etc.
But, overall, this is an excellent tutorial as it is.
Thanks!
You’re welcome, guys.
Great tutorial. I’ve got a question. In the section called “Disclosure events in a Sencha Touch List”, in the code on about line 12, you define a listener for the ‘render’ event. What is this for? Thanks in advance.
Thanks, ted. I use the render listener to load the notes store’s data.
Awesome tutorial, well done!
I would love to see some tutorials on TDD and BDD using Jasmine and how to run the tests on a build server.
Thanks and keep blogging
Hey!
Great tutorial!
I have one question though:
I’m making an application where I want to populate a textfield with the record from a list item and I just can’t get it to work. Could you point me in the right direction?
Again, great tutorial…it helped me a bunch!
Best regards,
Homan
Homan, this tutorial describes precisely how to do what you need. If you inspect the source code you will see it.
I’m kind of a noob and can’t seem to use your example in order to populate my textfield. Is there some other resources you could point me to?
Thanx in advance!
Okey, I managed to solve it by taking another look at your code. If anybody is interested you can look at my answer here: http://stackoverflow.com/questions/6726038/how-to-populate-a-textfield-with-the-value-from-a-list-selection-in-sencha-touch
This is a great tutorial!
Outstanding article! Thank you. In addition to the remote JSON via AJAX questions already mentioned above, can you please explain what the listeners: ‘render’ is for in the NotesList? This just showed up between parts 3 and 4 in the code without saying why.
Thanks Brad. I use the render listener to load the store.
Thanks for the wonderful tutorial. I have a question. when I use this line of code NotesList.refresh(); in this blockNotesApp.views.noteEditorBottomToolbar = new Ext.Toolbar. I am not able to go back to Note list when I delete a note. When I did not use refresh it work fine. Can you tell me what could be the problem?
Thanx Jorge. Your tutorial was very helpful.
It would be great to see a tutorial on adding a logo to the top of the app and changing the color schemes.
How is the localstorage suppose to work? When I refresh in my iPhone browser the data gets wiped. Anyone else having this issue? Thanks in advance.
Hey! Really helpful tutorial for begginers like me! I have one question, how can I change the code to pass the informations in the note’s list to another panel and show this information again in a html format instead to load the informations in a form? I want it to show more detailed informations about each item in my list. Thank you!
I am also experiencing problems with the local store when I refresh my browser or restart my Ipad the notes are wiped.
Another minor issue is when my note is delete via the delete button int he bottom toolbar the notes list view does not become active. Would appreciate your suggested solution and how to save notes to a server
Hey, thx for this great tutorial, thx to you i was able to make the list fit, i was trying that for while now… .
Thnx jorge, this article was very helpfull.
i am facing a problem. when i generat grouped list according to ur method then a vertcal bar at right side will be displayed having (A – Z) alphabets. i want to remove this bar plz help me.
something like that;
A
B
C
D
E
F….
Thanks a lot Jorge. This tutorial series was very helpful.
This tutorial really helped me to get started with Sencha Touch. However, i will request that you provide us with a tutorial on retrieving and manipulating data from a database say MySQL.
Thank you very much all the same.
Good work.
Great articles. I can now do a meaningful coding. Great tutorial on Sencha.
Really really a great tutorial for beginers. Very clear, methodic, and helpful. Thanks!!!, it saved my weekend.
Hi Jorge,
Thanks you very much to write a wonderful article with Sencha Touch for beginners.
This tutorial really helped me to get started with Sencha Touch. It would be really helpful for a beginner like me if you please share a tutorial on retrieving and manipulating data from a database like SQL Server. User can work with records in offline and when Internet connection will get available, then all the records stored locally will be sent to the DataBase.
Great work.
Thanks & Regards,
Sukanta Ghorui
Hİ Jorge ,
Thanks tutorial is very useful especially toolbar spacer object. I couldnt find anywhere use spacer object via this tutorial Iearned how can I use it.
Regards.
Hi Jorge,
It is really awesome. This is what I was looking for . I was goggling since morning to know how to start ST application, but you saved my day. I am already reader of your cookbook. Can you update some articles on ST2 as it is released couple of days before.
Jorge
Many thanks as a beginner here your Notes example provides a simple way of understanding the components of the app and how they work together.
I do have an ask however, do you have an example with how i can access information from a website and display within my app. for example hooking into my tweets or being able to render news items from a website.
I am also looking to build my own website with a database from which i provide the data for my mobile pages. i take it i need to do this using something like php. do you have any simple references to how to achieve this.
Many thanks again.
Andy j
Thank you, Andy. The scenario you mention is on my list of future tutorials. Stay tuned!
I echo the comments of gratitude. Marvelous job especially in contrast with the “Getting started” guides on Sencha website (their 2.0 guides make no sense whatsoever i.e. following the code examples result in error after erro) Really bad for someone just getting into the framework.
Your work is truly laudable. Thank you for taking the time!
I look forward to reading your tutorials on working with JSON and served data.
Thank you. I’m happy that these tutorials are helping so many people.
Thank you for this very helpfull tutorial.
Have you any tutorial like this or ported it to use Sencha Touch 2?
Andreas, as soon as Sencha Touch 2 is stable, I will port the tutorials.
The tutorial was really helpful.
There’s just one problem when i run the application. When i remove a note and refresh my browser the notes app crashes. The error i get is ” Cannot read property ‘id’ of null”. This happens inside the Sencha Touch debug file, not the notes script itself. My guess is that something goes wrong with the local storage.
Has anyone else had this problem and if so, how did you solve it? I’ve encountered this problem within my own version of the app as have i in the version that Jorge has put at the end of the tutorial.
Thank you!
Great tutorial man!!
This gave me a great insight on how to start doing my own sencha touch app, thank you very much! Now let’s expand it even more!! BTW… have u tried to make it a native app with phonegap? Any advice on this? Saludos bro!
Adrian
Thank you, Adrian. I’m glad the tutorial helped you.
Jorge,
Excellent tutorial! I had a great time following along building the app step by step and I have to say I was pleasantly surprised and very happy that it worked every step. It was my first attempt with building a mobile app. i used Eclipse along with the Android ADT plugin, the PhoneGap plugin by Mobile Developer Solutions and was able to build it as a native app quite effortlessly!
Thanks again for making it possible.
Dave
P.S. If you were to continue with more tutorials on this app, I would love to see how you would integrate it with a server side storage solution such as MongoDB or MySQL and having the application be able to sync while connected.
Thank you, Dave. It’s very rewarding to see how these tutorials have helped so many people.
Stay tuned. I will be talking about server-side storage and synchronization in the coming weeks.
App works fine but im having problems with making app offilne using cache manifest? It works offline perfectly fine for a few times i use it, then all my notes disappear from my phone when I reconnect to the internet? I think some should touch up on this topic also, that would make a complete package of this great app.
Excellent tutorial my brother, let me congratulate you for this job.
Jorge great tutorial.
I have one question, how to control that the same note is not saved more than once on the local storage? In my localstorage, the record is store one time, but on the id key keeps adding the id even that is already present, if the user press the save button again and again. The consequence of that is when I delete the item from my list, it will still be shown on the list if the id is more than one time.
This was a really great start to finish tutorial. Great job and thank you.
I have read that there is a component that ExtJs ComboBox is a variation of this component is called TimeField and serves to display values over time. Most properties are the same as the ComboBox. But I failed to get results like to know if you can help with that.
Very nice tutorial!
Thanks! hope to see more from you soon!
I’ve typed in the code, I’ve copied and pasted from the web and the book and no luck compiling. Mac and Aptana. Can you up load the source files? I have found differences between the web and book versions. I’m a Flex guy trying to get into to this and would appreciate it.
Thanks,
Tony
Tony, I’m not sure what you mean that you’ve had no luck compiling. Please post the specific error you’re seeing so we can help you.
I ran through your tutorial making my notes as I went along. My intent was to get familiar with the API and the calls you were making. The only thing that caught me off guard / confused me was in your last edit of:
views.noteEditorBottomToolbar
In it, you reference
currentNote.data.id
I didn’t find anywhere in the API that said that indicated Model “data” could be accessed that way. The closest i got was a get() method.
I also noticed in the very last edit, defining the getGroupString function, you use both methods to reference the “data” in a Model object
if (record && record.data.date) {
return record.get(‘date’).toDateString();
Can you shed a little more light for me?
By the way, fantastic tutorial. I actually bought the PDF because it was so good.
Thank you, Hacho. Both ways are acceptable. I personally prefer using accessor methods (get(‘something’) or getSomething()) if they exist. But I wanted to show both ways in the tutorial.
Very useful tutorial..thank u..
great tutorial. thanks so much Jorge…
Training was very good
Please description save the contents of the cache in the database…
thank you.
Thank you Mohammad. I’m working on the tutorial that will describe how to keep the local cache and the server in sync. Stay tuned!
Great tutorial!
I have worked through it have a working demo application!
I do have one question that I am struggling with, I would like to add a check box to the note screen. In my code below I can see the checkbox on the note edit screen and check it but it saves it as false always.
Here is my model:
Ext.regModel(‘Note’, {
idProperty: ‘id’,
fields: [
{ name: 'id', type: 'int'},
{ name: 'date', type: 'date', dateFormat: 'c' },
{ name: 'title', type: 'string'},
{ name: 'complete', type: 'boolean' },
{ name: 'narrative', type: 'string'}
],
validations: [
{ type: 'presence', field: 'id' },
{ type: 'presence', field: 'title', message: 'Please enter a title for this note.' }
]
});
Here is my noteEditor
//Create the Sencha Touch Form Panel
NotesApp.views.noteEditor = new Ext.form.FormPanel({
id: ‘noteEditor’,
items: [
{
xtype: 'textfield',
name: 'title',
label: 'Title',
required: true
},
{
xtype: 'textareafield',
name: 'narrative',
label: 'Narrative'
},
{
xtype: 'checkboxfield',
name: 'complete',
label: 'Complete'
}
],
dockedItems: [
NotesApp.views.noteEditorTopToolbar,
NotesApp.views.noteEditorBottomToolbar
]
});
Here is my noteListToolbar
//Create the Sencha toolbar
NotesApp.views.notesListToolbar = new Ext.Toolbar({
id: ‘notesListToolbar’,
title: ‘My Notes’,
layout: ‘hbox’,
items: [
{ xtype: 'spacer'},
{
id: 'newNoteButton',
text: 'New',
ui: 'action',
handler: function () {
var now = new Date();
var noteID = now.getTime();
var note = Ext.ModelMgr.create(
{ id: noteID, date: now, title: '', narrative: '', complete: ''},
'Note'
);
NotesApp.views.noteEditor.load(note);
NotesApp.views.viewport.setActiveItem('noteEditor', {type: 'slide', direction: 'left'});
}
}
]
});
Jeff, where’s the function that saves the note?
Sorry…left that out…(thanks for the quick response)
NotesApp.views.noteEditorTopToolbar = new Ext.Toolbar({
title: ‘Edit Note’,
items: [
{
text: 'Home',
ui: 'back',
handler: function () {
NotesApp.views.viewport.setActiveItem('notesListContainer', { type: 'slide', direction: 'right' });
}
},
{ xtype: 'spacer' },
{
text: 'Save',
ui: 'action',
handler: function () {
var noteEditor = NotesApp.views.noteEditor;
var currentNote = noteEditor.getRecord();
// Update the note with the values in the form fields.
noteEditor.updateRecord(currentNote);
var errors = currentNote.validate();
if (!errors.isValid()) {
currentNote.reject();
Ext.Msg.alert('Wait!', errors.getByField('title')[0].message, Ext.emptyFn);
return;
}
var notesList = NotesApp.views.notesList;
var notesStore = notesList.getStore();
if (notesStore.findRecord(‘id’, currentNote.data.id) === null) {
notesStore.add(currentNote);
} else {
currentNote.setDirty();
}
notesStore.sync();
notesStore.sort([{ property: 'date', direction: 'DESC'}]);
notesList.refresh();
NotesApp.views.viewport.setActiveItem(‘notesListContainer’, { type: ‘slide’, direction: ‘right’ });
}
}
]
});
Found it…needed to add value: true to the checkboxfield
Thanks for your help.
Great tutorial, will purchase the ebook.
Thanks so much.
i just started checking out sencha touch and this tutorial has been a very great jumpstart for me. very smooth & well-explained. kudos!
“Stay tuned. I will be talking about server-side storage and synchronization in the coming weeks.”
Please let me know if you’ve made a php-mysql-sencha app tutorial or anything similar. thanks!!
Hi Jorge,
Thanks for this useful guides. I’ve implemented you sample codes. Unfortunately I have 2 problems:
1. I cannot save a note that I edit.
2. I cannot delete a note.
On Save button’s handler, I put some console.log, like this:
var notesList = NotesApp.views.notesList;
var notesStore = notesList.getStore();
if (notesStore.findRecord(‘id’, currentNote.data.id) === null) {
notesStore.add(currentNote);
console.log(‘Notes store add current note’);
} else {
currentNote.setDirty();
console.log(‘Make current note dirty’);
}
notesStore.sync();
console.log(‘Notes store synched’);
notesStore.sort([{property: 'date', direction: 'DESC'}]);
notesList.refresh();
console.log(‘List refreshed’);
NotesApp.views.viewport.setActiveItem(‘notesListContainer’, {
type: ‘slide’, direction: ‘right’
});
I got every log is passed but the list item is not update after I edit a row from the list.
The same case happened when I tried to delete a content. Here is my code in trash button:
var currentNote = NotesApp.views.noteEditor.getRecord();
var notesList = NotesApp.views.notesList;
var notesStore = notesList.getStore();
if (notesStore.findRecord(‘id’, currentNote.data.id)) {
console.log(‘Deleting current note.’);
notesStore.remove(currentNote);
}
console.log(‘Syncing.’);
notesStore.sync();
console.log(‘Refresh list with .’);
notesList.refresh();
console.log(‘Move to list.’);
NotesApp.views.viewport.setActiveItem(‘notesListContainer’, {
type: ‘slide’, direction: ‘right’
});
Every log seem so normal. I don’t think notesStore.sync() works like I expected.
Please share your experince of what migh be wrong in my code. Thanks in advance.
Amri, I cannot reproduce the issue you described. what is the Sencha Touch version are you using? Also, can you send me your source code via email?
For a simulator, Can I use Safari? The code for the first part of the app loads, but none of the subsequent ones do, not even after downloading the final app and running… Should this not working in Safari?
Try Chrome.
i have a problem. i can navigate to the new page ( noteEditor ) but if i try to go back it won’t work. it has the same code.
//This one works
App.views.mainTopbar = new Ext.Toolbar({
id: ‘mainTopbar’,
dock:’top’,
title: ‘Mobile Todo’,
layout: ‘hbox’,
items: [{
xtype:'spacer'
},{
xtype:'button',
text:'New',
handler:function(){
App.views.viewport.setActiveItem('addTodoContainer',{type:'slide',direction:'right'});
}
}]
});//end of mainTopbar
//This one doesn’t
App.views.addTopbar = new Ext.Toolbar({
id: ‘addTopbar’,
dock:’top’,
title: ‘Add Todo’,
layout: ‘hbox’,
items: [{
ui:'back',
text:'Back',
handler:function(){
Ext.Msg.alert("INFO","No error here");
App.views.viewport.setActiveItem('mainTodoContainer',{type:'slide',direction:'left'});
}
}]
});//end of mainTopbar
What’s the error you see in the debugger?
Thank you for a speedy response. This is the error.
TypeError: Result of Expression ‘config’ [undefined] is not an object. at file:///android_asset/www/sencha-touch/sencha-touch-debug-w-comments.js:31949
I’m viewing it on the logcat.
Make sure mainTodoContainer is defined.
got it. i gave it a id of mainTodo and not mainTodoContainer. thanks!
Glad you found it.
When I save one note I noticed that in notesStore I can’t read the last notes id (but something like “ext-record-1″), when I refresh the page I can read the id . . . I don’t know why . . .
I use this: console.log(notesStore.data.keys);
the result is (:
[idNote1, idNote2, ..., "ext-record-n"]
when I refresh the page with the same command I obtain [idNote1, idNote2, ..., idNoten]
Huge thanks for putting this tutorial together and for keeping up with the comments.
I’m working on implementing some geolocation information to each note, which I’ve done successfully upon creating the note. However, I cannot seem to figure out how to update the latitude and longitude fields I’ve setup in my model when the Note is updated.
I have a similar question about updating the date field upon edits as well.
I assume these pieces would need to be in the save function, but in trying to use the var.set() method I can’t seem to reach the datastore.
Any ideas?
Sorry if that’s awkwardly written, still trying to get a hold of the language, so to speak.
Thank you, Justin. Yes, I think you need the new fields in the save function. If you want to send me your code I can take a look.
Will do, thanks for the offer!
Didn’t seen an email address on your site (sorry if I missed it), so I’ve temporarily uploaded the js file to my dropbox:
http://dl.dropbox.com/u/868828/app.js
Please don’t mind the mess. I’m confident there are a number of things that need some work in there, but any insight you can provide about the above would be a huge help!
Hi Jorge,
since Sencha Touch 2 Beta 3 is ready, and API is frozen, can we expect a ST2 version of your tutorial soon?
Btw, wonderful job on this tutorial, it helped me a lot.
Marian, the Sencha Touch 2 tutorial version is available here: http://miamicoder.com/2012/how-to-create-a-sencha-touch-2-app-part-1/
This made my day! Thanks Jorge, you are the best!
You’re welcome!