1
votes

I'm trying to learn Backbone by diving right in and building out a simple "question" app, but I've been banging my head against the wall trying to figure out how to use models and/or collections correctly. I've added the code up to where I've gotten myself lost. I'm able to get the collection to pull in the JSON file (doing "var list = new QuestionList; list.getByCid('c0') seems to return the first question), but I can't figure out how to update the model with that, use the current model for the view's data, then how to update the model with the next question when a "next" button is clicked.

What I'm trying to get here is a simple app that pulls up the JSON on load, displays the first question, then shows the next question when the button is pressed.

Could anyone help me connect the dots?

/questions.json

[
  {
    questionName: 'location',
    question: 'Where are you from?',
    inputType: 'text'
  },
  {
    questionName: 'age',
    question: 'How old are you?',
    inputType: 'text'
  },
  {
    questionName: 'search',
    question: 'Which search engine do you use?'
    inputType: 'select',
    options: {
      google: 'Google',
      bing:   'Bing',
      yahoo:  'Yahoo'
    }
  }
]

/app.js

var Question = Backbone.Model.Extend({});
var QuestionList = Backbone.Collection.extend({
  model: Question,
  url: "/questions.json"
});

var QuestionView = Backbone.View.extend({
  template: _.template($('#question').html()),
  events: {
    "click .next" : "showNextQuestion"
  },
  showNextQuestion: function() {
    // Not sure what to put here? 
  },
  render: function () {
    var placeholders = {
      question: this.model.question, //Guessing this would be it once the model updates
    }
    $(this.el).html(this.template, placeholders));
    return this;
  }
});
1

1 Answers

2
votes

As is evident, in the current setup, the view needs access to a greater scope than just its single model. Two possible approaches here, that I can see.

1) Pass the collection (using new QuestionView({ collection: theCollection })) rather than the model to QuestionView. Maintain an index, which you increment and re-render on the click event. This should look something like:

var QuestionView = Backbone.View.extend({

  initialize: function() {
     // make "this" context the current view, when these methods are called
     _.bindAll(this, "showNextQuestion", "render");
     this.currentIndex = 0;
     this.render();
  }      
  showNextQuestion: function() {
     this.currentIndex ++;
     if (this.currentIndex < this.collection.length) {
         this.render();
     }
  },
  render: function () {
    $(this.el).html(this.template(this.collection.at(this.currentIndex) ));
  }
});

2) Set up a Router and call router.navigate("questions/" + index, {trigger: true}) on the click event. Something like this:

var questionView = new QuestionView( { collection: myCollection });

var router = Backbone.Router.extend({
    routes: {
        "question/:id": "question"
    },

    question: function(id) {
        questionView.currentIndex = id;
        questionView.render();
    }
});