jQuery's append
is not a simple text concatenation. If you give a string, it will convert that string to a set of DOM nodes and insert those nodes. If you give append
a string that contains invalid HTML, then the browser will do its best to fix your HTML before it adds any nodes to the DOM.
You're adding this "HTML":
<table class="table table-bordered table-striped" id="example-default">
<thead>
...
</thead>
<tbody>
but that's not valid HTML so the browser will probably convert it to this:
<table class="table table-bordered table-striped" id="example-default">
<thead>
...
</thead>
<tbody>
</tbody>
</table>
before it hits the page. Then you try to add a more invalid stuff through your AbsenceListItemView
(i.e. <tr>
s that aren't inside <thead>
, <tbody>
, or <table>
) so the browser will try to make sense of that. Finally, you try to append:
</tbody>
</table>
which the browser will probably convert to:
<table>
<tbody>
</tbody>
</table>
and you end up with an incomprehensible mess.
You need to treat your <table>
as a single unit. Combine your tableEnd
and tableStart
into something valid:
<table class="table table-bordered table-striped" id="example-default">
<thead>
...
</thead>
<tbody>
</tbody>
</table>
and then append the AbsenceListItemView
s to the <tbody>
in there:
render: function (eventName) {
this.$el.html(this.template()); // This has both pieces.
this.collection.each(function(model) {
this.$('tbody').append(new AbsenceListItemView({model: model}).render().el);
}, this);
return this;
}
Note a few other changes:
- Your
model
was actually a collection so you should usethis.collection
instead ofthis.model
inside the view and saynew AbsenceListView({ collection: ... })
when instantiating the view. - Use
this.$el
inside the view instead of creating a new jQuery wrapped version all the time by calling$(this.el)
over and over again. Backbone createsthis.$el
for you so you should use it. - Use
this.$()
to find this within your view'sel
, this is a shortcut forthis.$el.find(...)
that Backbone sets up for you. - Backbone mixes various Underscore methods into collections so you can say
this.collection.each(...)
instead of mucking around with the collection'smodels
property with things like_.each(this.collection.models, ...)
.