{"id":647,"date":"2011-12-01T12:38:16","date_gmt":"2011-12-01T12:38:16","guid":{"rendered":"http:\/\/www.osd.net\/blog\/?p=647"},"modified":"2012-02-06T09:26:25","modified_gmt":"2012-02-06T09:26:25","slug":"creating-a-sencha-touch-mvc-application-from-scratch-part-4","status":"publish","type":"post","link":"https:\/\/www.osd.net\/blog\/mobile-development\/creating-a-sencha-touch-mvc-application-from-scratch-part-4\/","title":{"rendered":"Creating a Sencha Touch MVC application from scratch, part 4"},"content":{"rendered":"<p>In this final part of <strong>Creating a Sencha Touch MVC application from scratch<\/strong> series we&#8217;ll add some data to our application we&#8217;ve started in <a title=\"Creating a Sencha Touch MVC application from scratch, part 1\" href=\"https:\/\/www.osd.net\/blog\/mobile-development\/creating-a-sencha-touch-mvc-application-from-scratch-part-1\/\">part 1<\/a>, <a title=\"Creating a Sencha Touch MVC application from scratch, part 2\" href=\"https:\/\/www.osd.net\/blog\/mobile-development\/creating-a-sencha-touch-mvc-application-from-scratch-part-2\/\">part 2<\/a> and <a title=\"Creating a Sencha Touch MVC application from scratch, part 3\" href=\"https:\/\/www.osd.net\/blog\/mobile-development\/creating-a-sencha-touch-mvc-application-from-scratch-part-3\/\">part 3<\/a>.<\/p>\n<p>Before we start please note that in order for the examples in this article to work, you need to place the application on a web server because we&#8217;ll use AJAX to access our data.<\/p>\n<p><strong>Let&#8217;s add some news to our application.<\/strong><\/p>\n<p>Before adding news to our application, we must define first what is actually a news item, what properties does it have. We&#8217;ll do this by creating a <a title=\"Ext.data.Model\" href=\"http:\/\/docs.sencha.com\/touch\/1-1\/#!\/api\/Ext.data.Model\">Model<\/a>.<\/p>\n<h2>Creating a Model<\/h2>\n<p><em>&#8220;A Model represents some object that your application manages. For example, one might define a Model for Users, Products, Cars, or any other real-world object that we want to model in the system.&#8221;<\/em> (from Sencha Touch docs)<\/p>\n<p>We&#8217;ll create our news item model in <strong>app\/models\/,<\/strong> so create a file named <strong>NewsItemModel.js<\/strong> with the following content:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nExt.regModel('NewsItem', {\r\n\tfields: [\r\n\t\t{name: 'title', type: 'string'},\r\n\t\t{name: 'date', type: 'string'},\r\n\t\t{name: 'content', type: 'string'}\r\n\t]\r\n});\r\n<\/pre>\n<p>Include the newly created model file in index.html, above the controllers.<\/p>\n<p>As you can see, a model is created using the <strong>Ext.regModel<\/strong> function. We pass to it the name of the model and a configuration object as parameters. In the configuration object we define our model properties in the <strong>fields<\/strong> array. Each property is an object in which we can set a <strong>name<\/strong> and a <strong>type<\/strong>.<\/p>\n<p>Our <strong>NewsItem<\/strong> model has three properties <em>(title<\/em>, <em>date<\/em> and <em>content<\/em>) with the type set to <em>string<\/em>. The type property can also be <em><\/em> an <em>int<\/em>, a <em>float<\/em>, a <em>boolean<\/em> or it can be set to <em>auto<\/em>. Sencha Touch will automatically convert each property value to the type set. When no conversion is wanted, the type can be set to <em>auto<\/em>.<\/p>\n<p>The model property object can also have a <strong>defaultValue<\/strong> set.<\/p>\n<p>Now that we have a Model, we need to create a <a title=\"Ext.data.Store\" href=\"http:\/\/docs.sencha.com\/touch\/1-1\/#!\/api\/Ext.data.Store\">Store<\/a>.<\/p>\n<h2>Creating a Store<\/h2>\n<p><em>&#8220;The Store class encapsulates a client side cache of <a id=\"ext-gen1423\" href=\"http:\/\/docs.sencha.com\/touch\/1-1\/#%21\/api\/Ext.data.Model\" rel=\"Ext.data.Model\">Model<\/a> objects. Stores load data via a <a id=\"ext-gen1424\" href=\"http:\/\/docs.sencha.com\/touch\/1-1\/#%21\/api\/Ext.data.Proxy\" rel=\"Ext.data.Proxy\">Proxy<\/a>, and also provide functions for <a href=\"http:\/\/docs.sencha.com\/touch\/1-1\/#%21\/api\/Ext.data.Store-method-sort\" rel=\"Ext.data.Store-method-sort\">sorting<\/a>, <a href=\"http:\/\/docs.sencha.com\/touch\/1-1\/#%21\/api\/Ext.data.Store-method-filter\" rel=\"Ext.data.Store-method-filter\">filtering<\/a> and querying the <a href=\"http:\/\/docs.sencha.com\/touch\/1-1\/#%21\/api\/Ext.data.Model\" rel=\"Ext.data.Model\">model<\/a> instances contained within it.&#8221;<\/em> (from Sencha Touch docs)<\/p>\n<p>The <em>Store<\/em> for our news item model will be created in <strong>app\/stores\/<\/strong> and will be placed in a file named <strong>NewsItemsStore.js<\/strong> with the following content:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nExt.regStore('NewsItems', {\r\n\r\n    model: 'NewsItem',\r\n\r\n    proxy: {\r\n        type: 'ajax',\r\n        url : 'app\/data\/news.json',\r\n    },\r\n\r\n    autoLoad: true\r\n});\r\n<\/pre>\n<p>Include the newly created file in index.html, after the models:<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;!-- MODELS --&gt;\r\n&lt;script src=&quot;app\/models\/NewsItemModel.js&quot; type=&quot;text\/javascript&quot;&gt;&lt;\/script&gt;\r\n\r\n&lt;!-- STORES --&gt;\r\n&lt;script src=&quot;app\/stores\/NewsItemsStore.js&quot; type=&quot;text\/javascript&quot;&gt;&lt;\/script&gt;\r\n<\/pre>\n<p>The <strong>Ext.regStore<\/strong> function is used for the creation of a store and, similar to <em>regModel<\/em>, we pass to it the name of the store and a configuration object.<\/p>\n<p>Since a store is a collection of model instances, we must tell what type of objects will be in it, so we&#8217;ll set the <strong>model<\/strong> property in the configuration object to be our <em>NewsItem<\/em>. The source of the data and will be defined in a proxy configuration object.<\/p>\n<p><em>&#8220;Proxies are used by <a id=\"ext-gen1499\" href=\"http:\/\/docs.sencha.com\/touch\/1-1\/#%21\/api\/Ext.data.Store\" rel=\"Ext.data.Store\">Stores<\/a> to handle the loading and saving of <a href=\"http:\/\/docs.sencha.com\/touch\/1-1\/#%21\/api\/Ext.data.Model\" rel=\"Ext.data.Model\">Model<\/a> data. Usually developers will not need to create or interact with proxies directly.&#8221;<\/em> (from Sencha Touch docs)<\/p>\n<p>Two properties are required when we define a proxy object: the <strong>type<\/strong> and the <strong>url<\/strong> of the request responsible with data retrieval. For our <em>NewsItems<\/em> store we&#8217;ll use an <em>ajax<\/em> request and a url pointing to a <strong>JSON<\/strong> news file, since the default format of the expected request result is JSON.<\/p>\n<p>Since we want our news to be loaded as soon as possible automatically, we&#8217;ll set the <strong>autoLoad<\/strong> property of the store config object to <strong>true<\/strong>.<\/p>\n<p>Now, let&#8217;s create the <strong>news.json<\/strong> file in <strong>app\/data\/<\/strong> and add some news from <a title=\"Sencha Touch Press\" href=\"http:\/\/www.sencha.com\/company\/press\/\">Sencha Touch Press<\/a>:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n[\r\n    {\r\n    \t&quot;title&quot;: &quot;Beyond jQuery: JavaScript Tools For The HTML5 Generation&quot;,\r\n    \t&quot;date&quot;: &quot;November 09, 2011&quot;,\r\n    \t&quot;content&quot;: &quot;One of the stated goals of HTML5, at least for some groups, is to replace the Flash plug-in, the gold standard for making sprites and letters dance across the screen.&quot;\r\n    },\r\n    {\r\n    \t&quot;title&quot;: &quot;What Is the Best Mobile Platform for HTML5 Development?&quot;,\r\n    \t&quot;date&quot;: &quot;November 10, 2011&quot;,\r\n    \t&quot;content&quot;: &quot;The focus of the mobile world has turned to HTML5. Right now, HTML5 is positioning itself to be the No. 3 mobile platform behind Apple's iOS and Google's Android and we will see that evolution take place over the next couple of years.&quot;\r\n    },\r\n    {\r\n    \t&quot;title&quot;: &quot;No Flash? No Problem&quot;,\r\n    \t&quot;date&quot;: &quot;November 18, 2011&quot;,\r\n    \t&quot;content&quot;: &quot;So what does the future hold for Flash? I imagine Flash eventually being used more as a creative tool than a delivery format. As Adobe continues to put more effort into exporting HTML5-ready assets from Flash Pro, it tells me the swf may be slowly dying for desktop, too.&quot;\r\n    },\r\n    {\r\n    \t&quot;title&quot;: &quot;Adobe Flash Sites Rapidly Converted To HTML5 For iOS users&quot;,\r\n    \t&quot;date&quot;: &quot;November 21, 2011&quot;,\r\n    \t&quot;content&quot;: &quot;A developer using Sencha Touch reports that translating large existing websites built with Adobe Flash to HTML5 mobile sites accessible to iOS users can now be performed by 1 or 2 people in just three weeks.&quot;\r\n    }\r\n]\r\n<\/pre>\n<h2>Using a List to display Store data<\/h2>\n<p>Next we&#8217;ll display our news.<\/p>\n<p>Open <strong>HomeIndexView.js<\/strong> and add a new link:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nhtml: '&lt;a href=&quot;#News\/index&quot; class=&quot;menu-item&quot;&gt;News&lt;\/a&gt;' +\r\n      '&lt;a href=&quot;#Home\/about&quot; class=&quot;menu-item&quot;&gt;About&lt;\/a&gt;',\r\n<\/pre>\n<p>Create a new controller for handling the news (<strong>NewsController.js<\/strong>):<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nExt.regController('News', {\r\n\r\n    \/\/ index action\r\n\tindex: function(options)\r\n    {\r\n        if ( ! this.indexView)\r\n        {\r\n            this.indexView = this.render({\r\n                xtype: 'NewsIndex',\r\n            });\r\n        }\r\n\r\n        var backBtn = this.application.viewport.query('#backBtn')[0];\r\n        backBtn.show();\r\n\r\n        backBtn.setHandler(function()\r\n\t\t{\r\n        \tExt.dispatch({\r\n        \t    controller: 'Home',\r\n        \t    action: 'index',\r\n        \t    historyUrl: 'Home\/index',\r\n        \t    \/\/\r\n        \t    animation: {\r\n        \t        type: 'slide',\r\n        \t        reverse: true,\r\n        \t    },\r\n        \t});\r\n\t\t});\r\n\r\n        this.application.viewport.setActiveItem(this.indexView, options.animation);\r\n    },\r\n});\r\n<\/pre>\n<p>Now the news controller index view (<strong>NewsIndexView.js<\/strong>):<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nApp.views.NewsIndex = Ext.extend(Ext.List, {\r\n    store: 'NewsItems',\r\n    itemTpl: '{title}, &lt;span class=&quot;date&quot;&gt;{date}&lt;\/date&gt;',\r\n});\r\nExt.reg('NewsIndex', App.views.NewsIndex);\r\n<\/pre>\n<p>As you can see we&#8217;ve used the <a title=\"Ext.List\" href=\"http:\/\/docs.sencha.com\/touch\/1-1\/#!\/api\/Ext.List\">Ext.List<\/a> component for displaying the news.<\/p>\n<p>The <em>list<\/em> component requires two properties to be defined: the <strong>store<\/strong> used for data and the <strong>itemTpl<\/strong> responsible with displaying the data. We want our list to display the <em>title<\/em> and <em>date<\/em> for each of our news items, so we put in curly braces the name of the properties we&#8217;ve defined in our <em>News<\/em> model.<\/p>\n<p>Let&#8217;s style the list items a little by opening <em>res\/css\/style.css<\/em> and adding:<\/p>\n<pre class=\"brush: css; title: ; notranslate\" title=\"\">\r\n.x-list-item-body {\r\n\tfont-size: 0.8em;\r\n\tcolor: #0b3e7b;\r\n\tfont-weight: bold;\r\n}\r\n.x-list-item-body .date {\r\n\tcolor: #666;\r\n\tfont-weight: normal;\r\n}\r\n<\/pre>\n<p>Here&#8217;s how the news list should look:<\/p>\n<p><a href=\"https:\/\/www.osd.net\/blog\/wp-content\/uploads\/2011\/12\/MvcTouch-part-4-news-list.jpg\"><img loading=\"lazy\" class=\"alignnone size-full wp-image-659\" title=\"MvcTouch part 4 news list\" src=\"https:\/\/www.osd.net\/blog\/wp-content\/uploads\/2011\/12\/MvcTouch-part-4-news-list.jpg\" alt=\"MvcTouch part 4 news list\" width=\"345\" height=\"440\" srcset=\"https:\/\/www.osd.net\/blog\/wp-content\/uploads\/2011\/12\/MvcTouch-part-4-news-list.jpg 345w, https:\/\/www.osd.net\/blog\/wp-content\/uploads\/2011\/12\/MvcTouch-part-4-news-list-235x300.jpg 235w\" sizes=\"(max-width: 345px) 100vw, 345px\" \/><\/a><\/p>\n<p>For more info on List component you can watch the <a title=\"Intro to the List Component\" href=\"http:\/\/www.sencha.com\/learn\/intro-to-the-list-component\/\">Intro to the List Component<\/a> screencast. To find what else you can do in the itemTpl property you can watch <a title=\"XTemplates; part I\" href=\"http:\/\/www.sencha.com\/learn\/xtemplates-part-i\/\">XTemplates; part I<\/a> and <a title=\"XTemplates; part II\" href=\"http:\/\/www.sencha.com\/learn\/xtemplates-part-ii\/\">part II<\/a> screencasts.<\/p>\n<h2>Creating a details screen<\/h2>\n<p>All we have to do now is to show a details screen when a list item is tapped.<\/p>\n<p>First let&#8217;s create the view by adding a file named <strong>NewsDetailsView.js<\/strong> in <em>views\/news\/<\/em> with the following content:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nApp.views.NewsDetails = Ext.extend(Ext.Panel, {\r\n    scroll: 'vertical',\r\n    styleHtmlContent: true,\r\n    style: 'background: #d8efed',\r\n\r\n    initComponent: function()\r\n    {\r\n        if (this.newsItem)\r\n        {\r\n        \tthis.html = '';\r\n            this.html += '&lt;h3&gt;'+ this.newsItem.get('title') +'&lt;\/h3&gt;';\r\n            this.html += '&lt;p&gt;'+ this.newsItem.get('date') +'&lt;\/p&gt;';\r\n            this.html += '&lt;p&gt;'+ this.newsItem.get('content') +'&lt;\/p&gt;';\r\n        }\r\n\r\n        App.views.NewsDetails.superclass.initComponent.apply(this, arguments);\r\n    }\r\n});\r\nExt.reg('NewsDetails', App.views.NewsDetails);\r\n<\/pre>\n<p>With the details view created, we now need to catch the event triggered by the list when an item is selected, so modify the news controller index action like this:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n...\r\nthis.indexView = this.render({\r\n    xtype: 'NewsIndex',\r\n    listeners: {\r\n        itemtap: function(view, index){\r\n            this.selectedNewsItem = view.store.getAt(index);\r\n            Ext.redirect('News\/details');\r\n        },\r\n        scope: this\r\n    }\r\n});\r\n...\r\n<\/pre>\n<p>As you can see on <em>itemtap<\/em> event we pass a function that has two parameters: the first one will be the instance of the list component and the second will be the index of the selected item. Using the store from the list component we can retrieve the record associated with the item selected by using the <strong>getAt<\/strong> function of the store by passing the index as the parameter. The returned record it will be a <em>NewsItem<\/em> model instance and we&#8217;ll store it as a property in the <em>News<\/em> controller in order to be accessible from the details action we&#8217;ll create next.<\/p>\n<p>News controller details action:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\ndetails: function(options)\r\n{\r\n    if ( ! this.selectedNewsItem)\r\n    {\r\n        Ext.redirect('News\/index');\r\n        return;\r\n    }\r\n\r\n    if ( ! this.detailsView)\r\n    {\r\n        this.detailsView = this.render({\r\n            xtype: 'NewsDetails',\r\n            newsItem: this.selectedNewsItem,\r\n            listeners: {\r\n                deactivate: function(view){\r\n                    view.destroy();\r\n                    delete this.detailsView;\r\n                },\r\n                scope: this\r\n            }\r\n        });\r\n    }\r\n\r\n    var backBtn = this.application.viewport.query('#backBtn')[0];\r\n    backBtn.show();\r\n\r\n    backBtn.setHandler(function()\r\n\t{\r\n    \tExt.dispatch({\r\n    \t    controller: 'News',\r\n    \t    action: 'index',\r\n    \t    historyUrl: 'News\/index',\r\n    \t    \/\/\r\n    \t    animation: {\r\n    \t        type: 'slide',\r\n    \t        reverse: true,\r\n    \t    },\r\n    \t});\r\n\t});\r\n\r\n    this.application.viewport.setActiveItem(this.detailsView, options.animation);\r\n}\r\n<\/pre>\n<p>First, if there is no selected news item the app will redirect to news index action. Next we pass the news item to the details view in the render function. Also we use the deactivate event to destroy the details view when it&#8217;s not needed.<\/p>\n<p>For more info on <strong>Listeners<\/strong> you can watch the <a title=\"Intro to Listeners\" href=\"http:\/\/www.sencha.com\/learn\/intro-to-listeners\/\">Intro to Listeners<\/a> screencast.<\/p>\n<p>If you select a news item from the list you should see a details screen like this:<\/p>\n<p><a href=\"https:\/\/www.osd.net\/blog\/wp-content\/uploads\/2011\/12\/MvcTouch-part-4-news-details.jpg\"><img loading=\"lazy\" class=\"alignnone size-full wp-image-660\" title=\"MvcTouch part 4 news details\" src=\"https:\/\/www.osd.net\/blog\/wp-content\/uploads\/2011\/12\/MvcTouch-part-4-news-details.jpg\" alt=\"MvcTouch part 4 news details\" width=\"345\" height=\"440\" srcset=\"https:\/\/www.osd.net\/blog\/wp-content\/uploads\/2011\/12\/MvcTouch-part-4-news-details.jpg 345w, https:\/\/www.osd.net\/blog\/wp-content\/uploads\/2011\/12\/MvcTouch-part-4-news-details-235x300.jpg 235w\" sizes=\"(max-width: 345px) 100vw, 345px\" \/><\/a><\/p>\n<p><strong>This is the end of part 4 and of the series!<\/strong><\/p>\n<p>You can download the final version of the project from <a title=\"MvcTouch, part 4\" href=\"https:\/\/www.osd.net\/blog\/wp-content\/uploads\/2011\/12\/MvcTouch-part-4.zip\">here<\/a>.<\/p>\n<p><strong><\/strong>If you have questions, suggestions or improvements don\u2019t hesitate to add a comment and let me know about them.<\/p>\n<div id=\"share-and-beer-container\">\t<div id=\"buy_me_a_beer_div\" class=\"single beer\">\n\t \t\n\t\t<div class=\"buy-beer\" onclick=\"document.getElementById('buy_me_a_beer_form').submit();\">\n\t\t\t<form action=\"https:\/\/www.paypal.com\/cgi-bin\/webscr\" id=\"buy_me_a_beer_form\" method=\"post\">\n\t\t\t\t<input type=\"hidden\" name=\"cmd\" value=\"_xclick\" \/>\n\t\t\t\t<input type=\"hidden\" name=\"business\" value=\"info@directaccess.ro\" \/>  \n\t\t\t\t<input type=\"hidden\" name=\"item_name\" value=\"A Beer For Creating a Sencha Touch MVC application from scratch, part 4\" \/>  \n\t\t\t\t<input type=\"hidden\" name=\"item_number\" value=\"1\" \/>  \n\t\t\t\t<input type=\"hidden\" name=\"return\" value=\"https:\/\/www.osd.net\/blog\/mobile-development\/creating-a-sencha-touch-mvc-application-from-scratch-part-4\/\" \/>  \n\t\t\t\t<input type=\"hidden\" name=\"amount\" value=\"5\" \/>  \n\t\t\t\t<input type=\"hidden\" name=\"undefined_quantity\" value=\"1\" \/>  \n\t\t\t\t<input type=\"hidden\" name=\"currency_code\" value=\"USD\" \/>  \n\t\t\t<\/form>\n\t\t\t<p class=\"buy-beer-text\">If you liked this post <br \/> you can <strong>buy me a beer<\/strong><\/p>\n\t\t<\/div>\n\t<\/div><\/div>","protected":false},"excerpt":{"rendered":"<p>In this final part of Creating a Sencha Touch MVC application from scratch series we&#8217;ll add some data to our application we&#8217;ve started in part 1, part 2 and part 3. Before we start please note that in order for the examples in this article to work, you need to place the application on a &hellip;<\/p>\n<div class=\"cta1\"><a href=\"https:\/\/www.osd.net\/blog\/mobile-development\/creating-a-sencha-touch-mvc-application-from-scratch-part-4\/\">Read more<\/a><\/div>\n<div class=\"like-excerpt\"><div\n        class=\"fb-like\"\n        data-href=\"https:\/\/www.osd.net\/blog\/mobile-development\/creating-a-sencha-touch-mvc-application-from-scratch-part-4\/\"\n        data-layout=\"button_count\"\n        data-action=\"like\"\n        data-show-faces=\"false\"\n        data-share=\"false\">\n        <\/div><\/div>","protected":false},"author":4,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[88],"tags":[98,92,93,102,100,90,89,101],"_links":{"self":[{"href":"https:\/\/www.osd.net\/blog\/wp-json\/wp\/v2\/posts\/647"}],"collection":[{"href":"https:\/\/www.osd.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.osd.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.osd.net\/blog\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/www.osd.net\/blog\/wp-json\/wp\/v2\/comments?post=647"}],"version-history":[{"count":15,"href":"https:\/\/www.osd.net\/blog\/wp-json\/wp\/v2\/posts\/647\/revisions"}],"predecessor-version":[{"id":666,"href":"https:\/\/www.osd.net\/blog\/wp-json\/wp\/v2\/posts\/647\/revisions\/666"}],"wp:attachment":[{"href":"https:\/\/www.osd.net\/blog\/wp-json\/wp\/v2\/media?parent=647"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.osd.net\/blog\/wp-json\/wp\/v2\/categories?post=647"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.osd.net\/blog\/wp-json\/wp\/v2\/tags?post=647"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}