PDA

View Full Version : How to reference component in controller when using autoEl to reference link



DocAhrens
31 Jan 2012, 11:10 AM
I have a button and a link in my View, and I was able to move the click handler for the button to the Controller, calling it by its id, but I was unable to figure out how to put the click handler for the component based link in the controller. What would be the syntax for referencing my link component from my controller? See my code below:
View

items: [
{
xtype: 'button',
id: 'scheduleSubmit',// event handling moved to controller
text: 'Submit'
},
{
xtype: 'component',
autoEl: {
tag: 'a',
href: '#delete'
},
html: 'Delete',
id: 'delete',
// want to move to Controller
listeners: {
el: {
click: function(ev){
ev.preventDefault();
console.log('type: ' + ev.type + ' | text: ' + ev.target.text);
}
}
}
}
]
Controller

Ext.define('MyCompany.controller.Dashboard', {
extend: 'Ext.app.Controller',
models: ['MyModel'],
stores: ['CompanyJsonStore'],
init: function() {
var me = this;
this.control({
'#scheduleSubmit': {click: this.scheduleSave}
});
},
scheduleSave: function(button){
console.log('button.type: ' + button.type +' | button.text: ' + button.text);
}
});

mitchellsimoens
31 Jan 2012, 11:47 AM
this.control cannot resolve elements, just components

skirtle
31 Jan 2012, 11:54 AM
The way I'd do this is to fire an event on the component (possibly called click) when the element click event fires.

You can move your existing logic into the controller by adding the click listener in an afterrender listener (rather than using the el syntax). However, it could be argued that relaying the click event from the element to the component belongs in the view rather than the controller anyway.

DocAhrens
1 Feb 2012, 9:57 AM
Thanks for the tip - I solved it by creating the following Link class:


Ext.define('MyCompany.link.Link', {
alias: 'widget.link',
alternateClassName: 'MyCompany.Link',
extend: 'Ext.Component',

hidden: false,

/**
* @cfg {Boolean} preventDefault, default is true
* set to false to allow typical link action when {@link #click} occurs.
*/
preventDefault: true,

/**
* @cfg {String} text, the text to place inside the link (innerHTML)
* may contain HTML
*/

/**
* @cfg {String} href, the URL to visit when the link is clicked or
* and what to show on hover in status bar or
* if preventDefault = true (default), just show in the status bar
*/

/**
* @cfg {String} tooltip
* The tooltip (string) for the link - using the browser built in tooltip
* for a link title attribute
*/

/**
* @cfg {Function} handler
* A function called when the link is clicked (can be used instead of click event).
* @cfg {Ext.link.Link} handler.link This link.
* @cfg {Ext.EventObject} handler.e The click event.
*/

/**
* @cfg {Number} tabIndex
* Set a DOM tabIndex for this link.
*/

// inherit docs
initComponent: function() {
var me = this;

if (me.text) {
me.html = me.text;
}

me.callParent();
/**
* @default config, sets href to '#' and a tag as the element.
*/
me.autoEl = {
tag: 'a',
href: (me.href ? me.href : '#')
};
if (me.tooltip) {
me.autoEl.title = me.tooltip;
}
if (me.tabIndex) {
me.autoEl.tabindex = me.tabIndex;
}

me.listeners = {
el: {
click: function(ev, el){
if (me.preventDefault){
ev.preventDefault();
}
me.fireEvent('click', me, ev);
if (me.handler){
me.handler(ev, el);
}
}
}
};
}
});
and calling it like so:


items: [
{
xtype: 'link',
text: 'Delete',
tabIndex: 3,
href: '#delete',
tooltip: 'Delete this item'
}
]
and then in the controller, I referenced it in the controller like so:


init: function() {
var me = this;
this.control({
'#delete': {
click: this.delete
}
});
},
deleteItem: function(link){
console.log('link.text: ' + link.text + ' | link.id: ' + link.id);
}

I'm definitely open to suggestion for improving this class (it is my first in ExtJs)...

skirtle
2 Feb 2012, 6:17 PM
I'd avoid calling that method 'delete' if I were you: it's a reserved word and it may not work in all browsers.

Personally I wouldn't pass the arguments to callParent. initComponent never takes any arguments so it's unnecessary.

It isn't clear to me why you copy xtype to a type property.

I don't really follow the check for setting preventDefault to true. It's already set to true by default, so the only way it could be false is if someone explicitly sets it to false. Do you really want to override them by setting it back to true?

Using a static id could be problematic too.

DocAhrens
2 Feb 2012, 7:01 PM
Thanks for the suggestions! I will make all those changes. Can you elaborate on your comment about the "static id"?