Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Backbone dynamically switch templates

I need to initially set a Backbone view's template based on whether the date a user has selected is in the past or future as well as switch it later when it's collection changes pulling data from a different date. How do I do this? I thought I would be able to set the template to a function that returns the correct selector string based on whether I'm in the past or not, but this doesn't work.

pR.views.ScheduleJobView = Backbone.Marionette.ItemView.extend({
    tagName: "tr",
    // NEED A WAY TO SWITCH THIS TOO
    template: "#schedule-job-template"
});


pR.views.ScheduleJobsView = Backbone.Marionette.CompositeView.extend({
    // DOESN'T WORK
    template: function () {
        if (this.isPast)
            return "#schedule-jobs-past-template";
        else
            return "#schedule-jobs-template";
    },      itemView: pR.views.ScheduleJobView,

    itemView: pR.views.ScheduleJobView,
    itemViewContainer: "tbody",

    // Defaults for the model's url
    baseUrl: "/schedules/day/",
    baseApiUrl: "/api/schedule/day/",
    // Empty object to store url parameters
    urlParameters: {},

    initialize: function () {
        pR.vent.bindTo("change:parameters", this.changeUrl, this);
        this.model.url = this.baseApiUrl;
    },

    onRender: function () {
        console.log("Rendering Jobs View");
    },

    // Change the main model's url
    changeUrl: function (parameters) {
        // merge new parameters with old ones
        this.urlParameters = _.extend(this.urlParameters, parameters);

        var url = "";
        var apiUrl = this.baseApiUrl;

        _.each(this.urlParameters, function (value, parameter) {
            // Add each parameter segment to the url
            url = url + parameter + '/' + value + '/';
            apiUrl = apiUrl + parameter + '/' + value + '/';
        });

        this.model.url = apiUrl;
        console.log("Updated CurrentDay model url to " + apiUrl);
        this.model.fetch();

        console.log("Navigating to " + url);
        pR.routers.appRouter.navigate(url);
    },

    // Check if we are in the past
    isPast: function () {
        var year = this.urlParameters.year;
        var month = this.urlParameters.month;
        var day = this.urlParameters.day;
        var selectedDate = Date(year, month, day);

        if (selectedDate < Date()){
            return true;
        } else {
            return false;
        }
    }
});

Note that I'm using Marionette's composite views here, too, so I need a way to change the itemView's template based on the timeframe as well. I'm definitely open to approaching this differently if my basic strategy is poorly thought out.

like image 232
Gabriel Syme Avatar asked Sep 17 '12 20:09

Gabriel Syme


2 Answers

You are setting this.template to a method, and Marionette is looking for a string value.

You can probably get away with using the same logic but putting it into your initialize method.

pR.views.ScheduleJobsView = Backbone.Marionette.CompositeView.extend({
    template: null,
    [ ... ]
    initialize: function () {
         if (this.isPast) {
             this.template = "#schedule-jobs-past-template";
         } else {
             this.template = "#schedule-jobs-template";
         }
like image 158
phawk Avatar answered Nov 18 '22 23:11

phawk


There is a function called getTemplate built in for this, I know I saw it in the documentation (That's what I was googling for)

Marionette template switching documentation

like image 27
PJUK Avatar answered Nov 18 '22 22:11

PJUK