Chapter 2. Creating an Application

In the previous chapter, we looked at the Sencha MVC architecture and also listed the various framework classes which map to the model-view-controller. In this chapter we will take a step-by-step approach to create a functional application in ExtJS as well as Sencha Touch, using the MVC architecture and the framework classes related to it. For the sake of completeness and illustration of the concepts, we will be taking up an application requirement and implementing it in ExtJS and Sencha Touch. Though most of the features are common in ExtJS and Touch, there are features such as profiles which are unique to Touch. In this chapter, we will cover the common functionality across the two frameworks and visit the specific features in the subsequent chapters.

As a requirement, we will be creating an application, which would:

  • Show the list of departments and the users
  • Show the list of users for a selected department
  • Allow the user to edit user information
  • Refresh the users list to get all the users of all the departments

The following screenshot shows the layout of the page we would like to have when the application is run:

Creating an Application

The following screenshot depicts the Edit User panel, which would show the field values populated from the selected user's record and allow the user to modify them:

Creating an Application

After clicking on Save, the modified user's information will appear on the user list.

Application design

Let us delve deeper into the application that we want to create in ExtJS and Touch. First, let us identify the different views we would like to have in our application. Deciding about the number of views is totally based on the granularity at which you would like to work on. For example, in this application we can define the panel's top title bar as one view that can show a Title and a Refresh button on the top of a panel to which it is added. Similarly, the Save and Cancel buttons on the Edit User panel can be encapsulated inside the ButtonBar view and can be used on the panels where we need to show those two buttons. If tomorrow, one more button such as the Help button needs to be added to it so that we start seeing three buttons in all the places in the application, then making that change would be a lot faster and cleaner. However, if we take a different level of granularity, then we will have a panel with the title bar showing the panel title and a Refresh icon. Also, we would have an Edit User panel with the Save and Cancel buttons. So, is there a rule to decide when I should have the Save and Cancel buttons added to the panel, directly, and when I should wrap them into a ButtonBar view and add it to the panel? Well, there is no pre-defined rule or recommendation from Sencha. It totally depends upon how you want to model your application to achieve the goals, such as re-usability, agility (incorporating changes quickly), maintainability, and testability. So, if you see that the Save and Cancel buttons would appear in multiple places in your application, then that tells us that it would be better to create a ButtonBar view and use it across the panels in the application.

For simplicity, we will be defining the following views:

  • Users List: This shows the list of users for all or a particular department
  • Departments List: This shows the list of departments
  • Edit User: This shows the selected user information and allows the editing of the same

Now, let us list out the models. Going by the same goals, we will define the following models:

  • User: This model represents a user
  • Department: This model represents a department

Since we will be showing a list of users and departments, we will define the following stores:

  • Users: This contains a collection of User models and will be used to show the departments' list
  • Departments: This contains a collection of Department models and will be used to show the users list

The store would load the data from a data source. So, let us define the following datafiles which we will be using in the application to load the data in the different stores:

  • users.json

    This datafile contains a list of users. Information, such as name, email, and the department code is returned for a user id, which identifies a user uniquely.

    {
        success: true,
        users: [
            {id: 1, name: 'Sunil',    email: '[email protected]', department:'FIN'},
            {id: 2, name: 'Sujit', email: '[email protected]', department:'FIN'},
            {id: 3, name: 'Alok', email: '[email protected]', department:'DEV'},
            {id: 4, name: 'Pradeep', email: '[email protected]', department:'SAL'},
            {id: 5, name: 'Ajit', email: '[email protected]', department:'DEV'}
        ]
    }

    The users field in the JSON contains the users list. For each user, it contains the id, name, email, and department code. The success property is used to report the application's success/failure, and the true property indicates success.

  • departments.json

    This datafile contains a list of departments with their code, name, and location.

    {
        success: true,
        departments: [
            {code: 'FIN', name: 'Finance',    location: 'Hyderabad'},
            {code: 'SAL', name: 'Sales', location: 'Hyderabad'},
            {code: 'DEV', name: 'Development', location: 'Agra'}
        ]
    }

    The departments field in the JSON contains the department list. For each department, it contains code, name, and location. The success property is used to report the application's success/failure, and the true property indicates success.

One last thing we are left with is the controller. Again, the question is whether we should have one controller or multiple controllers? I generally recommend having one controller per entity in the application. In our application, we have got two entities – User and Department. So, we will have the following controllers:

  • Users: This controller is used to manage the views related to the User entity
  • Departments: This controller is used to manage the views related to the Department entity

Now that we have identified all the pieces of our application, let us see how each one of them needs to be implemented in ExtJS and Touch and understand how they need to be assembled to create a functional application, which meets the requirements that we have outlined earlier.

ExtJS-based application

In ExtJS, we will be dealing with the following classes:

  • Ext.app.Application: This is the application class
  • Ext.app.Controller: This class provides the controller functionality
  • Ext.container.Container, Ext.Component: This class and its sub-classes are used for providing views
  • Ext.data.Model: This class helps us represent a model which the Ext.data.Store class can understand
  • Ext.data.Store: This class contains a collection of Ext.data.Model type objects and is used on the components to show a list of records

Folder structure

In Sencha MVC architecture, folder structure is very important as the underlying class loading uses the pre-defined rules, related to the folder structure, to load the classes automatically for us, on demand. More about the class loading and how it works will be covered in the next chapter.

Create a folder named extjsapp under WebContent in the SenchaArchitectureBook project, which we created in Chapter 1, Sencha MVC Architecture, and add the following files and directories:

  • app: This is the main application directory. This will have the model, view, controller, and store directories
    • model
    • User.js
    • Department.js
    • store
    • Users.js
    • Departments.js
    • view
    • userList.js
    • userEdit.js
    • departmentList.js
    • Viewport.js
    • controller
    • Users.js
    • Departments.js
  • data: This contains the JSON datafiles
  • extjs-4.1.0-rc1: This contains the ExtJS framework
  • app.js: This contains the entry point code for the application
  • index.html: This is the HTML for the application

Once created, the folder structure should look like the following screenshot:

Folder structure

Model

Let us define the different models for our application. We will have the following models:

  • User
  • Department
User

Save the following code inside the appmodelUser.js file:

Ext.define('AM.model.User', {
    extend: 'Ext.data.Model',
    fields: ['id', 'name', 'email','department'],
});

The code that we just used defines a User model, which represents a user in the application. AM.model in the class name is important as it is used by the loader to identify the file, which contains the class definition and loads the same. AM is the name of the application, which acts as a namespace. This has been explained, in detail, in the later part of this section.

Department

Save the following code inside the appmodelDepartment.js file:

Ext.define('AM.model.Department', {
    extend: 'Ext.data.Model',
    fields: ['code', 'name', 'location']
});

The code that we just used defines a Department model, which represents a department in the application.

Store

Similar to the models, now let us define the stores. In the application, we will have the following stores:

  • Users
  • Departments
Users

Save the following code inside the appstoreUsers.js file:

Ext.define('AM.store.Users', {
    extend: 'Ext.data.Store',
    model: 'AM.model.User',
    autoLoad: true,  //loads data as soon as the store is initialized
    
    proxy: {
        type: 'ajax',
        api: {
            read: 'data/users.json'
        },
        reader: {
            type: 'json',
            root: 'users',
            successProperty: 'success'
        }
    },
    
    
    filterUsersByDepartment: function(deptCode) {
      this.clearFilter();
      this.filter([{
            property: 'department',
            value: deptCode
        }]);
    },
    
    refresh: function() {
      this.clearFilter();
    }
});

The code that we just used defines a store, which keeps a collection of User models, indicated by the model property. The proxy property contains the information about the AJAX proxy that the store will use to call the specified read URL data/user.json to load the users. Reader is configured based on the users.json file where the root must be set to the config in the users.json file, which contains the user records, which is users.

The autoLoad: true property will tell the framework to load the data into the store as soon as the store is instantiated.

The filterUsersByDepartment method is a public method, which filters the store using the specified department code. This method is called as part of the handling of the selection of a specific department from the Departments List view.

The refresh method is a public method, which clears all the filters applied on the store data and shows all the records in the store. This method is called as part of the handling of the Refresh button click on the Users List view.

Departments

Save the following code inside the appstoreDepartments.js file:

Ext.define('AM.store.Departments', {
    extend: 'Ext.data.Store',
    model: 'AM.model.Department',
    autoLoad: true,
    
    proxy: {
        type: 'ajax',
        api: {
            read: 'data/departments.json'
        },
        reader: {
            type: 'json',
            root: 'departments',
            successProperty: 'success'
        }
    }
});

The code that we just used defines store, which would contain the departments data. Every entry in it will be a Department model.

View

The application will have the following views:

  • User List
  • Edit User
  • Department List
User List

Save the following code inside the appviewuserList.js file:

Ext.define('AM.view.user.List' ,{
    extend: 'Ext.grid.Panel',
    alias : 'widget.userlist',

    title : 'All Users',
    store: 'Users',

    columns: [
        {header: 'Name',  dataIndex: 'name',  flex: 1},
        {header: 'Email', dataIndex: 'email', flex: 1}
    ],
    
    tools:[{
        type:'refresh',
        tooltip: 'Refresh',
        handler: function(){
        	var pnl = this.up('userlist'),
        	pnl.getStore().refresh();
        	pnl.setTitle('All Users'),
        }
    }],
    
    filterUsersByDepartment: function(deptCode) {
    	this.getStore().filterUsersByDepartment(deptCode);
    }
});

The code that we just used defines the User List view, which extends a grid panel. The Users store is associated with it. The grid will show two columns Name and Email, and has a toolbar with the Refresh button. Since, the refresh logic is private to the User List view, the handler is registered in the view class where it is refreshes the store and sets the title correctly.

The filterUsersByDepartment method is a public method, which filters the store using the specified department code. This method is called as part of the handling of the selection of a specific department from the Departments List view. This relies on the store's filterUsersByDepartment entity to accomplish the task.

userlist has been mentioned as an alias, which can be used as xtype for the User List view.

User Edit

Save the following code inside the appviewuserEdit.js file:

Ext.define('AM.view.user.Edit', {
    extend: 'Ext.window.Window',
    alias : 'widget.useredit',

    requires: ['Ext.form.Panel'],

    title : 'Edit User',
    layout: 'fit',
    autoShow: true,
    height: 120,
    width: 280,

    initComponent: function() {
        this.items = [
            {
                xtype: 'form',
                padding: '5 5 0 5',
                border: false,
                style: 'background-color: #fff;',

                items: [
                    {
                        xtype: 'textfield',
                        name : 'name',
                        fieldLabel: 'Name'
                    },
                    {
                        xtype: 'textfield',
                        name : 'email',
                        fieldLabel: 'Email'
                    }
                ]
            }
        ];

        this.buttons = [
            {
                text: 'Save',
                action: 'save'
            },
            {
                text: 'Cancel',
                action: 'cancel'
            }
        ];

        this.callParent(arguments);
    }
});

The code that we just used defines the Edit User view. This extends the Window and has a form panel, which contains two text fields and two buttons.

The name property on the text fields has been specified and their value must match with the field name on the User model. This will be helpful in loading the data from the model into the form.

useredit has been mentioned as an alias, which can be used as xtype for the Edit User view.

Department List

Save the following code inside the appviewdepartmentList.js file:

Ext.define('AM.view.department.List' ,{
    extend: 'Ext.grid.Panel',
    alias : 'widget.departmentlist',

    title : 'Departments',
    store: 'Departments',

    columns: [
        {header: 'Name', dataIndex: 'name', flex: 1},
        {header: 'Location', dataIndex: 'location', flex: 1}
    ]
});

In the code we just used, we defined the Department List view, which extends a grid panel and uses the Departments store. It has two columns, Name and Location. departmentlist has been mentioned as an alias, which can be used as xtype for the Department List view.

Viewport

Save the following code inside the appviewViewport.js file:

Ext.define('AM.view.Viewport', {
    extend: 'Ext.container.Viewport',
    
    requires: ['AM.view.department.List', 'AM.view.user.List'],

    layout: 'border',
    config: {
        items: [{
        	region: 'west',
        	width: 200,
            xtype: 'departmentlist'
        }, {
        	region: 'center',
            xtype: 'userlist'
        }]
    }
});

Controller

In the application, we will have the following controllers:

  • Users
  • Departments
Users

Save the following code inside the appcontrollerUsers.js file:

Ext.define('AM.controller.Users', {
    extend: 'Ext.app.Controller',

    config: {
      stores: ['Users'],

        models: ['User'],

        views: ['user.Edit', 'user.List'],

        refs: [{
            ref: 'usersList',
            selector: 'userlist'
        }]
    },
    
    init: function(app) {
        this.control({
            'userlist dataview': {
                itemdblclick: this.editUser
            },
            'useredit button[action=save]': {
                click: this.updateUser
            },
            'useredit button[action=cancel]': {
                click: this.cancelEditUser
            }
        });
        
        app.on('departmentselected', function(app, model) {
        	this.getUsersStore().filterUsersByDepartment(model.get('code'));
        	this.getUsersList().setTitle(model.get('name') + ' Users'),
        }, this);
    },

    editUser: function(grid, record) {
        var edit = Ext.create('AM.view.user.Edit').show();

        edit.down('form').loadRecord(record);
    },

    updateUser: function(button) {
        var win    = button.up('window'),
            form   = win.down('form'),
            record = form.getRecord(),
            values = form.getValues();

        record.set(values);
        win.close();
            },
    cancelEditUser: function(button) {
      var win    = button.up('window'),
      win.close();
    }
});

In the code that we just used, we defined the Users controller, which manages the userlist and edituser views. It also uses the Users store and the User model. All these are listed in a controller using the views, stores, and models properties.

The init method in a controller class is called by the framework to initialize the controller, even before the application is launched. The typical task that we do here is registering the handlers for the different view elements. This is done by calling the control method of the controller, where we specify the xtype-based selectors to identify the view component (for example, useredit button[action=save] identifies the Save button on the Edit User window) and register their event handlers.

The controller also handles the departmentselected event in the application, which is fired by the Departments controller when a particular department is selected. Let us see what the Departments controller looks like.

Departments

Save the following code inside the appcontrollerDepartments.js file:

Ext.define('AM.controller.Departments', {
    extend: 'Ext.app.Controller',

    config: {
      stores: ['Departments'],

        models: ['Department'],

        views: ['department.List']
    },
    
    init: function() {
        this.control({
            'departmentlist': {
                itemclick: this.showDepartmentUser
            }
        });
    },

    showDepartmentUser: function(grid, model, itemEl, idx, e, eOpts) {
      var app = this.application;
        app.fireEvent('departmentselected', app, model);
    }
});

The code that we just used defines the Departments controller, which manages the department-related view, model, and the store. It fires the departmentselected event on the application when a department is selected.

Application

Save the following code inside the app.js file:

Ext.application({
    name: 'AM',  //application name that becomes the namespace

    // automatically create an instance of AM.view.Viewport
    autoCreateViewport: true,

    controllers: [
        'Users', 'Departments'
    ]
});

In the code that we just used, we are initializing the application. The name:'AM' property is a very important property. It creates an automatic namespace for our application. Due to this, we defined all the classes starting with AM, for example, AM.model.User. Once specified, if the framework comes across with any class name starting with AM, it will look for that class in the app folder. For example, when it encounters AM.model.User, it will look for the User.js file inside the appmodel folder. Similarly, for AM.view.user.List it will look for the List.js file inside the appviewuser folder.

The autoCreateViewport:true property will tell the framework to automatically look for the Viewport.js file inside the appview folder and create the viewport using it.

An application is a collection of controllers, which internally manage one or more views to accomplish the overall requirement. All the controllers, which constitute the application, need to be specified as part of the controllers property. A fully qualified name, such as AM.controller.Users, is not required as the framework will automatically look for the Users controller inside the appcontroller folder.

index.html

Save the following code inside the index.html file:

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title id="page-title">Account Manager</title>

    <link rel="stylesheet" type="text/css" href="extjs-4.1.0-rc1/resources/css/ext-all.css">
    <script type="text/javascript" src="extjs-4.1.0-rc1/ext-debug.js"></script>
    
    <script type="text/javascript" src="app.js"></script>
</head>
<body>

</body>
</html>

Publish the application to Apache Tomcat, Start the server, and access http://<host>:<port>/SenchaArchitectureBook/extjsapp/index.html in the browser. You shall see the following screen:

index.html

Selecting a particular department from the Departments list shows the users from the selected department, as shown in the following screenshot:

index.html

Double-click on the user record. This will bring up the Edit User view with the values populated from the selected user, as shown in the following screenshot:

index.html

Make some change to the user information, say, Name, and click on Save. We shall see the updated information in the users list, as shown in the following screenshot:

index.html

Click on the Refresh icon on the users list. This will reload all the users in the users list.

Sencha Touch-based application

For the MVC architecture, as ExtJS and Touch have a lot of things in common, the overall approach would remain similar for Touch as well. In Sencha Touch, we will be dealing with the following classes:

  • Ext.app.Application: This is the application class
  • Ext.app.Controller: This class provides the controller functionality
  • Ext.Container, Ext.Component: These classes and their sub-classes are used for providing views
  • Ext.data.Model: This class helps us represent a model which the Ext.data.Store class can understand
  • Ext.data.Store: This class contains a collection of Ext.data.Model type objects and is used on the components to show a list of records

Folder structure

Create a folder touchapp under WebContent in the SenchaArchitectureBook project, which we created in Chapter 1, Sencha MVC Architecture, and add the following files and directories:

  • app: This is the main application directory. It will have a model, view, controller, and store directories:
    • model
    • User.js
    • Department.js
    • store
    • Users.js
    • Departments.js
    • view
    • userList.js
    • userEdit.js
    • departmentList.js
    • controller
    • Users.js
    • Departments.js
  • data: This contains the JSON datafiles.
  • sencha-touch-2.0.0: This contains the ExtJS framework.
  • app.js: This contains the entry point code for the application.
  • index.html: This is the HTML for the application.

Once created, the folder structure should look like the following screenshot:

Folder structure

Model

We will have the following models:

  • User
  • Department
User

Save the following code inside the appmodelUser.js file:

Ext.define('AM.model.User', {
    extend: 'Ext.data.Model',
    config: {
        fields: ['id', 'name', 'email', 'department']
    }
});

The code that we just used defines the User model.

Department

Save the following code inside the appmodelDepartment.js file:

Ext.define('AM.model.Department', {
    extend: 'Ext.data.Model',
    config: {
        fields: ['code', 'name', 'location']
    }
});

The code that we just used defines the Department model.

Store

In the application we will have the following stores:

  • Users
  • Departments
Users

Save the following code inside the appstoreUsers.js file:

Ext.define('AM.store.Users', {
    extend: 'Ext.data.Store',
    
    config: {
        autoLoad: true,
        model: 'AM.model.User',
        storeId: 'Users',
        proxy: {
            type: 'ajax',
            api: {
                read: 'data/users.json'
            },
            reader: {
                type: 'json',
                rootProperty: 'users'
            }
        }
        
    },
    
    filterUsersByDepartment: function(deptCode) {
      this.clearFilter();
      this.filter([{
            property: 'department',
            value: deptCode
        }]);
    },
    
    refresh: function() {
      this.clearFilter();
    }
});

The code that we just used defines the Users store, which contains the collection of User models.

Departments

Save the following code inside the appstoreDepartments.js file:

Ext.define('AM.store.Departments', {
    extend: 'Ext.data.Store',
    model: 'AM.model.Department',
    
    config: {
        autoLoad: true,
        model: 'AM.model.Department',
        storeId: 'Departments',
        proxy: {
            type: 'ajax',
            api: {
                read: 'data/departments.json'
            },
            reader: {
                type: 'json',
                rootProperty: 'departments'
            }
        }
    }
});

The code that we just used defines the Departments store, which contains the collection of Department models.

View

The application will have the following views:

  • User List
  • Edit User
  • Department List
User List

Save the following code inside the appviewuserList.js file:

Ext.define('AM.view.user.List' ,{
    extend: 'Ext.Container',
    alias : 'widget.userlist',

    config: {
        ui: 'light',
        layout: {
            type: 'fit'
        },
        items: [
            {
                xtype: 'toolbar',
                docked: 'top',
                title: 'All Users',
                defaults: {
                    iconMask: true
                },
                items: [{
                    xtype: 'spacer'
                },
                {
                    iconCls: 'refresh',
                    ui: 'confirm',
                    handler: function(){
                    	this.up('userlist').down('list').getStore().refresh();
                    	this.up('toolbar').setTitle('All Users'),
                    }
                }]
            },
            {
                xtype: 'list',
                height: '100%',
                ui: 'round',
                itemTpl: [
					'<div style="float:left;">{name}</div>',
					'<div style="float:left;position:absolute;padding-left:150px;">{email}</div>'
                ],
                store: 'Users',
                onItemDisclosure: true
            }
        ]
    }
});

The code that we just used defines the User List view by extending the Container class. It shows a list of users with the disclosure option (refer to the Sencha Touch API documentation of Ext.dataview.List for more detail) and a toolbar on the top with the Title and the Refresh button. The list uses the Users store to load data. Similar to the ExtJS-based app, the handler for the Refresh button is implemented inside the view as the logic is local to the view.

The userlist alias will act as xtype for this view.

User Edit

Save the following code inside the appviewuserEdit.js file:

Ext.define('AM.view.user.Edit', {
    extend: 'Ext.form.Panel',
    alias : 'widget.useredit',

    config: {
        ui: 'light',
        items: [
            {
                xtype: 'titlebar',
                docked: 'top',
                title: 'Edit User'
            },
        	{
                xtype: 'textfield',
                label: 'Name',
                name: 'name',
                labelWidth: '50%',
                required: true
            },
            {
                xtype: 'textfield',
                label: 'Email',
                name: 'email',
                labelWidth: '50%',
                required: true
            },
            {
            	xtype: 'toolbar',
            	docked: 'bottom',
            	items: [{
                    xtype: 'button',
                    margin: 10,
                    align: 'left',
                    ui: 'confirm',
                    action: 'save',
                    text: 'Save'
                }, {
                    xtype: 'spacer'
                }, {
                xtype: 'button',
                    margin: 10,
                    align: 'right',
                    ui: 'decline',
                    action: 'cancel',
                    text: 'Cancel'

                }]
            }
            
        ]
    }
});

The code that we just used defines the Edit User view by extending the form panel. It contains two text fields and a bottom toolbar with Save and Cancel buttons.

The useredit alias will be used as xtype for this view.

Department List

Save the following code inside the appviewdepartmentList.js file:

Ext.define('AM.view.department.List' ,{
    extend: 'Ext.Container',
    alias : 'widget.departmentlist',

    config: {
        ui: 'light',
        layout: {
            type: 'fit'
        },
        items: [
            {
                xtype: 'titlebar',
                docked: 'top',
                title: 'Departments'
            },
            {
                xtype: 'list',
                height: '100%',
                ui: 'round',
                itemTpl: [
          '<div style="float:left;">{name}</div>',
          '<div style="float:left;position:absolute;padding-left:150px;">{location}</div>'
                ],
                store: 'Departments',
                onItemDisclosure: false
            }
        ]
    }
});

The code that we just used defines the Department List view by extending the Container class. It shows a list of departments without the disclosure option. The list uses the Departments store to load data.

The departmentlist alias will act as the xtype for this view.

Controller

In the application, we will have the following controllers:

  • Users
  • Departments
Users

Save the following code inside the appcontrollerUsers.js file:

Ext.define('AM.controller.Users', {
    extend: 'Ext.app.Controller',

    config: {
    	stores: ['Users'],

        models: ['User'],

        views: ['user.Edit', 'user.List'],

        refs: {
        	usersPanel: 'userlist'
        }
    },
    init: function(app) {
        this.control({
        	'userlist list': {
                disclose: this.editUser
            },
            'useredit button[action=save]': {
                tap: this.updateUser
            },
            'useredit button[action=cancel]': {
                tap: this.cancelEditUser
            }
        });
        
        app.on('departmentselected', function(app, model) {
        	this.getUsersStore().filterUsersByDepartment(model.get('code'));
        	this.getUsersPanel().down('toolbar').setTitle(model.get('name') + ' Users'),
        }, this);
    },
    editUser: function(view, model, t, index, e, eOpts) {
        var edit = Ext.create('AM.view.user.Edit'),
        Ext.Viewport.add(edit);

        edit.setRecord(model);
        Ext.Viewport.setActiveItem(edit);
    },
    updateUser: function(button, e ,eOpts) {
        var form   = button.up('formpanel'),
        var record = form.getRecord(),
            values = form.getValues();

        record.set(values);
        this.getUsersStore().sync();
        Ext.Viewport.setActiveItem(0);
    },
    cancelEditUser: function(button, e ,eOpts) {
    	Ext.Viewport.setActiveItem(0);
    },
    showUsersList: function() {
    	var list = Ext.create('AM.view.user.List'),
        Ext.Viewport.add(list);
    },
    getUsersStore: function() {
    	return this.getUsersPanel().down('list').getStore();
    }
});

The code that we just used defines the Users controller.

Departments

Save the following code inside the appcontrollerDepartments.js file:

Ext.define('AM.controller.Departments', {
    extend: 'Ext.app.Controller',

    config: {
    	stores: ['Departments'],

        models: ['Department'],

        views: ['department.List']
    }

	init: function() {
        this.control({
            'departmentlist list': {
                itemtap: this.showDepartmentUser
            }
        });
    },

    showDepartmentUser: function(view, idx, t, model, e, eOpts) {
    	var app = this.initialConfig.application;
        app.fireEvent('departmentselected', app, model);
    }
});

The code that we just used defines the Departments controller.

Application

Save the following code inside the app.js file:

Ext.application({
  name: 'AM',

    // dependencies
    controllers: ['Users', 'Departments'],
    
    // launch application
    launch: function() {
        var config = {
       layout: 'fit',
        items: [{
          xtype: 'departmentlist',
          docked: 'left',
          width: 400
        }, {
          xtype: 'userlist'
        }]
            
      };

        Ext.Viewport.add(config);
    }
});

In the last line, we added the panel, with department list and user list, to the viewport. Since the viewport concept is not very straightforward on touch devices, the framework wraps those differences and provides us with static methods, such as add, to add content to it.

index.html

Save the following code inside the index.html file:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Account Manager</title>

<!-- Sencha Touch specific files -->
<link rel="stylesheet" type="text/css" href="sencha-touch-2.0.0/resources/css/sencha-touch.css">
<script type="text/javascript" src="sencha-touch-2.0.0/sencha-touch-all-debug.js"></script>

<!-- Application specific files -->
<script type="text/javascript" src="app.js"></script>
 
</head>
<body>

</body>
</html>

Publish the application to Apache Tomcat, Start the server, and access http://<host>:<port>/SenchaArchitectureBook/touchapp/index.html in the Webkit browser. You should see the following screen:

index.html

Selecting a particular department from the Departments list shows the users from the selected department, as shown in the following screenshot:

index.html

Double-click on the User Record button. This will bring up the Edit User view with the values populated from the selected user, as shown in the following screenshot:

index.html

Make some change to the user information, say, Name, and click on Save. We should see the updated information in the users list, as shown in the following screenshot:

index.html

Click on the Refresh icon on the users list. This will reload all the users in the users list.

index.html
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.188.57.172