Page 2 of 3 FirstFirst 123 LastLast
Results 11 to 20 of 25

Thread: Dynamically loading MVC controller

  1. #11
    Ext JS Premium Member
    Join Date
    Jun 2011
    Posts
    14

    Default

    Quote Originally Posted by yd290276 View Post
    Hello,
    with extJS 3.x i've built a similar architecture. i tried with extjs 4.x a proof of concept to load dynamically controllers. Here is how i do this:

    1) You need an Application (says 'app.js') with at least 1 controller (says 'users')
    2) in my view 'user' that is linked to controller 'users' i add a simple button
    3) in controller 'users', add a listener to the 'click' event of view 'user' button
    4) in click event handler in controller 'users', just call method 'this.getController('newController')'
    5) ExtJs4 MVC will synchronously load the 'newController' file and add it to the application 'app.js'
    6) to handle dynamic adding of controllers, in application 'launch' method, i add an event handler for 'add' event of 'controllers' property. So this way i can call the controller 'init' method (says with 'object.init()')

    Is this answer your problem ? You can see my test source files : Attachment 26203

    Now, i'm still thinking the best way to handle/manage view replacement in viewport after adding a controller. To be continued !
    Thank you for your example yd290276, did you had the chance to do the "handle/manage view replacement in viewport after adding a controller"?

  2. #12
    Sencha User
    Join Date
    Oct 2010
    Location
    Brazil - MG, Belo Horizonte
    Posts
    62

    Default

    Quote Originally Posted by emilianm View Post
    Thank you for your example yd290276, did you had the chance to do the "handle/manage view replacement in viewport after adding a controller"?
    Well, i have two things to comment, first is it:
    You can remove all the contetn from the panel before load the desired controller like this:


    panel.removeAll(); //removes all children of panelpanel.add({ xtype : 'gridpanel', column : [....], store : someStore});
    I didn't tested it already, but it should work nice. Also, in the controller you just add them, in the controller, you add the new view on the panel (Sorry, i'm starting, and i need to test it, i just know how to do because some theads i had saw. But the panel, i think that you could get it with queryBrowser or other function)

    The second is, i had downloaded the last file to test it working, and it is really nice, i just had an question.
    After the app.js load the new controller and delete their isntance, if you try to make it again, loading the controller again, and so, delete it, an errors is trigged:

    Code:
    Uncaught TypeError: Cannot read property 'xtype' of undefined

  3. #13
    Ext JS Premium Member
    Join Date
    Jun 2009
    Location
    Eastern WA, US
    Posts
    78

    Default

    I've got dynamic controller loading by doing the following:

    Code:
    Ext.app.Application.prototype.addController = function(classPath, config) {
    	var self = this,
    		config = config || {};
    	
    	Ext.require(classPath, function() {
    		var controller = Ext.create(classPath, Ext.apply({
    			application : self
    		}, config.options || {}));
    		
    		self.controllers.add(classPath, controller);
    		
    		controller.init();
    		
    		if (config.callback) { config.callback.call((config.scope || this), config); }
    	});
    };
    
    // usage - self is a reference to the current controller
    self.application.addController('test.controller.Test', {
    	options : { 
    		lexicon : {
    			container : newCard
    		}
    	},
    	callback : function() {
    		console.log(self.application);
    	}
    });

  4. #14
    Sencha User mysticav's Avatar
    Join Date
    Mar 2007
    Location
    Mexico
    Posts
    518

    Default

    yd290276, your solution works great.

    I was looking for a way to load the init() just once for each controller. Your suggestion resolved my problem.

    I'm defining stores and views on controllers, so now all my scripts are loaded dynamically, on demand.

    Thanks.

  5. #15
    Sencha User
    Join Date
    Oct 2011
    Posts
    15

    Default

    Hi,

    Could you please explain more how to use it in MVC? in my app file I added
    Code:
    Ext.application({
        name: 'CRM',
        appFolder : 'CRM',
        
        controllers: [
        	//'CRM.controller.AppController'
        	'CRM.controller.AttributeController'
        	//'CRM.controller.AttributeSelectController'
        	//'CRM.controller.vtest'
        ],
        
        autoCreateViewport: true,
        
        launch: function() {
        
            console.log('-> Launch <-');
            
        }
         
    });
    
    
    Ext.app.Application.prototype.addController = function(classPath, config) {
    	var self = this,
    		config = config || {};
    	
    	Ext.require(classPath, function() {
    		var controller = Ext.create(classPath, Ext.apply({
    			application : self
    		}, config.options || {}));
    		
    		self.controllers.add(classPath, controller);
    		
    		controller.init();
    		
    		if (config.callback) { config.callback.call((config.scope || this), config); }
    	});
    };
    then in a controller, when I wan to load another controller I call
    Code:
    self.application.addController('CRM.controller.AttributeSelectController', {
    					callback : function() {
    						console.log(self.application);
    					}
    				});
    which gives me :

    self.application is undefined

    self.application.addController('CRM.controller.AttributeSelectController', {

  6. #16
    Sencha User
    Join Date
    Oct 2011
    Posts
    15

    Default

    stupid me, self -> this .

    Thanks a lot. This has was very helpful!

  7. #17
    Sencha User
    Join Date
    Sep 2011
    Posts
    1

    Default

    Hey, I just found a example of this in the tutorials:

    http://docs.sencha.com/ext-js/4-0/#!/guide/mvc_pt2
    ....
    When including the controllers in your application, the framework will automatically load the controller and call the init method on it. Inside the init method, you should set up listeners for your view and application events. In larger applications, you might want to load additional controllers at runtime. You can do this by using the getController method.


    (app.js)

    someAction:function(){
    var controller =this.getController('AnotherController');

    // Remember to call the init method manually

    controller
    .init();
    }

  8. #18
    Sencha User
    Join Date
    Jan 2012
    Posts
    62

    Default Sencha Touch 2.0

    Guys, this approach doesn't work in Sencha Touch 2.0. My code is absolutely the similar:
    Code:
    Ext.app.Application.prototype.addController = function(classPath, config) {
    	var self = this,
    		config = config || {};
    	Ext.Loader.setConfig({ enabled: true });
    	Ext.require(classPath);
    	Ext.require(classPath, function() {
    		var controller = Ext.create(classPath, Ext.apply({
    			application : self
    		}, config.options || {}));
    		//self.controllers.add(classPath, controller);
    		self.controllers.push(classPath);
    		
    		controller.init();
    		
    		if (config.callback) { config.callback.call((config.scope || this), config); }
    	});
    };
    The problem is connected with self.controllers.add(classPath, controller), because self.controllers in Sencha Touch is an array (not class object). How to load it in app?

    After init() when I try to get my added before controller I get nothing. My code:
    Code:
    var app = this.getApplication();
    app.addController('ContactsController',
    {
    	callback : function() {
    		console.log(self.application);
    	}
    });
    
    var myController = this.getApplication().getController('ContactsController');
    myController is undefined and I see ContactsController in array of controllers but it's not loaded.

  9. #19

    Default Should I initialize the controller for each view instance?

    someAction:function(){
    var controller =this.getController('AnotherController');

    // Remember to call the init method manually

    controller
    .init();
    }
    This is very helpful. But what if a controller may have already been loaded for a view and I want to create another instance of the view? Should I initialize it again when I create the new instance?

    As an example:

    Say I have a tabpanel, and when a user wants to add a certain type of tab I load and initialize the contoller for that type of tab.

    Later the user adds another instance of that tab view. Will the controller that I initialized earlier be able to control the events that are dispatched from this new instance of the view? Or should I call init again?

    Ultimately, I guess I don't fully understand how the controllers control function works. I see it could do one of two things:
    1. It creates event listeners on each of the view selectors at the time that the init function is run - in which case I would need to call init whenever I create a new instance of the view because the new instance did not exists when I called the controller's init function the last time.
    2. Each controller listens to all events in the app somehow and when it gets one it compares it to the control selectors that are written and fires the appropriate event - in this case I wouldn't have to call init with each new view instance.

    I ask because the first one seems much more plausible, but this sentence in the MVC tutorial seems to indicate the second option:

    The overall effect is that whenever any component that matches our selector fires a render event, our onPanelRendered function is called.
    Also, if the first one is the case, wouldn't this create an additional listener on older instances of the view? I.e. any earlier instances of the view would get an extra event handler for the same event.
    Last edited by ejerrywest; 6 May 2012 at 11:42 AM. Reason: clarified question

  10. #20

    Default Only initialize once!

    To answer my own question, in case anyone else was wondering about this.

    The controller's control function runs somewhat according to that second option above (probably not exactly like that, but functionally it calls the selector whenever it receives a controlled event). In other words you should call the controller's init function only once even if the view has not been created yet because the selector will get called when it receives this event and find all instances of the view.

    For example:

    In my use case covered above, I had a function in my main controller which opened a tab view in a tab panel like this:
    Code:
        openCustomTabView: function() {
            var customTabController = this.application.getController('CustomTab'), 
                selModel = this.getGridPanel().getSelectionModel(),
                aUniqueRecord = selModel.getSelection()[0];
    
            // have to explicitly call this when we load a controller dynamically
            customTabController.init();
            
            // openCustomTab is my own function to create the custom tab view
            customTabController.openCustomTab(aUniqueRecord);
        },
    The above code is bad because it would initialize the controller's controls every time a new instance of the view was created. As a result whenever a controlled event occurred the function that was mapped to it would fire multiple times (once for every time I initialized the controller - which occurred whenever I created a new instance of the view).

    I changed the function to the following to check for an existing controller and calling init only when a new controller was created, and this worked well:

    Code:
        
        openCustomTabView: function() {
            var customTabController = this.application.controllers.get('CustomTab'),
                selModel = this.getGridPanel().getSelectionModel(),
                aUniqueRecord = selModel.getSelection()[0];
    
            if (customTabController) {
                // if controller already exists, just create the tab view
                customTabController.openCustomTab(aUniqueRecord);
            } else {
                // otherwise create the controller, init and then create the tab view
                customTabController = this.application.getController('CustomTab');
                customTabController.init();
                customTabController.openCustomTab(aUniqueRecord);
            }
        },
    This may be obvious to other people, but it wasn't to me so I figured I would share.
    Last edited by ejerrywest; 6 May 2012 at 11:39 AM. Reason: some typos

Page 2 of 3 FirstFirst 123 LastLast

Similar Threads

  1. newbie issue -- problems loading controller
    By JKeane in forum Ext: Discussion
    Replies: 2
    Last Post: 27 Apr 2011, 12:52 PM
  2. Loading ext-all.js dynamically
    By arajagop in forum Ext 2.x: Help & Discussion
    Replies: 2
    Last Post: 18 Oct 2008, 4:49 AM
  3. dynamically loading script into dynamically added iframe in IE
    By markpele in forum Ext 2.x: Help & Discussion
    Replies: 6
    Last Post: 13 Dec 2007, 4:50 AM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •