PDA

View Full Version : Best Practice for obtaining reference to View inside Controller method



sl5337
29 Jun 2012, 5:43 AM
I've seen many different examples of this in the documentation and sample code. I've adopted a certain method for accomplishing this but I wanted to throw it out here and make sure there isn't a 'better' way. The situation is very typical: the user clicks a toolbar button and I want to show a particular view. Given the view class 'MyApp.view.MyViewClass' with id 'myViewClass' I obtain a reference to it in my controller method as follows:



var myView = Ext.getCmp('myViewClass') || this.getView('MyViewClass').create();


This seems to work fine. If the view has already been created then Ext.getCmp() gives me the reference, otherwise I create it for the first time. This technique avoids the issue with trying to registering a component more than once with the controller. But is this the best way or is there a more accepted method? Just looking for some guidance. Thanks.

scottmartin
29 Jun 2012, 7:31 AM
I would recommend you not use id and getCmp() in your code.
Look at using itemId and container.down()/up() and Ext.ComponentQuery()

Scott.

redraid
29 Jun 2012, 8:16 AM
Use refs (http://docs.sencha.com/ext-js/4-1/#!/api/Ext.app.Controller-cfg-refs) controller config:

Ext.define("MyApp.controller.Foo", {
extend: "Ext.app.Controller",
refs: [
{
ref: 'list',
selector: 'grid' // view xtype (alias: 'widget.grid') or selector
}
],

myMethod: function () {
var me = this,
list = me.getList(); // get view
}
});

el_chief
29 Jun 2012, 9:43 AM
Don't use refs. They are a mistake. They don't allow for multiple instances of a view.

You should either use only event handlers and grab the component when the handler is called (it's usually the first argument, or a child of the view), or use Deft which is one controller instance per view instance.

sl5337
29 Jun 2012, 10:11 AM
I have found that refs are only helpful if you know that the component has already been instantiated by the time you call the generated "get" method. The "get" method generated by the ref does not instantiate the component being referenced. I guess I could pre-instantiate all of my views in the init() method of the controller but that seems like a waste since the user may not visit all of them.

I am curious about the suggestion to not use Ext.getCmp(). I have seen that suggestion before but I don't know the reasoning. Is that method going to be deprecated in a future release? I use it quite a lot in my code so if its not going to be around forever then I have a lot of refactoring to do. Thanks again for all of your suggestions.

filippo.ferrari
3 Dec 2012, 9:12 AM
+ 1

I haven't found yet a clear explanation how create a view with some controls (in a differet control class), ref correctly to my view parts (eg. form fields I need to control) and do it in the best way if I know that my app probably (with user interaction) need many instances of this view+controls.

ettavolt
4 Dec 2012, 4:12 AM
I do this way:

{ref:'importImage', selector:'v2d_float_importimage', xtype:'v2d_float_importimage', autoCreate:true},
{ref:'importImagePreview', selector:'v2d_float_importimage #image'},
{ref:'importImageSubmit', selector:'v2d_float_importimage #submit'},
First ref grabs existing view or creates, if no exists. Just make sure, that you call next refs only after first. 'v2d_float_importimage' is an xtype config option, that may be set when component is defined. Some people even add preprocessor to autogenerate it.
Ext.getCmp returns component by id, but you should not specify ids and let them to be autogenerated - this may come useful, if app will have several instances of that.
There is also an option 'forceCreate' that will return new instance each time method is called. The problem is to get ref to that view when handling events. Container.up('selector') maybe used.
About "Controller per View": I prefer 'stateless' design - believing that it reduces number of errors. :)