14

We use XTemplates - lots of XTemplates. They are great for displaying read-only content. But have you ever added (Ext JS) listeners to DOM created via a template? Would you care to share your preferred technique for creating these listeners?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Upperstage
  • 3,747
  • 8
  • 44
  • 67

4 Answers4

24

My preferred technique is using the analog of $.live function from jquery. F.i. let's assume you are going to use xtemplate for creating simple list like the following:

<ul class="nav">
    <li><a href="example.com">item1</a></li>
    <!-- ... -->
</ul>

To assign handler to the anchors you would do in jquery something like:

$('.nav a').live('click', function(){
    // do something on anchor click
});

The $.live function is great because it would work even if handler assignation would happen before list rendering. This fact is extremely important when you use xtemplate.

Fortunately there is analog in ExtJs - delegating events. Just look at the code:

Ext.getBody().on('click', function(event, target){
        // do something on anchor click
    }, null, {
        delegate: '.nav a'
    });

For more info take a look at docs for the Ext.Element.addListener method.

Molecular Man
  • 22,277
  • 3
  • 72
  • 89
  • WOW! Thanks for the response! (+1 for the reference to jQuery) – Upperstage Nov 10 '11 at 15:17
  • 2
    yes this function is great but it comes with jquery dependency which is another 200k javascript and the ext dom wrappers are much better and convenient to work with – user732456 Nov 11 '11 at 15:51
  • 3
    @user732456, what jquery dependency? Read carefuly my answer. In answer the **analog** of famous jquery function is described. ExtJs only is being used. – Molecular Man Nov 11 '11 at 16:01
  • sry didn't read it to the end and didn't figure it out that delegating events can do the trick. I'm voting for your solution. – user732456 Nov 15 '11 at 16:40
  • For those who want a simpler syntax, this is the same code, converted to a more jQuery-ish syntax: Ext.live = function (selector, event, handler) { Ext.getBody().on(event, handler, null, { delegate: selector }); }; To use: Ext.live('.deleteSymbol', 'click', function (event, target) {}); – Jerod Venema Aug 17 '12 at 15:42
  • That's why I love jQuery, and hate Ext JS. +1. However, it's better to use `on()` instead of `live()`. – Saeed Neamati Feb 09 '13 at 13:57
5

Shamelessly modified version of MolecularMan's concept:

Ext.live = function (selector, event, handler) {
    Ext.getBody().on(event, function(event, target){
        handler.apply(Ext.get(target), arguments);
    }, null, {
        delegate: selector
    });
};

Usage:

Ext.live('.myclass', 'click', function () {
    this.fadeOut();
});
Jerod Venema
  • 44,124
  • 5
  • 66
  • 109
3

The simplest approach we adopt here is the following:

// Function to be called on DOM event
var functionCallback = function () {
    console.log('hello');
}

// function to bind elements created via XTemplate and DOM events
function bind(Ext.Element element, String selector, Obj callback) {
    var els = element.query(selector);

    Ext.Array.each(els, function (item, index, allItems) {
        item.addEventListener('click', callback, false);
    });
}

And the usage:

var tpl = new Ext.XTemplate(...);
var data = [..]

var returnedEl = tpl.append(otherElem, data, true);
bind(returnedEl, 'div.my-css-class', functionCallback);
eduardosouza
  • 84
  • 1
  • 7
  • +1 for the response; thanks. I don't want the same handler called for each click event, but that is likely a minor point. The bigger problem is with the third parameter to tpl.append(); I am currently using HTML that is "pushed to" the DOM at some point the future. Do you think if I set this flag to true, Ext JS would render my template somewhere in the DOM (as a place holder)? – Upperstage Nov 10 '11 at 15:14
  • Pretty much what I wanted to do, but you should also add checking for whether or not `addEventListener` exists - IE8 and below uses `attachEvent`. – Mike Demenok May 06 '13 at 04:36
0

Well, you can use something like this:

  1. create id via Ext.id(), pass it to the template to some element
  2. then fetch that element using Ext.get()
  3. attach the listener to just found element
Sergey Stolyarov
  • 2,587
  • 3
  • 27
  • 40
  • Thanks for your response. I agree, but step 2 is missing some detail. For example, if I use the template to create HTML, then the element may not be rendered until sometime in the future. I was hoping for some magic that allowed me to create - or defer creation - of the listeners in the template. – Upperstage Nov 10 '11 at 13:21
  • I share the same technique. When I need to do I normally have afterRender method that must be called after template is rendered. – user732456 Nov 11 '11 at 15:48