EN   |  RO

Online Solutions Development Blog   |  

RSS

Creating a Sencha Touch MVC application from scratch, part 1

posted by CAM,
Categories: Mobile Development
Tags , ,

Introduction

Sencha Touch is an OOP JavaScript framework that makes it easy to build mobile web applications that look and feel native on iPhone, Android, and BlackBerry touch devices. To find more you can take a look at Sencha Touch website.

If you haven’t worked with JavaScript in an object-oriented way, I think you’ll find the framework a bit strange since it’s completely based on OOP. If you are not familiar with OOP concepts you could take a look here. If you have some OOP knowledge, but you don’t know how that works in JavaScript you can read this Object-Oriented JavaScript article.

Another concept you should know before we dive into coding is MVC pattern (Model View Controller). If you don’t know what MVC is you should read this article.

Let’s start

Now, let’s start creating our first Sencha Touch MVC web app.

First create the project folder on you hard-drive. I named the project MvcTouch.

In the project folder you should create the following structure:

MvcTouch project structure

In the app folder we will put all the application code. For now we only created app.js file in there, but as we move forward will add more folders and files.

The lib folder will contain the Sencha Touch framework and other JavaScript libraries, if necessary.

All the images and CSS files will go in the res folder.

The file index.html is the application main-entry point and the only html file we’ll have.

Now you should go and download the Sencha Touch framework if you haven’t did that already.

Let’s include the framework in our project:

Create a folder named sencha-touch-1.1.0 in the lib folder.

Now copy in lib/sencha-touch-1.1.0/ the sencha-touch.js file from the downloaded package (sencha-touch-1.1.0/sencha-touch.js).

We also need the Sencha Touch CSS file so let’s include that also in lib/sencha-touch-1.1.0/sencha-touch.css (the path to this file in the downloaded package is: sencha-touch-1.1.0/resources/css/sencha-touch.css).

This two files are all we need to add in our project.

Now the fun part, the coding

First, we need to add some content to our index.html:


<!DOCTYPE html>
 <html>
 <head>
 <title>MvcTouch</title>

 <!-- Sencha Touch framework -->
 <link rel="stylesheet" type="text/css" href="lib/sencha-touch-1.1.0/sencha-touch.css" />
 <script type="text/javascript" src="lib/sencha-touch-1.1.0/sencha-touch.js"></script>

 <script type="text/javascript" src="app/app.js"></script>

 </head>
 <body></body>
 </html>

Nothing complicated here, we just added the Sencha Touch required files (the js and css file) and we’ve also included our app.js file.

Let’s write some JavaScript code now.

Open app.js and add the following in it:


Ext.regApplication({
    name: 'App',
    launch: function()
    {
        alert("Yay, it's working!");
    }
});

Great, but what this code does?! Well, it creates our application.

We call Ext.regApplication function (Ext is the namespace Sencha Touch uses) by passing a configuration object with the name of our application and a function to execute when everything has loaded and the application can do “our stuff”.  Here, we’ve just added an alert box just for testing to see if everything it’s working fine.

Please note that the application name is very important because it will be our namespace in which we’ll add our custom views, controllers etc. A little fragment from Sencha Touch documentation:

Instantiating a new application automatically creates a global variable using the configured name property and sets up namespaces for views, stores, models and controllers within the app.”


//this code is run internally automatically when creating the app
Ext.ns('MyApp', 'MyApp.views', 'MyApp.stores', 'MyApp.models', 'MyApp.controllers');

So, for example, we will have something like this later in our code: App.views.HomeMainView.

Ok, but why App and not MvcTouch as the name of our project?

App is shorter and make more sense because is more consistent. If we named it like the project name, MvcTouch, we will than have MvcTouch.views.HomeMainView etc. Later when you’ll write another app if you will name the application instance again like the project name you’ll have: AnotherApp.views.HomeView. However, if we always name the application instance as App in all of our projects, we will find the “things” more quicker: the views will be always in App.views.*, the controllers in App.controllers.* etc.

Now, open index.html in Safari or Google Chrome and see if the alert is showing.

Why Safari or Google Chrome? Why not Firefox also?

Sencha Touch role is to build web apps that run on mobile devices, not on desktop browsers. The reason why Safari and Google Chrome can handle a Sencha Touch app is because they are build on top of the webkit browser engine, like a lot of browsers from mobile devices.

That’s it for part 1!

You can download the current phase of the project from here.

If you have questions, suggestions or improvements don’t hesitate to use the form below.

If you liked this post
you can buy me a beer

16 Responses to Creating a Sencha Touch MVC application from scratch, part 1

  1. cool! I’m waiting the part 2! Good job mate!

  2. Thanks for the article it’s excellent.
    One thing that is confusing me is if I name all my applications “App” – wouldn’t this cause problems in the browser with name space collision.

    Also, I read on Android devices “App” cannot be used for some reason.

    Thanks again for the article
    JRS

    • “One thing that is confusing me is if I name all my applications “App” – wouldn’t this cause problems in the browser with name space collision.”
      Only one application will be running at a time, so there will be no namespace collision.

      If you plan to use Sencha Touch with PhoneGap than you shouldn’t name you application “App” because it’s used by PhoneGap.

  3. Well-written, concise, clear, complete.

    Thanks!

  4. Great tutorial, has cleared up some issues I was having on other tutorials. Looking forward to part 3!

  5. Hi Cam!

    It’s me again. haha! i do have a question. im thinkin about it an hour. can u help me to view the data here. because it’s not working. i dont know what’s wrong here in my code. thanks to you cam!

    HERE is my CODE!

    InquiryIndexView.js

    App.views.InquiryItem = Ext.extend(Ext.List, {
        store: 'InquiryItems',
        title: 'RF Badge',
        styleHtmlContent: true,
        style: 'background: #EAEAEA',
        listeners: {
            itemtap: function (view, index) {
                this.selectedInquiryItem = view.store.getAt(index);
                alert(view.store.getAt);
                Ext.redirect('Inquiry/details');
            },
            scope: this
        },
    
        itemTpl: '{strRequestNo}</br>Requested by {EmployeeName} ({EmployeeNo})</br> Access to {AreaToAccess} for {TypeofAuthorityToEnter}'
    });
    
    Ext.reg('InquiryItem', App.views.InquiryItem);
    
    App.views.InquiryListATE = Ext.extend(Ext.List, {
        store: 'InquiryATEItems',
        scroll: 'vertical',
        styleHtmlContent: true,
        style: 'background: #EAEAEA', listeners: {
            itemtap: function (view, index) {
                this.selectedInquiryATEItem = view.store.getAt(index);
                alert(view.store.getAt);
                Ext.redirect('Home/index');
            },
            scope: this
        },
    
        itemTpl: '{strRequestNo}</br>Requested by {EmployeeName} ({EmployeeNo})</br> ({RequestDatetime}) AS {TypeofAuthorityToEnter}'
    });
    
    Ext.reg('InquiryListATE', App.views.InquiryListATE);
    
    
    App.views.InquiryIndex = Ext.extend(Ext.TabPanel, {
        activeItem: 0,
        style: 'background: #EAEAEA',
        items: [App.views.InquiryItem, {
            title: 'Authority To Enter',
            items: App.views.InquiryListATE
        }]
    });
    Ext.reg('InquiryIndex', App.views.InquiryIndex);
    
    
    
    

    InquiryDetailsView.js

    App.views.InquiryDetails = Ext.extend(Ext.Panel, {
        scroll: 'vertical',
        styleHtmlContent: true,
    
        initComponent: function () {
            if (this.inquiryItem) {
                this.html = '';
                this.html += '<h3>' + this.inquiryItem.get('strRequestNo') + '</h3>';
                this.html += '<p>' + this.inquiryItem.get('EmployeeNo') + '</p>';
                this.html += '<p>' + this.inquiryItem.get('EmployeeName') + '</p>';
                this.html += '<p>' + this.inquiryItem.get('EmployeeDepartment') + '</p>';
                this.html += '<p>' + this.inquiryItem.get('ReasonForRequest') + '</p>';
                this.html += '<p>' + this.inquiryItem.get('AreaToAccess') + '</p>';
                this.html += '<p>' + this.inquiryItem.get('TypeofAuthorityToEnter') + '</p>';
                this.html += '<p>' + this.inquiryItem.get('RequestDatetime') + '</p>';
                this.html += '<p>' + this.inquiryItem.get('strRequestStatus') + '</p>';
            }
    
            App.views.InquiryDetails.superclass.initComponent.apply(this, arguments);
        }
    });
    Ext.reg('InquiryDetails', App.views.InquiryDetails);
    
    

    InquiryController.js

    Ext.regController('Inquiry', {
        index: function (options) {
            if (!this.indexView) {
                this.indexView = this.render({
                    xtype: 'InquiryIndex',
                    listeners: {
                      itemtap: function (view, index) {
                        this.selectedInquiryItem = view.store.getAt(index);
                          Ext.redirect('Inquiry/details');
                    }, 
                    scope: this
             }
    
                });
            }
    
            var LogoutBtn = this.application.viewport.query('#LogoutBtn')[0];
            LogoutBtn.show();
    
            this.application.viewport.setActiveItem(this.indexView, options.animation);
        },
        details: function (options) {
            if (!this.selectedInquiryItem) {
                Ext.redirect('Inquiry/index');
            }
    
            if (!this.detailsView) {
                this.detailsView = this.render({
                    xtype: 'InquiryDetails',
                    inquiryItem: this.selectedInquiryItem,
                    listeners: {
                        deactivate: function (view) {
                            view.destroy();
                            delete this.detailsView;
                        },
                        scope: this
                    }
                });
            }
            var LogoutBtn = this.application.viewport.query('#LogoutBtn')[0];
            LogoutBtn.hide();
    
            this.application.viewport.setActiveItem(this.detailsView, options.animation);
        }
    });
    
  6. Hi Cam

    I asked some time ago if you would do a tut on ST2 MVC when it was ready. The implementation in the Beta should be fine. Are you ready to do the tut? It was a great help with ST1.

    Also maybe the TabPanel MVC example too?

  7. Hi Cam,
    I have used “Sencha Touch TabBar in a MVC structured application.” in some Applications and it is Awesome! But I guess it will not work with ST2 ;-)

    I hope you soon will write something. It’s a great help.

  8. hi !

    How can I do List paging in sencha touch mvc ? .for example there are 36 records and I want to list ten items each page on screen. Help .Is it possible to do with Ext.plugins.ListPagingPlugin?

  9. Hi all,
    I am new to sencha touch
    How can I display an image in the detail view if there is a url of the image is available in the json ?????
    Can you please help me..

Add a Comment

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Also, if you want to display source code you can enclose it between [html] and [/html], [js] and [/js], [php] and [/php] etc