Dimich
Dimich

Reputation: 53

Backbone event doesn't fire with Handlebars template

I have this code:

PageView.js

var PageView = Backbone.View.extend({
    events: {
         'click .unpublish': 'unpublish'
    },

    tagName: 'tr',
    className: 'pageedit',

    template: Handlebars.compile( PageViewTemplate ),

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

    unpublish: function() {
        alert('hi');
    }
});

PagesView.js

PagesView = Backbone.View.extend({

     tagName: 'tbody',

     initialize: function() {
         this.collection.on('reset', this.render, this);
         this.render();
     },

     template: Handlebars.compile(PagesTemplate),

     render: function() {
         var countPages = this.collection.at(0).get('count');

         _.each(this.collection.at(0).get('pages'), function(model) {
              pageView = new PageView({ model: model });
              this.$el.append( pageView.render().el );
         }, this);

         $('.main').html( this.template({ pages: this.$el.html() }) );

         this.delegateEvents(this.events);

         return this;
     },
});

Page.hbs

<td class="pageId">
    {{ id }}
</td>
<td class="pagename">
    <a href="/pages/{{ alias }}">{{ pagename }}</a>
</td>
<td class="catname">{{ catname }}</td>
<td class="author">{{ author }}</td>
<td>{{ date }}</td>
<td>
    {{#if status}}
        <a href="#" class="unpublish">
            <img src='../{{ siteURL }}assets/img/admin/published.png'>
        </a>
    {{else}}
        <a href="#" class="publish">
            <img src='../{{ siteURL }}assets/img/admin/not-published.png'>
        </a>
    {{/if}}
</td>
<td>
    <a href="#" class="intrash">
        <img src='../{{ siteURL }}assets/img/admin/delete.png'>
    </a>
</td>

Pages.hbs

<table class="table table-bordered table-striped">
    <thead>
        <tr>
            <th>ID</th>
            <th>Name</th>
            <th>Catalog</th>
            <th>Author</th>
            <th>Date</th>
            <th>Status</th>
            <th>Intrash</th>
        </tr>
    </thead>
    <tbody>
        {{{pages}}}
    </tbody>
</table>

Create all instances in router.js:

var pages = new Pages();
pages.fetch().done(function() {
    new PagesView({ collection: pages});
});

Event in PageView don't fired if I click .unpublish link. All Views renders good, but events not working :( Can help me?

Upvotes: 1

Views: 1255

Answers (1)

mu is too short
mu is too short

Reputation: 434845

I think your problem is right here:

$('.main').html( this.template({ pages: this.$el.html() }) );

As soon as you say this.$el.html(), you've lost your events. Backbone binds a delegate (or its equivalent on) to the view's el for event handling so the event handling is bound to a DOM node object. When you say this.$el.html(), you've converted everything to a string and that string goes into the DOM; but the events are bound to the DOM element object not the string. The result is that everything looks right but no events fire.

Your Pages.hbs should look more like this:

<table class="table table-bordered table-striped">
    <thead>
        <tr>
            <th>ID</th>
            <th>Name</th>
            <th>Catalog</th>
            <th>Author</th>
            <th>Date</th>
            <th>Status</th>
            <th>Intrash</th>
        </tr>
    </thead>
</table>

And then you should do something like this to get everything on the page:

// Add the basic <table> HTML.
$('.main').html(this.template());
// Append the <tbody> DOM node which has event handling attached to it.
$('.main').find('table.table').append(this.$el);

Upvotes: 1

Related Questions