PDA

View Full Version : Add listeners to preconfigured class



michiel
5 Jul 2010, 12:15 AM
Hi guys,

in my application I make extensive use of preconfigured classes, as suggested by Saki on his blog. This works absolutely great and saves me a lot of time. One thing I recently came across is how to add a custom listener, while preserving the default ones. Consider the following preconfigured class:



var MyTree = function (config) {

var defaults = {
border: false,
enableDD: true,
dataUrl: 'index.php',
root: {
nodeType: 'async',
text: 'root',
id: 'root',
draggable: false
},
listeners: {
// expand tree node upon render
render: function () {
this.getRootNode().expand();
}
}
}

// create config object
var cfg = Ext.apply({}, config, defaults);

// instantiate
var cmp = new Ext.tree.TreePanel(cfg);

return cmp

}


Now I'd for example like to add an onclick listener to a specific tree, so that would become something like this:




var ClickMyTree = function(config) {

config.listeners = {
click: function () {
alert('clicked');
}
}
return MyTree(config)

}


However, this (obviously) overwrites the existing listeners (in this case 'render'). So my question is how to add a listener, while keeping the existing ones? A hacky workaround I'm using now, is to copy-paste the existing listeners into the new function, but that kind of kills the philosophy of preconfigured classes.

I hope I was clear enough and that someone knows a solution to this problem!

Thanks, Michiel

Animal
5 Jul 2010, 12:20 AM
You'll have to apply passed in listeners to the listeners object in the defaults in a separate statement.

michiel
5 Jul 2010, 12:39 AM
Awesome! That does the trick .. and now that you said it, it also makes a lot of sense!

For those with similar problems, I've added 1 single line of code to make this work:



// create listeners config object
if(config.listeners) config.listeners = Ext.apply({}, config.listeners, defaults.listeners);

// create config object
var cfg = Ext.apply({}, config, defaults);

// instantiate
var cmp = new Ext.tree.TreePanel(cfg);

return cmp

Animal
5 Jul 2010, 12:51 AM
You don't want the "if" there do you?

You need to always set config.listeners. Even if they don't pass any in. Otherwise your defaults won't get set if they don't pass any in.

michiel
5 Jul 2010, 12:56 AM
Are you sure? Since the listeners are already set in the default, it only makes sense to merge the default config if any different listeners are passed in? Otherwise, they already exist the default config



var defaults = {
border: false,
enableDD: true,
dataUrl: 'index.php',
root: {
nodeType: 'async',
text: 'root',
id: 'root',
draggable: false
},
listeners: {
// expand tree node upon render
render: function () {
this.getRootNode().expand();
}
}
}



It seems to be working that way here, but please correct me again if I'm totally missing something here .. Thanks! Michiel

Animal
5 Jul 2010, 12:57 AM
Your code only apply the default.listeners into config.listeners if config.listeners is present!

Animal
5 Jul 2010, 12:59 AM
But if you are writing a class, then you should not be using listeners to add subclass functionality anyway.

http://www.sencha.com/learn/Tutorial:Creating_new_UI_controls

michiel
5 Jul 2010, 1:00 AM
True .. but then after the config is merged with the defaults again, isn't it? Or is that bad practice?



// create config object
var cfg = Ext.apply({}, config, defaults);

michiel
5 Jul 2010, 1:06 AM
But if you are writing a class, then you should not be using listeners to add subclass functionality anyway.

http://www.sencha.com/learn/Tutorial:Creating_new_UI_controls

Not sure if I'm writing a Class as such .. basically what I'm doing is this:

I have a basic tree configuration that is used for most modules in my CMS. But for some modules the tree has to act slighlty different (e.g a different click action, not allow to drop certain nodes somewhere etc.). For those cases I want to use my basic tree configuration, while adding some of these extra's. That's all basically.

Animal
5 Jul 2010, 1:10 AM
You're right, it's not a new class. It's a factory function which is in fact the right way to do what you are doing: churn out configured instances of a class.

OK, I see, defaults.listeners gets applied in the second stage. You've got it covered.

Animal
5 Jul 2010, 1:11 AM
On a point of style, do not capitalize functions, only class constructors.

name your function, getNewTree or something descriptive.

michiel
5 Jul 2010, 1:14 AM
Ok! Thanks for the help and suggestions. Will definitely take it into account. Always good to hear that I'm doing it 'the right way' :)