0
votes

tl;dr
I rendered a collection of items into Backbone Views, pass them on to what will be their parent view in an array, and attempt to display them from within an underscore template. Instead of the html, I get [object HtmlDivElement].

Full description

I have a sort of view generator such that:

  1. I receive data from my backend,
  2. I send it to the view generator line by line
  3. I receive back the rendered view

The point of the process is to receive generically handle responses form different sources, where the data from each source needs to be parsed differently. I know and have defined the parsing methods for each set depending on the request.

Relevant code:

var ResultGroupView = Backbone.View.extend({
    tagName: 'tbody',
    initialize: function (options) {
        var self = this;
        self.collection = new ResultGroupModel();
        self.parent = options.parent;
        self.collection.bind('add', self.renderItem, self);
        _.bindAll(self, 'render', 'renderItem', 'addItem');
        [...]
    }
    template: _.template(resultGroupTemplate),
    addItem: function (item) {
        var self = this;
        var values = [];
        //a new item is being added to the collection. get the details on how to parse it
        _(self.parent.getColumns()).each(function (v) {
            values.push(((!!v.parser) ? v.parser.call(self, item[v.Id]) : item[v.Id]));
        });

        //due to the binding above, this next line triggers the renderItem function
        self.collection.add(new ResultItemModel({ Id: item.Id, Values: values }));
    },
    renderItem: function (item) {
        var self = this;
        //ResultItemView has tagName: 'tr'
        var itemView = new ResultItemView({
            model: item,
            parent: self
        });
        self.$el.append(itemView.render().el);
    },
    [...]
});

Each type of data has a different parser function defined. Specifically, where we have v.parser.call(self, item[v.Id]), this is the call to the view generator. The parser simply creates a backbone View and returns the rendered object.

The ResultItemView mentioned above simply renders its view over an underscore template, which is:

<td><input type="checkbox" value="<%=Id%>" /></td>
<% _.each(Values, function(Val) { %>
    <td>
        <%=Val%>
    </td>
<% }); %>

What ends up being displayed where it says <%=Val%> is [object HtmlImgElement], [object HtmlDivElement] and so on.

Apparently, there was some basic mistake in my understanding of how I was passing the information between the views and into the template... but I can't figure out what needs to be changed.

I feel like using something along the lines of node.outerHTML || new XMLSerializer().serializeToString(node); (as described here) is rather hacky... Is there a better way around this?

1
"The parser simply creates a backbone View and returns the rendered object." - okay.. so I understand that parser creates a backbone view. But what do you mean by "the rendered object."..?!! If parser creates a backbone view, why are you again creating a model with parsed values and another view, ResultItemView for that model..? What was the purpose of backbone view that was created by parser..?!! and what does values look like..? - T J
@TJ I was unclear... "the rendered object" is a sub-view's element. I say rendered object because while it is a bunch of html elements, it's not yet in the DOM and upon trying to add it, I get [object DivHtmlElement] or some such. I actually have 3 layers here - the ResultGroupView being the top layer, ResultItemView being the middle layer, and the "parsed view" being the bottom layer. ResultGroupView contains a collection of ResultItemModel, which in turn contains an array of the "parsed view"s. Each new ResultItemModel is then automatically rendered (bind('add',[...])) - Guy Passy
okay, so you've a collection ResultGroup and a ResultGroupView, which renders ResultItemView for each ResultItem in ResultGroup . I got that much, but then i got lost - "ResultItemModel, which in turn contains an array of the "parsed view"s" why are you storing lots of view's in a model..? and if values is really an array of backbone view's , why are you trying to print properties of a view object using underscore..?!! those views should have a render method, which renders it's data, and you should append them to DOM. - T J
"ResultItemView mentioned above simply renders its view" - what do you mean by its view..? ResultItemView is the view itself. I don't understand what you expect to see when you try to pass an array of views and try to print them as html template. That fact that you're trying to print a nested javascript object like that using underscore template doesn't make sense... I believe you're seeing the output of object.toString(). What do you expect to see instead..?! - T J
@TJ well, I suppose the actual answer to why I'm storing views in a model is simply flawed design on my part... As you say, I am in fact seeing the object.toString() output. Guess I'm heading toward a redesign of these views. thanks :) - Guy Passy

1 Answers

0
votes

I suspect you're over-thinking this. Is it as simple as, in your renderItem method, changing ...

self.$el.append(itemView.render().el);

... to ...

self.$el.append(itemView.render().$el.html());

... ?