Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling a jQuery plugin in a Backbone render method

I have a render method in Backbone that goes basically like this:

render: function () {
  $.tmpl(this.template, attrs).appendTo(this.el);
  return this;
},

which is called from a router action:

action: function () {
  $('#container').empty();
  $('#container').append(myView.render().el);
},

Now, I want to apply a plugin on label elements inside this view. My first thought was to call the plugin inside render:

render: function () {
  $.tmpl(this.template, attrs).appendTo(this.el);
  this.$('label').inFieldLabels();
  return this;
},

but this doesn't work (I'm assuming this is because the element hasn't been added to the DOM yet). It does work if I call the plugin in the router action though:

action: function () {
  $('#container').empty();
  $('#container').append(myView.render().el);
  myView.$('label').inFieldLabels();
},

I'd rather not do this, because the plugin is part of the view, not the router, so it doesn't make sense to be calling it inside the action. Is there a better way to do this?

like image 201
Skilldrick Avatar asked Aug 18 '11 13:08

Skilldrick


3 Answers

Beter do it this way:

action: function () {
    var container = $('#container');

    container.empty();
    myView.render(container);
},

render: function (container) {
    $(this.el)
        .append($.tmpl(this.template, attrs))
        .appendTo(container);
    $('label', this.el).inFieldLabels();
    return this;
},
like image 125
ant_Ti Avatar answered Oct 18 '22 17:10

ant_Ti


I ran into a similar issue setting up the jQuery Tools Tooltip plugin. But I had a much different approach that works well: triggering a custom event on the view. As far as I know, there is no 'inserted into dom' event fired built into Backbone, so I just did it myself. I don't use a Router but the modified code above would look something like this:

// In the router:
action: function () {
    var container = $('#container');

    container.append(myView.render().el));
    myView.trigger('rendered');
},

// In the view:
initialize: function() {
    this.bind('rendered', this.afterRender, this);
},
render: function (container) {
    $(this.el).append($.tmpl(this.template, attrs))
    return this;
},
afterRender: function() {
    $('label', this.el).inFieldLabels();
}

I suppose the advantage is that the view stays ignorant of its container. The disadvantage is that it's like an extra line or two of code. But if you need to setup a lot of plugins or do more stuff that requires the element to be in the DOM, it will work well (and it keeps logic separated).

I actually like @Skilldrick's method of passing the container to the view, but I still feel as if it makes sense to have the parent view be responsible for inserting the children. I'm new to Backbone so please feel free to comment.

like image 29
Matt De Leon Avatar answered Oct 18 '22 16:10

Matt De Leon


I was able to get this to work for my jQuery plugin only by specifying the context for jQuery in the render function:

    render: function () {
    $(this.el).html(this.template(this.model.toJSON()));
    $('#email1dropdown', this.el).dropdownify();

    return this;
},
like image 2
Todd Gardner Avatar answered Oct 18 '22 17:10

Todd Gardner