A lot of Sencha Touch examples I found online, don’t really focus on proper view encapsulation. So the Controller listens to every single button’s event even if the button is deep nested inside a view. In other words the internals of the view leak through which is never a good thing.
I found one good tutorial that encourages you to create meaningful views that listen to local events and raise meaningful business events etc.
http://miamicoder.com/2012/how-to-create-a-sencha-touch-2-app-part-2/
However, one thing that I couldn’t really figure out so far is how to best cache nested component instances. Consider this example:
Ext.define("NotesApp.view.NotesListContainer", {
extend: "Ext.Container",
alias: "widget.noteslistcontainer",
initialize: function () {
this.callParent(arguments);
var newButton = {
xtype: "button",
text: 'New',
ui: 'action',
handler: this.onNewButtonTap,
scope: this
};
var topToolbar = {
xtype: "toolbar",
title: 'My Notes',
docked: "top",
items: [
{ xtype: 'spacer' },
newButton
]
};
this.add([topToolbar]);
},
onNewButtonTap: function () {
console.log("newNoteCommand");
this.fireEvent("newNoteCommand", this);
},
config: {
layout: {
type: 'fit'
}
}
});
Let’s say we want to add a method setSpecialUIState to our NotesListContainer. When it’s called we want to do something with the newButton (e.g. hide it). How would I gain access to the newButton instance without misusing Ext.getComp() for that? Can I set it as an instance variable? How is the canonical way?
UPDATE
I just tried this as Nikolaj Borisik suggested.
this._newButton = this.add([{
xtype: "button",
text: 'New',
ui: 'action',
handler: this.onNewButtonTap,
scope: this
}];
That works like a charm. I just don’t know if its idiomatic to do so or if there are any downsides I might be missing. Otherwise I would highly recommend to do this. Sencha aside, it’s much better to compose meaningful views that abstract away coherent UI parts. That’s much better than leak every single button through to the controller and fiddle directly with them.
So I wonder if there are any downsides of this approach?
After I spent more time with Sencha I figured out that I had a wrong assumption about
Ext.getCmp(). I thought this would first query the DOM to find a matching ID and then would try to get the component instance which is bound to it. However, that’s not what it does. In fact, it doesn’t query the DOM at all. It just queries a facility called the ComponentManager which holds references to all components beeing used.So, it’s not that dirty to use it. However, we still can do better.
Every container supports the methods
child(selector)anddown(selector)to query for sub components. While at first glance this seems to query the DOM, again that does only query the ComponentManager. It uses the container at the starting point and queries down it’s inner items. The difference between both is thatchild(selector)only queries the very first sub level whereasdown(selector)queries all sub level.I guess it’s ok to use those to get a handle on those sub components. However, if there are still performance concerns because of repetitive calls to those method’s I would recommend to cache those after the very first retrieval.