0

I can't seem to get the children view templates to render. They are showing up in console log, and they are showing up the right amount of times, but I can't get them to render in the browser.

The goals are the parents and the steps are the children.

CODE BITS:

models:

$(function() {
    window.Goal = Backbone.Model.extend({
        defaults: {
        description: null
        },
        initialize: function() {
            this.steps = new Steps();
            this.steps.fetch({ reset: true });
            this.stepsAll = new StepsViewForGoals({ collection:this.steps });
            $('.all-steps').append(this.stepsAll.render().el);
        }
    });
    window.Goals = Backbone.Collection.extend({
        model: Goal,
        url: '/api/goals/'
    });
    window.goals = new Goals();
});

goals views:

$(function() {
    window.GoalView = Backbone.View.extend({
        className: 'list-item',
        template: _.template($('#goal-item-template').html()),
        initialize: function() {
            _.bindAll(this, 'render');
            this.model.bind('change', this.render);
        },
        render: function() {
            this.$el.html(this.template(this.model.toJSON()));
            return this;
        }
    });
    window.GoalsView = Backbone.View.extend({
        el: '#app',
        template: _.template($('#goals-list-template').html()),
        initialize: function () {
            _.bindAll(this, 'render', 'addGoal');
            this.collection.bind('reset', this.render);
            this.collection.bind('change', this.render);
            this.collection.bind('add', this.render);
        },
        render: function() {
            this.$el.html(this.template());
            this.collection.each(function(goal) {
                var view = new GoalView({ model:goal });
                $('#goals').append(view.render().el);
            });
            return this;
        }
    });
});

step views

$(function() {
    window.StepView = Backbone.View.extend({
        className: 'list-item',
        template: _.template($('#step-item-template').html()),
        initialize: function () {
            _.bindAll(this, 'render');
            this.model.bind('change', this.render);
        },
        render: function() {
            this.$el.html(this.template(this.model.toJSON()));
            console.log('Individual step');
            return this;
        }
    });
    window.StepsViewForGoals = Backbone.View.extend({
        el: '.all-steps',
        template: _.template($('#step-list-template').html()),
        initialize: function () {
            _.bindAll(this, 'render');
            this.collection.bind('reset', this.render);
            this.collection.bind('change', this.render);
        },
        render: function() {
            this.$el.html(this.template());
            console.log(this.collection.toJSON());
            this.collection.each(function(step) {
                var view = new StepView({ model:step });
                $('.all-steps-list').append(view.render().el);
            });
            console.log('Steps View');
            return this;
        }
    });
});

Parent model template:

{% verbatim %}

    <script id="goal-item-template" type="text/template">
        <h4><a class="controls-toggle"><%- description %></a></h4>
        <div class="controls">
            <a class="edit">
                <span class="ss-icon ss-pika edit-toggle">edit</span>
                <span class="ss-icon ss-pike save-toggle">save</span>
            </a>
            <a class="remove">
                <span class="ss-icon ss-pika">delete</span>
            </a>
        </div>
        <div class="edit-func">
            <div class="form-block">
                <textarea name="description"><%- description %></textarea>
            </div>
            <div class="all-steps"></div>
        </div>
    </script>

{% endverbatim %}

child list template

{% verbatim %}

    <script id="step-list-template" type="text/template">
        <h1 class="section-title">My Steps</h1>
        <div id="steps" class="all-steps-list"></div>
    </script>

{% endverbatim %}

Router for Clarity:

$(function() {
    window.AppRouter = Backbone.Router.extend({
        routes: {
            'goals/': 'goals',
            'steps/': 'steps'
        },
        initialize: function() {
            // Goals
            this.goalsview = new GoalsView({
                collection: goals
            });
            goals.fetch({ reset:true });

            this.stepsview = new StepsView({
                collection: steps
            });
            steps.fetch({ reset:true });
        },
        goals: function () {
            $('#app').empty();
            $('#app').append(this.goalsview.render().el);
        },
        steps: function () {
            $('#app').empty();
            $('#app').append(this.stepsview.render().el);
        }
    });

    window.appRouter = new AppRouter();
    Backbone.history.start();
});
Dave Merwin
  • 1,382
  • 2
  • 22
  • 44

2 Answers2

0

Your code looks incomplete, So just added missing parts. With following code I could see Goals and Steps views being rendered. Let me know if your code is some thing different.

$(function () {

    window.Step = Backbone.Model.extend({
    })

    window.Steps = Backbone.Collection.extend({
        model:window.Step,
        url: 'data/steps.json'
    })

    window.Goal = Backbone.Model.extend({
        defaults: {
            description: null
        },
        initialize: function () {
            this.steps = new Steps();
            this.steps.fetch({ reset: true });
            this.stepsAll = new StepsViewForGoals({ collection: this.steps });
            $('.all-steps').append(this.stepsAll.render().el);
        }
    });
    window.Goals = Backbone.Collection.extend({
        model: Goal,
        url: 'data/goals.json'
    });

    window.goals = new Goals();

});


$(function () {
    window.GoalView = Backbone.View.extend({
        className: 'list-item',
        template: _.template($('#goal-item-template').html()),
        initialize: function () {
            _.bindAll(this, 'render');
            this.model.bind('change', this.render);
        },
        render: function () {
            this.$el.html(this.template(this.model.toJSON()));
            return this;
        }
    });
    window.GoalsView = Backbone.View.extend({
        el: '#app',
        template: _.template($('#goals-list-template').html()),
        initialize: function () {
            _.bindAll(this, 'render');
            this.collection.bind('reset', this.render);
            this.collection.bind('change', this.render);
            this.collection.bind('add', this.render);
        },
        render: function () {
            this.$el.html(this.template());
            this.collection.each(function (goal) {
                var view = new GoalView({ model: goal });
                $('#goals').append(view.render().el);
            });
            return this;
        }
    });
});


$(function () {
    window.StepView = Backbone.View.extend({
        className: 'list-item',
        template: _.template($('#step-item-template').html()),
        initialize: function () {
            _.bindAll(this, 'render');
            this.model.bind('change', this.render);
        },
        render: function () {
            this.$el.html(this.template(this.model.toJSON()));
            console.log('Individual step');
            return this;
        }
    });
    window.StepsViewForGoals = Backbone.View.extend({
        el: '.all-steps',
        template: _.template($('#step-list-template').html()),
        initialize: function () {
            _.bindAll(this, 'render');
            this.collection.bind('reset', this.render);
            this.collection.bind('change', this.render);
        },
        render: function () {
            this.$el.html(this.template());
            console.log(this.collection.toJSON());
            this.collection.each(function (step) {
                var view = new StepView({ model: step });
                $('.all-steps-list').append(view.render().el);
            });
            console.log('Steps View');
            return this;
        }
    });
});


$(function () {
    var view = new window.GoalsView({
        collection:window.goals
    });
    view.render();
    window.goals.fetch();
})
Ravi Hamsa
  • 4,721
  • 3
  • 14
  • 14
  • whenever something is not working, you should look into console first. – Ravi Hamsa Nov 06 '13 at 15:55
  • I've fixed the code for the render. However, that still doesn't render the views. Also, I'm not sure what you mean by the comment about the console. I've been using the console to make sure that things are loading. I didn't see an error in the console. Maybe I'm not understanding what I'm seeing, but there were no "undefined" errors or empty arrays. Thanks for the help. – Dave Merwin Nov 06 '13 at 16:44
  • I'm not sure I understand your changes. Regardless, that is handled by the router. The issue is with the steps not populating the Goals, not the goals not loading. I've added the router so you can see that the goals are loaded. I apologize if I'm not seeing what you are trying to point out. – Dave Merwin Nov 06 '13 at 19:19
0

I found it.

The issue is WHERE the call to render is made from.

It has to be made in the PARENT view of where you what the child to show up. I was doing it all in the initialize function, but that just put's a render call into a view that's still in memory. As soon as I moved the render OUT of the model.initialize and into the parent.view.render it worked.

Dave Merwin
  • 1,382
  • 2
  • 22
  • 44