PDA

View Full Version : Can't get event to fire from toolbar.



wceuppens
8 Jul 2010, 2:54 AM
I've been trying to fire and event from a toolbar, but I cannot get it to work. It does work when I fire the event from a button. I don't see what I'm doing wrong...:s
Any help would be appreciated.

This my testcode:

Ext.ns("TPL.listpanel");
TPL.listpanel.algemeen_gebruikers = Ext.extend(Ext.Panel, {
id : 'algemeen_gebruikers.card',
tbar: [{
text : 'Add User top',
handler : function(){this.fireEvent('algemeen_gebruikers_createUser');} // does NOT work
}] ,
initComponent : function() {
Ext.apply(this, {
items: [new Ext.Button({
id: 'theButton',
text: 'Test',
listeners: {
'click': {
scope: this,
fn: function(){this.fireEvent('algemeen_gebruikers_createUser');} // WORKS
}
}
})],
bbar: [{
text : 'Add User',
handler : function(){this.fireEvent('algemeen_gebruikers_createUser');} // does NOT work
}]
});
TPL.listpanel.algemeen_gebruikers.superclass.initComponent.call(this, arguments);
this.addEvents({algemeen_gebruikers_createUser : true});
}
});
Ext.reg('TPL.listpanel.algemeen_gebruikers', TPL.listpanel.algemeen_gebruikers);And here do I capture the event:

...
items :
[
{xtype: 'TPL.listpanel.algemeen_gebruikers',
listeners : {
algemeen_gebruikers_createUser : function (){alert('algemeen_gebruikers_createUser fired.');}
}
}
]
...

Animal
8 Jul 2010, 3:00 AM
Obviously "this" isn't what you are hoping it will be.

When it works, you are firing the event from the TPL.listpanel.algemeen_gebruikers because when you set up the items object INSIDE initComponent, "this" is the TPL.listpanel.algemeen_gebruikers instance, and you assign a scope to the click listener.

But in the other one, "this" will be the button.

You can go up the ownerCt to the TPL.listpanel.algemeen_gebruikers and fire from that if you like.

wceuppens
9 Jul 2010, 3:15 AM
Thanks a lot Animal. Your answer put me in the right direction.

The following code works:

TPL.listpanel.algemeen_gebruikers = Ext.extend(Ext.Panel, {
id : 'algemeen_gebruikers.card',
tbar: [{
text : 'Add User top',
// handler : function(){this.fireEvent('algemeen_gebruikers_createUser');} // does NOT work
handler : function(){Ext.getCmp('algemeen_gebruikers.card').fireEvent('algemeen_gebruikers_createUser');} // WORKS 1
}],
bbar: [{
text : 'Add User bottom',
// handler : function(){this.fireEvent('algemeen_gebruikers_createUser');} // does NOT work
handler : function(){this.ownerCt.ownerCt.fireEvent('algemeen_gebruikers_createUser');} // WORKS 2
}],
....
});

Animal
9 Jul 2010, 3:33 AM
That's one way.

wceuppens
9 Jul 2010, 3:47 AM
Mind telling what the other(s) are?

Animal
9 Jul 2010, 4:03 AM
You could use



this.findParent("panel").fireEvent...


Which would work if you were writing a real reusable class.

Or you could instantiate the Toolbar inside initComponent, where "this" is the Panel, put it into "this.tbar" BEFORE calling the superclass initComponent.

Again, if you were writing a reusable class, this would work.

wceuppens
9 Jul 2010, 12:42 PM
You could use


this.findParent("panel").fireEvent...
Which would work if you were writing a real reusable class.
I'm not sure what the "panel" stands for, not what you mean by a "real reusable class". What I do know is that I tried to minimise the submitted code to the bare essentials for clarity.
Not sure you'd agree, but I think that the 'getCmp' option provides more clarity than 'ownerCt' or 'getParent'.


Or you could instantiate the Toolbar inside initComponent, where "this" is the Panel, put it into "this.tbar" BEFORE calling the superclass initComponent.
I missed something - again -, but I thought that's what I did with the bbar in my initial post.

Again, if you were writing a reusable class, this would work.
Although you've been very helpfull, somehow your answers always incite more questions.
What's a real reusable class? The cut-down code I posted produces exactly the same dom and html as my "more resusable" code...
As far as I can see (thanks to your input) in the dom, a toolbar button is always 2 levels down from the originating panel. And a context menu is 1 level down from the originatin panel.
I'm new to OO and web stuff, having a procedural background, so I might still not get the in's and out's of OO.
But that's also why I'm asking these - perhaps silly for an OO/web expert - questions....

Animal
9 Jul 2010, 12:53 PM
Well, you're not creating a class which you intend to instantiate many instances of are you? Obviously not because you have that hardcoded ID in there.

I meant findParentByType. You can see what I meant by reading the docs for it.

wceuppens
10 Jul 2010, 3:32 AM
Initially, I "hardcoded" the ID to be able to find the class in the DOM.
But now I think that it improves the readability of my code to use getCmp("classID").

For the sake of the argument: Even a piece of reusable code needs a name. If I give the ID the same name as my class and xtype, it is no more hardcoded than those 2, isn't it?

Animal
10 Jul 2010, 4:25 AM
IDs must be unique, so no, if you ever instantiated more than one instance of that class, it would not work. You would have a bug.

wceuppens
10 Jul 2010, 5:00 AM
Exactly, just like xtype names, class names, file names...

Animal
10 Jul 2010, 5:29 AM
Not sure if you are getting it. IDs must be unique. Every instance you create of one type must have a DIFFERENT, UNIQUE id.

wceuppens
10 Jul 2010, 1:12 PM
Hey, don't you guys ever sleep?

But anyhow, I think I DO get it... I'm just wondering if we're talking the same language here:
Let me repeat:
an ID has to be unique, an xtype has to be unique, a class has to be unique, a file has to be unique.
So why should an ID be different from any of these other types ??

Animal
10 Jul 2010, 2:09 PM
So you think



Ext.ns("TPL.listpanel");
TPL.listpanel.algemeen_gebruikers = Ext.extend(Ext.Panel, {
id : 'algemeen_gebruikers.card',
tbar: [{
text : 'Add User top',
handler : function(){this.fireEvent('algemeen_gebruikers_createUser');} // does NOT work
}] ,
initComponent : function() {
Ext.apply(this, {
items: [new Ext.Button({
id: 'theButton',
text: 'Test',
listeners: {
'click': {
scope: this,
fn: function(){this.fireEvent('algemeen_gebruikers_createUser');} // WORKS
}
}
})],
bbar: [{
text : 'Add User',
handler : function(){this.fireEvent('algemeen_gebruikers_createUser');} // does NOT work
}]
});
TPL.listpanel.algemeen_gebruikers.superclass.initComponent.call(this, arguments);
this.addEvents({algemeen_gebruikers_createUser : true});
}
});
Ext.reg('TPL.listpanel.algemeen_gebruikers', TPL.listpanel.algemeen_gebruikers);


then



var p1 = new TPL.listpanel.algemeen_gebruikers();
var p2 = new TPL.listpanel.algemeen_gebruikers();


will work?

wceuppens
11 Jul 2010, 12:16 AM
Just tried and yes, it works. Perhaps I'm doing something wrong?

Hold it... just tried again, and indeed, the event fires 2x !!

Animal
11 Jul 2010, 1:17 AM
The ID!!!!

Every instance must have a unique ID.

wceuppens
11 Jul 2010, 3:14 AM
Ok, let's get the ID out:

TPL.listpanel.algemeen_gebruikers = Ext.extend(TPL.listpanel.BaseCls, {
...
buildTbar : function() {
return [{
text : centre1.users.lang.update,
iconCls : 'icon-updateUser',
handler : this.onUpdateUser
}];
},
...
doCtxMenu : function(view, idx, node, e) {
e.stopEvent();
if (!view.ctxMenu) {
view.ctxMenu = new Ext.menu.Menu({
items: [{
text : centre1.users.lang.update,
iconCls : 'icon-updateUser',
handler : this.ownerCt.onUpdateUser
}]
});
}
},
...
onUpdateUser: function() {
//// var me = Ext.getCmp('algemeen_gebruikers.card');
var me = this.findParentByType('TPL.listpanel.algemeen_gebruikers');
me.fireEvent('algemeen_gebruikers_createUser', 'Update');
},
...
});
Ext.reg('TPL.listpanel.algemeen_gebruikers', TPL.listpanel.algemeen_gebruikers);This works fine if I press the button on my toolbar. But if I use the button on my contextmenu, it no longer works. (me is null - because Extjs generates the contextmenu code outside of the panel).

And I instantiate my class twice:

...
xtype: 'TPL.listpanel.algemeen_gebruikers',
id:'test1',
...
...
xtype: 'TPL.listpanel.algemeen_gebruikers',
id:'test2',
...Somewhere else in the code, I put my listener:

...
Ext.getCmp("test").on('algemeen_gebruikers_createUser', function(action){
console.log('algemeen_gebruikers_CreateUser captured. Action: ' + action);
});
...
The event still fires twice.

Animal
11 Jul 2010, 3:19 AM
What's all this "me="?

Your buildTbar should be happening in the scope of the Panel. So scope the button handler right there!

Animal
11 Jul 2010, 3:21 AM
And just execute doCtxMenu in the scope of the Panel, and you'll have "this" available to scope the handler there too!

wceuppens
11 Jul 2010, 4:41 AM
Thank's a lot Animal, scope definition did the trick. I was wondering what this scope thing was all about. Guess I've learned it now.

There's only problem remaining now. I defined 2 instances of my panel with 2 different unique id's in my application. I put my listener on 1 of the id's. When I fire the event, it gets captured twice, once for each instance of my panel...