Over a million developers have joined DZone.

Writing a Sencha Touch Application, Part 2

· Web Dev Zone

Make the transition to Node.js if you are a Java, PHP, Rails or .NET developer with these resources to help jumpstart your Node.js knowledge plus pick up some development tips.  Brought to you in partnership with IBM.

In the first part of this Sencha Touch tutorial we started building an app that allows its user to take notes and store them on the device. Having created the foundation of the application we are in the process of building the Notes List view, which at this point looks like this:

This view is missing the Ext.list that will render the notes created by the user and the New button in the toolbar, as depicted in the mock-up we created in the first part of this tutorial:

 

Let’s work on the notes list.

Creating a Data Model in Sencha Touch

Before can create the list, we need to create the data model that will represent a note. We do this using the Ext.regModel() method:

Ext.regModel('Note', {
idProperty: 'id',
fields: [
{ name: 'id', type: 'int' },
{ name: 'date', type: 'date', dateFormat: 'c' },
{ name: 'title', type: 'string' },
{ name: 'narrative', type: 'string' }
],
validations: [
{ type: 'presence', field: 'id' },
{ type: 'presence', field: 'title' }
]
});

Our Note model, as any data model in Sencha Touch, is defined as a set of fields and the methods and properties relevant to it. The model has built-in support for validation, which we use to assert, via the validations config option, that the id and title properties require a value. We will see how model validation takes place when we build the note editor.

Data models also support associations with other models via has-many and belongs-to relationships. Although we will not use associations in this tutorial, I urge you to check out their documentation and examples. You will likely run into associations when building Sencha Touch applications.

Configuring a Sencha Touch Data Store to use HTML5 local storage

We also need a mechanism to cache our notes. The Ext.regStore() function allows us to create a data store, our notes cache, like so:

Ext.regStore('NotesStore', {
model: 'Note',
sorters: [{
property: 'date',
direction: 'DESC'
}],
proxy: {
type: 'localstorage',
id: 'notes-app-localstore'
}
Ext.regStore('NotesStore', {
model: 'Note',
sorters: [{
property: 'date',
direction: 'DESC'
}],
proxy: {
type: 'localstorage',
id: 'notes-app-localstore'
}
});
});

Ext.regStore() creates and registers a store with the framework’s Store Manager. Just as other classes in the framework do, you can use the Store Manager to lookup and modify the data stores in your application.

Our NotesStore’s model config option is the Note model. We also use the sorters option to specify that the notes will be sorted by date in descending order.

Remember that one of our application’s features is the ability to persist notes between browser sessions? The task of loading and saving model data is delegated to the store’s proxy. We use the proxy config option to define our proxy as an instance of the Ext.data.LocalStorageProxy class. This class uses the HTML5 localStorage API to save model data locally on the client browser. I find this abstraction of the local storage API one of the nicest features of the Sencha Touch framework.

Creating a Sencha Touch list

With data model and store ready, we can create the notes list like so:

NotesApp.views.notesList = new Ext.List({
id: 'notesList',
store: 'NotesStore',
itemTpl: '
<div class="list-item-title">{title}</div>
' +
'
<div class="list-item-narrative">{narrative}</div>
'
});

Nothing complicated here. The list will use the NotesStore, passed by name through the store config option. We define the markup used to render the notes with the itemTpl config option. The markup uses the list-item-title and list-item-narrative classes, which we will add to the app.css file:

.list-item-title
{
float:left;
width:100%;
font-size:90%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.list-item-narrative
{
float:left;
width:100%;
color:#666666;
font-size:80%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.x-item-selected .list-item-title
{
color:#ffffff;
}
.x-item-selected .list-item-narrative
{
color:#ffffff;
}

Now let’s add the list to the container panel using the panel’s items config option:

NotesApp.views.notesListContainer = new Ext.Panel({
id: 'notesListContainer',
layout: 'fit',
html: 'This is the notes list container',
dockedItems: [NotesApp.views.notesListToolbar],
items: [NotesApp.views.notesList]
});

Want to do a quick run on the simulator to see how we are doing? All right, but before we do that, let’s add a dummy note to the NotesStore just so we can see how the list renders a note. We can do this using the data config option:

Ext.regStore('NotesStore', {
model: 'Note',
sorters: [{
property: 'date',
direction: 'DESC'
}],
proxy: {
type: 'localstorage',
id: 'notes-app-store'
},
// TODO: remove this data after testing.
data: [
{ id: 1, date: new Date(), title: 'Test Note', narrative: 'This is simply a test note' }
]
});

On the device emulator the Notes List view should look like this:

At this point our Notes List view is almost ready. We’ve added the toolbar, the notes list, the data model and the store that will cache the notes. We’re just missing the two navigation aids that will allow the user to open the Note Editor view: the New button on the toolbar and the disclosure button on each list item.

Adding buttons to a Sencha Touch toolbar

This is how we add the “New” button to the 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 () {
// TODO: Create a blank note and make the note editor visible.
}
}
]
});

Using an hbox layout and adding a spacer to the toolbar allows us to push the New button all the way to the right. We will leave the handler function alone for a while. After we create the Note Editor view we’ll add code to open the editor from this handler.

Implementing disclosure buttons in a Sencha Touch list

The disclosure button is also very easy to implement by means of the onItemDisclosure config option:

NotesApp.views.notesList = new Ext.List({
id: 'notesList',
store: 'NotesStore',
itemTpl: '
<div class="list-item-title">{title}</div>
' +
'
<div class="list-item-narrative">{narrative}</div>
',
onItemDisclosure: function (record) {
// TODO: Render the selected note in the note editor.
}
});

We’re using one of the onItemDisclosure overrides to bind a listener to the tap event on any list item. All we will need to do inside this listener is grab the record that received the tap and pass it to the Note Editor view. But we will finish this handler later, after we create our Note Editor.

Where are we?

Let’s stop for another quick check on the simulator. The app should look like this:

Cool! We have completed the main view of the application, except the two event handlers that will allow our users to navigate to the Note Editor.

We are now ready to begin work on the Note Editor:

But that will happen in the next chapter of this series. For now I will leave you with the source code of the app at this stage:

var App = new Ext.Application({
name: 'NotesApp',
useLoadMask: true,
launch: function () {

Ext.regModel('Note', {
idProperty: 'id',
fields: [
{ name: 'id', type: 'int' },
{ name: 'date', type: 'date', dateFormat: 'c' },
{ name: 'title', type: 'string' },
{ name: 'narrative', type: 'string' }
],
validations: [
{ type: 'presence', field: 'id' },
{ type: 'presence', field: 'title' }
]
});

Ext.regStore('NotesStore', {
model: 'Note',
sorters: [{
property: 'date',
direction: 'DESC'
}],
proxy: {
type: 'localstorage',
id: 'notes-app-localstore'
},
// TODO: remove this data after testing.
data: [
{ id: 1, date: new Date(), title: 'Test Note', narrative: 'This is simply a test note' }
]
});

NotesApp.views.notesList = new Ext.List({
id: 'notesList',
store: 'NotesStore',
itemTpl: '
<div class="list-item-title">{title}</div>
' +
'
<div class="list-item-narrative">{narrative}</div>
',
onItemDisclosure: function (record) {
// TODO: Render the selected note in the note editor.
}
});

NotesApp.views.notesListToolbar = new Ext.Toolbar({
id: 'notesListToolbar',
title: 'My Notes',
layout: 'hbox',
items: [
{ xtype: 'spacer' },
{
id: 'newNoteButton',
text: 'New',
ui: 'action',
handler: function () {
// TODO: Create a blank note and make the note editor visible.
}
}
]
});

NotesApp.views.notesListContainer = new Ext.Panel({
id: 'notesListContainer',
layout: 'fit',
html: 'This is the notes list container',
dockedItems: [NotesApp.views.notesListToolbar],
items: [NotesApp.views.notesList]
});

NotesApp.views.viewport = new Ext.Panel({
fullscreen: true,
layout: 'card',
cardAnimation: 'slide',
items: [NotesApp.views.notesListContainer]
});
}
});

Stay tuned! And don’t forget to leave your comments or suggestions. :-)

 

From http://miamicoder.com/2011/writing-a-sencha-touch-application-part-2

Learn why developers are gravitating towards Node and its ability to retain and leverage the skills of JavaScript developers and the ability to deliver projects faster than other languages can.  Brought to you in partnership with IBM.

Topics:

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}