+40 745 232 788

Online Solutions Development Blog   |  

RSS

Loading Sencha Touch controllers and views dynamically

posted by ,
Categories: JavaScript, Mobile Development
Taggs , , , ,

Usually, when creating a Sencha Touch MVC application all of its controllers and views are included manually in index.html and loaded when the app starts. But, when there are a lot of controllers and views to load, the time it takes the application to launch will be longer.

A solution for this could be to load the controllers and views dynamically when there is a need for them. Since Sencha Touch can’t do this out of the box and doing it yourself can be tricky, I’ve created a script that will do it for you named DynamicMvc.

Download DynamicMvc.js and include it in index.html file and you’re almost done. The script follows the conventions described below.

Here’s how it works.

Before a controller action is called, the script will check first if a view is registered based on the action name. So the convention is that every action must have a view. If not registered (not loaded) the view will be added. After that the controller will be loaded (if it’s not already).

The registered name of the view must be constructed from the controller and its action name, like this:

if Home is the controller and we have an action named contact, than we should have a folder under app/views named after the controller in lower case and in it there must be a view file named app/views/home/HomeContactView.js; the registered name of the view must be HomeContact.

Here’s an example:

controller name: Search
controller file: app/controllers/SearchController.js
action name: index
action’s view name: SearchIndex
view file: app/views/search/SearchIndexView.js

Notes:

  • If you are using Ext.dispatch you must specify the historyUrl property; without it DynamicMvc can’t find the right controller to load.
  • Dynamic loading the controllers and views will halt the application while the files are loaded.

That’s all about my solution for loading controllers and views dynamically.

You can download an example project from here.

If you have questions, suggestions or improvements don’t hesitate to add a comment and let me know about them.

If you liked this post
you can buy me a beer

33 Responses to Loading Sencha Touch controllers and views dynamically

  1. Hi Cam,
    Thanks again for the excellent Article.

    I have uploaded your sample code here,

    http://indiaom.com/temple1/#Home/index

    1. Click on http://indiaom.com/temple1/#Home/index [ Works fine ]
    2. Click on “About” in the tool bar [ Works fine ]
    3. Click on “Contact” in the tool bar [ Works fine [
    4. However when i go back to click on “About” it is still showing the “Contact” content.
    5. My Goal is to add in the initComponent( As i want use some the netsteld List later) Any other alternatives ? please advice

    Here is what i put in Contact View

    App.views.ContactIndex = Ext.extend(Ext.Panel, {
    	
    	html: 'Contact',
    	
    	styleHtmlContent: true,
    	style: 'background: #f4f3dc',
    	initComponent: function(){ 
    	            
    	             var dockedItems1 = [
    	            
    	                    {
    	                        xtype: 'tabpanel',
    	                        items:[
    	                               {
    	                               title: 'Tab 1',
    	                               html:  'tab 1',
    	                               },
    	                               {
    	                               title: 'Tab 2',
    	                               html:  'Tab 2',
    	                              },
    	                              {
    	                              title: 'Tab 3',
    	                              html:  'Tab 3'
    	                              },
    	                            ]
    	                    }                
    	                ]
    	          
    	              var appPanel = new Ext.Panel({
    	                 id: 'appPanel',
    	                 fullscreen: true,
    	                 //dockedItems: dockedItems1            
    	                 items: dockedItems1            
    	                });
    	    
    	             App.views.ContactIndex.superclass.initComponent.apply(this, arguments)        
       },   // end onReady 
    });
    Ext.reg('ContactIndex', App.views.ContactIndex);
    

    Thanks for your help.

    Rgds, Nag

    • App.views.ContactIndex = Ext.extend(Ext.TabPanel, {
       
      	styleHtmlContent: true,
      	style: 'background: #f4f3dc',
      	
      	items: [
      		{
      			title: 'Tab 1',
      			html:  'tab 1',
      		},
      		{
      			title: 'Tab 2',
      			html:  'Tab 2',
      		},
      		{
      			title: 'Tab 3',
      			html:  'Tab 3'
      		}
      	]
       
      });
      
      Ext.reg('ContactIndex', App.views.ContactIndex);
      

      Wouldn’t this work for you?

    • I have exactly the same problem, but I’m not using this dynamic controller loading, I’m using the previous TabBar MVC version.

      When navigating back to tabs, nothing happens…

      Did you manage to solve this?

  2. I was able to implement this. However, there was an error in calling the ext.dispatch,

    sample code:

    handler: function() {
    	Ext.dispatch({
    		controller: 'Search',
    		action: 'index',
    		animation: { type: 'pop' }}
    	);
    }
    

    error in console:
    Uncaught TypeError: Cannot read property ‘controller’ of undefined

    Any solution? Thanks

  3. Hi CAM,

    Thanks again. I need to use the initComponent so i can place the NestedList there.

    Thanks for time.. You Rock…

    Thanks, Nag

  4. Hi Cam,
    All i want is to load a nestedList. In one of the Views

    Thanks again CAM. Can you please let me know if we can send in a token of friendship for all your help. ( Say to PayPal or a Amazon gift card or some Candies )

    Thanks, Nag

    • Hi Nag,

      Can you give me more details on what you try to accomplish? You can add a NestedList to views without a need to instantiate it in the initComponent, so be more precise.

      PS: about your token of friendship: I am glad if these posts helped you and the other guys and your comments keep me going.
      Although I must say that this blog does provide a way to show some special gratitude using that plugin right under the article which allows you to choose from FB like to paypal donation (the “Buy me a beer” button) 🙂

  5. Hi Cam,
    Enjoy the Beer… Relax… Have fun.

    Any to the point,
    I am trying to embed a Netsted List in one of the Views.

    Could you please share some sample code of that. If i don’t have to sue initComponent i am fine with that tooo.

    Thanks, Nag

  6. Hi Cam,

    Kind of stuck, would be of really of great help if you could shed some light. Tried lot of different things..

    Thanks, Nag

    • Hi Nag,

      To add a nested list to one of the views do this:

      1. Open ContactIndexView.js and replace its content with:

      App.views.ContactIndex = Ext.extend(Ext.NestedList, {
      	title: 'Groceries',
      });
       
      Ext.reg('ContactIndex', App.views.ContactIndex);
      

      2. Open ContactController.js and replace its content with:

      // store with data
      var groceriesData = {
          text: 'Groceries',
          items: [
      		{
      	        text: 'Drinks',
      	        items: [
      				{
      		            text: 'Water',
      		            items: [
      		              {text: 'Sparkling', leaf: true},
      		              {text: 'Still', leaf: true}
      		            ]
      				},
      		        {text: 'Coffee', leaf: true},
      		        {text: 'Espresso',leaf: true},
      		        {text: 'Redbull', leaf: true},
      		        {text: 'Coke', leaf: true},
      		        {text: 'Diet Coke', leaf: true}
      		]
      	    },
      	    {
      	        text: 'Fruit',
      	        items: [
      				{text: 'Bananas', leaf: true},
      				{text: 'Lemon', leaf: true}
      			]
      	    },
      	    {
      	    	text: 'Snacks',
      	        items: [
      				{text: 'Nuts', leaf: true},
      				{text: 'Pretzels', leaf: true},
      				{text: 'Wasabi Peas', leaf: true}]
      	    },
      	    {text: 'Empty Category', items: []}
          ]
      };
      
      Ext.regModel('GroceriesItem', {
          fields: [{name: 'text', type: 'string'}]
      });
      
      var groceriesStore = new Ext.data.TreeStore({
          model: 'GroceriesItem',
          root: groceriesData,
          proxy: {
              type: 'ajax',
              reader: {
                  type: 'tree',
                  root: 'items'
              }
          }
      });
      
      Ext.regController('Contact', {
       
          // index action
      	index: function(options)
          {
              if ( ! this.indexView)
              {
                  this.indexView = this.render({
                      xtype: 'ContactIndex',
                      store: groceriesStore
                  });
              }
              
              this.application.viewport.setActiveItem(this.indexView, options.animation);
          },
      });
      

      (A part of this example is from the Sencha Touch documentation on NestedList)

  7. HI again Cam. I too am interested in inserting a Nested list if you are following that post up?
    Although I thought about changing my mind as the new component in Version2 still doesn’t seem to have a filter option which is very necessary for what I want to do. Unless you know of any other way?

    Keep the tutorials coming and the rest of us going please.

    Super stuff.

    Malky

  8. Hello!

    Sorry, one more problem. I have included TabBarMvc and DynamicMvc. It seems to work, but how can I load also the models dynamically? I have each model in one model/*.js file with an Ext.redModel and an Ext.data.store.

    Maybe you have a solution for that problem?

    Best Regards Tim

    • Hi, Tim!

      I didn’t find a way to load the models dynamically.

      • Thank you for your reply.
        Okay, so I have to include the model js files in my index.html file?
        But why doesn’t it work? Isn’t it possible to include these model files like the views js files?

        Best Regards Tim

        • Before a controller action is called a before-dispatch event is triggered. Capturing this event the dispatch to the controller action can be delayed until the view is loaded.

          But with the models there is no such event that triggers when its used, so there’s no easy way to tell when a model file needs to be loaded.

          But why will you want to also load the models dynamically? Loading too much “stuff” dynamically will make the app respond very slow to the user actions since the “data” needed is not available and it needs to be loaded before something can happen.

          • Okay, thank you, I understand the problem.
            So I will go the way to load all models on startup and the controllers and views dynamically.
            I think, that is then a good way, some parts on startup, some dynamically.

  9. Hi,

    Loving these tutorials… wondering if you’re planning another one soon?

    Thanks!

    –d

  10. THANKS A LOT CAM.

    It is working 100% Perfect.

    You ROCK!

    Rgds, Nag

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=""> <s> <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