最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Howto bind a click event in a Backbone subview - Stack Overflow

programmeradmin1浏览0评论

I'm having problems understanding the event binding in a Backbone subview. My view is defined as follows:

TenantView = Backbone.View.extend({
  events: {
    "click": "setActive"
  },
  initialize: function() {
    this.parentEl = this.options.parentEl;
    return this.render();
  },
  template: new EJS({
    url: '/scripts/templates/tenant.ejs'
  }),
  render: function() {
    $(this.parentEl).children('ul').append(this.template.render(this.model));
    return this;
  },
  setActive: function(event) {
    return this.model.set('active', true);
  }
});

The template simply consists of an li containg an a. Done this way, clicks events on my view are not catched, my method setActive is never triggered.

When I extend my view by an el property like el: 'li' one of my (2) views acts properly and triggers the setActive function. The second view does not react at all. If I insepct the el property during the views initialization, the working view's el property points to the right li, the failing views el points to the first li that can be found in the page.

As one can see, I am totally lost when it es to the meaning of the el property.

Question is, how can I bind a click on view to this very views setActive function?

Can anyone enlighten me please?

Regards Felix

I'm having problems understanding the event binding in a Backbone subview. My view is defined as follows:

TenantView = Backbone.View.extend({
  events: {
    "click": "setActive"
  },
  initialize: function() {
    this.parentEl = this.options.parentEl;
    return this.render();
  },
  template: new EJS({
    url: '/scripts/templates/tenant.ejs'
  }),
  render: function() {
    $(this.parentEl).children('ul').append(this.template.render(this.model));
    return this;
  },
  setActive: function(event) {
    return this.model.set('active', true);
  }
});

The template simply consists of an li containg an a. Done this way, clicks events on my view are not catched, my method setActive is never triggered.

When I extend my view by an el property like el: 'li' one of my (2) views acts properly and triggers the setActive function. The second view does not react at all. If I insepct the el property during the views initialization, the working view's el property points to the right li, the failing views el points to the first li that can be found in the page.

As one can see, I am totally lost when it es to the meaning of the el property.

Question is, how can I bind a click on view to this very views setActive function?

Can anyone enlighten me please?

Regards Felix

Share Improve this question asked Nov 7, 2012 at 11:43 GeorgieFGeorgieF 2,7375 gold badges31 silver badges44 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 2

First thing, you may read documentation and this. Explanation about el is given there.

As TenantView has parentEl property, I'm assuming it is being rendered from some parent_view. I would suggest some approach like below and give it a try.

var ChildView = Backbone.View.extend({
  tagName : "li", // change it according to your needs

  events : {
    "click": "setActive"
  },

  initialize : function() {
    _.bindAll(this, "setActive");
    // code to initialize child_view
  },

  render : function() {
    // as I'm not familiar with the way you are using template, 
    // I've put simple call to render template, but it should render the
    // content to be kept inside "li" tag
    this.$el.html(this.template()); 

    return this;
  },

  setActive : function(event) {
    // code to be executed in event callback
  }
});


var ParentView = Backbone.View.extend({
  el : "#parent_view_el",

  initialize : function() {
    // parent view initialization code
  },

  render : function() {
    // a place from where ChildView is initialized
    // might be a loop through collection to initialize more than one child views
    // passing individual model to the view

    var child_view = new ChildView();

    this.$("ul").append(child_view.render().$el); // equivalent to this.$el.find("ul")

    return this;
  }
});

Hope it helps !!

You have kind of disabled backbones natural behavior by introducing your parentEl property and circumventing the creation of a view element. You basically never wire up the views `elz property to anything.

If I get your code right, the TenantView is a single list item in a list of tenants.

In your TenantView you can do this to leverage backbones built in events:

render: function() {
    this.setElement(this.template.render(this.model));
    $(this.parentEl).children('ul').append(this.$el);
    return this;
}

The setElement function will use the return value of you template function to wire up the views element and also setup the events for you. In the documentation it is suggested to use setElement in favor of just assigning something to the el property. There is also the nifty $el property which will contain a cached jQuery (or Zepto) object of your view's element.

To go more in the backbone way personally I would consider something like this:

var TenantView = Backbone.View.extend({
    // =========
    // = Setup =
    // =========

    events: {
        "click": "setActive"
    },

    template: new EJS({
        url: '/scripts/templates/tenant.ejs'
    }),

    // =============
    // = Lifecycle =
    // =============

    initialize: function(model, options) {
        this.render();
    },

    render: function() {
        var content = this.template.render(this.model);
        this.$el.html(content);
        return this;
    },

    // ==========
    // = Events =
    // ==========

    setActive: function(event) {
        return this.model.set('active', true);
    }

});


var TenantList = Backbone.View.extend({

    // =========
    // = Setup =
    // =========

    id: "tenantList",
    tagName: "ul",

    // =============
    // = Lifecycle =
    // =============

    initialize: function() {
        this.render();
    },

    render: function() {
        if (this.collection.length > 0) {
            this.renderChildren();
        }
    },

    renderChildren: function() {
        var that = this;

        this.collection.each(function(tenant) {
            that.$el.append(new TenantView(tenant).$el);
        });
    }
});
发布评论

评论列表(0)

  1. 暂无评论