0
votes

I've finally got my Rails Todo List app to display the Todos using Backbone's renderer. I've a small issue though. In the addOne function, I've used view.render() instead of view.render().el, what was taught in the tutorial.

The view doesn't render with view.render.el(). Any explanation?

$(function(){
Todos = new TodoList.Collections.Todos;
TodoList.Views.TodoView = Backbone.View.extend({
    tagName: "li",
    events: {},
    initialize: function(){},
    template: _.template('<li> <%= task %></li>'),
    render: function(){
        var todo = this.model.toJSON();
        return this.template(todo);
    }
});

TodoView = TodoList.Views.TodoView;

TodoList.Views.AppView = Backbone.View.extend({
    el: $("#todo_app"),
    events: {
        "submit form#new_todo": "createTodo"
    },
    initialize: function(){
        _.bindAll(this, 'addOne', 'addAll','render');
        Todos.bind("add", this.addOne);
        Todos.bind("reset", this.addAll);
        Todos.bind("all", this.render);
        Todos.fetch();
    },

    addOne: function(todo){
        var view = new TodoView({model: todo});
        this.$("#todo_list").append(view.render());
    },

    addAll: function(){
        Todos.each(this.addOne);
    },

    newAttributes: function(event){
        var new_todo_form = $(event.currentTarget).serializeObject();
        return {
            dog: {
                name: new_todo_form["todo[task]"],
                age: new_todo_form["todo[done]"]
            }
        };
    },

    createTodo: function (e){
        e.preventDefault();
        var params = this.newAttributes(e);
        Dogs.create(params);
    }
});
});
2

2 Answers

2
votes

If you were to console.log each of the components of the call the output would be similar to the following:

view // your view object which contains methods and properties - BackboneView
render  // a method of the view object - a function
el // a property of the view object - an HTMLElement

So, you can't call el because it's only a property, in fact it's an HTMLElement object. In your code you are returning html. If you were to chain the the calls via view.render().el you would have to return the instance using the this keyword. When you return an instance you get access to all of the instance's properties and methods again in one line (chainablility). So, when you return html you can't chain off the view object, which is why, in the demo, they return this.

render: function () {
    this.$el.html( this.template( this.model.toJSON() ));
    return this; // return the instance
}

You shouldn't return the html of the view anyway. You always want to access Backbone's html via the el or $el properties.

1
votes

el isn't a function, but rather the HTML that would constitute the view. Calling render() normally generates the HTML and stores it in the el property. By convention this method should return this allowing you to reference the object directly (and for chaining).

So, view.render().el will render the element and return the HTML suitable for appending to the DOM.