Search code examples
javascriptbackbone.jsparse-platformbackbone-views

Rendering more than just model attributes in Parse JS API (backbone.js) view templates


So I'm trying to use a join table to display a list of data in my Parse app. The javascript API is similar enough to backbone.js that I'm assuming anyone who knows that could help me. I can't show my actual source code but I think I simple twitter-like "user follows user" scenario can answer my question. So assume I have a join table called "follows" that simply contains its own objectId, the id of each user in the relationship, and some meta-data about the relationship (needing metadata is why I'm using a join table, instead of Parse.Relation). I want to have a view that finds all of the users the current user follows and renders an instance of another view for each case. From what I have so far, that would looks something like this.

In the intialize of the top level view (let's call it AllFollowsView), I would have something like this.

var currentUser = Parse.User.current();
var followsQuery = new Parse.Query(Follows);
followsQuery.equalTo("userId", currentUser.id);
followsQuery.find({
    success: function(followsResult){
        for (var i = 0; i < followsResult.length; i++){
          var view = new OneFollowView({model:followsResult[i]});
          this.$("#followed-list").append(view.render().el);
        }//for loop       
    },
    error: function(error){
      console.log("error finding plans query");
    }
  });

OneFollowsView is just a view that renders an

  • showing data about the relationship and listens for changes on that particular relationship (mainly change or delete in my case). I understand that by passing in the corresponding model with

    var view = new OneFollowView({model:followsResult[i]});
    

    I can print out attributes of that model in the OneFollowsView template like this

    <li>You are following a user with the id of <%= _.escape(followedUserId) %></li>
    

    My problem is that this only gives me access to the information stored in the "follows" object. How would I pass in the corresponding user models (or any other models that I can query for the id of) into the template so I can access them in the html in the same way. I would like to be able to run queries in one of the views and then access those models in the html. I know I can add attributes to the object before declaring a new instance of the lower level class with that object as the model, but that doesn't help me because I don't want to save it with new attributes attached.

    EDIT: My render function for the top level function is empty at the moment. It's initilize function contains this line to render the template. I guess this should probably be in the render function and then I would call render from initialize.

    this.$el.html(_.template($("#all-follows-template").html()));
    

    Here's the render for the lower (individual li) view

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

    From my understanding this just renders the template to el while parsing the model to JSON and then returns to allow chained calls.


  • Solution

  • The problem here lies in you render method. When you call this.template in your render method. That method, this.template is a template function returned by calling the _.template function. When you call your this.template method, the properties of the object you pass in will be available as instance variables in your template.

    In your case you're passing in the JSON of the object. So, the properties of the model become names of variables available in your template. If you want to expose additional variables to the template you have a couple options: 1) Add to the jsonified model's attributes. 2) Send in the model as a top level variable and any additional variables you may want.

    // option 1
    render: function() {
      var templateArgs = _.extend(this.model.toJSON(), { additionalVar: 'new var' });
      var content = this.template(templateArgs);
      $(this.el).html(content);
    
      this.delegateEvents();
      return this;
    }
    
    // option 2
    render: function() {
      var templateArgs = {
        followResult: this.model.toJSON(),
        additionalVar: 'new var'
      };
      var content = this.template(templateArgs);
      $(this.el).html(content);
      return this;
      this.delegateEvents();
    }
    

    Either option is reasonable. I would probably go with option 2. Which allows you in the template to say something like:

    <li> <%= followResult.someProperty %> <%= additionalVar %> </li>
    

    Hope that helps. :)