Monday, April 23, 2012
Thursday, April 5, 2012
This is a cross post from: Rally Engineering Blog
Sometimes I run across a task where I need to attach event listeners to many different dom elements of the same type. I am usually tempted to do something similar to the code below.
Ext.each(Ext.query('a', parentNode), function(el) { el.on('click', doSomethingAwesome); });
This is ExtJs's way to loop through each dom element matching the passed css selector and attach an event listener to it. I'm lazy and it's less code than the correct implementation, which would be to add a listener to the parent element and filter for the correct target element inside the handler function. The disadvantages to the lazy method are that multiple listeners are created, all of which have some amount of overhead attached, and that listeners need to be removed and/or reattached whenever the innerHTML of the parent element changes.
An ExtJs specific example of when the 'lazy' method doesn't work is when event listeners need to be attached to elements created by a renderer inside of a GridPanel cell. The GridPanel does not expose any row or cell render events, so there is no reliable way to add event listeners to dom elements located inside cells.
Fortunately ExtJs's Element.on method has a helpful 'delegate' option that does all of this for you automatically. Use ExtJs's Element.on method to attach a listener to the parent dom element and specify a css selector for the 'delegate' option to filter out events whose target node does not match the passed css selector.
var parentEl = Ext.fly(parentNode); parentEl.on('click', function(event, target, options) { console.log('the "target" argument is the anchor element that is a child of parentNode'); }, this, { delegate: 'a' });