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
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); } });
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.
Hi,
Could you please explain more how to use it in MVC? in my app file I added
then in a controller, when I wan to load another controller I callCode: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); } }); };
which gives me :Code:self.application.addController('CRM.controller.AttributeSelectController', { callback : function() { console.log(self.application); } });
self.application is undefined
self.application.addController('CRM.controller.AttributeSelectController', {
stupid me, self -> this .
Thanks a lot. This has was very helpful!
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();
}
Guys, this approach doesn't work in Sencha Touch 2.0. My code is absolutely the similar:
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?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); } }); };
After init() when I try to get my added before controller I get nothing. My code:
myController is undefined and I see ContactsController in array of controllers but it's not loaded.Code:var app = this.getApplication(); app.addController('ContactsController', { callback : function() { console.log(self.application); } }); var myController = this.getApplication().getController('ContactsController');
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?someAction:function(){
var controller =this.getController('AnotherController');
// Remember to call the init method manually
controller.init();
}
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:
- 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.
- 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:
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.The overall effect is that whenever any component that matches our selector fires a render event, our onPanelRendered function is called.
Last edited by ejerrywest; 6 May 2012 at 11:42 AM. Reason: clarified question
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:
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).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); },
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:
This may be obvious to other people, but it wasn't to me so I figured I would share.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); } },
Last edited by ejerrywest; 6 May 2012 at 11:39 AM. Reason: some typos