Reputation: 7743
I have pulled down a collection of models from the server like so:
I only want to render the first model in the view, and then when the user clicks a button in the rendered view we render the next model from the collection in sequence.
I cannot render the whole view and then show/hide as these are quiz questions and people will most likely figure out how to cheat that way!
My current view:
define([
'domLib',
'underscore',
'backbone',
'router',
'config',
'collection/quiz',
'text!template/quiz.html'
],
function($, _, Backbone, Router, AppConfig, QuestionList, QuizTemplate) {
var QuizView = Backbone.View.extend({
el: '[data-view="main-content"]',
template: _.template(QuizTemplate),
initialize: function onInitialize(param){
this.collection = new QuestionList();
this.collection.fetch({
reset: true,
data: {
categoryId: param.id || AppConfig.constants.CATEGORY,
limit: AppConfig.constants.QLIMIT
}
});
this.collection.bind('reset', this.render, this);
},
render: function onRender(){
this.$el.html(this.template({questions: this.collection.toJSON()}));
}
});
return QuizView;
});
My collection; the base64 decoding is there to decode the encoded response from the server:
define([
'domLib',
'underscore',
'backbone',
'router',
'config',
'model/quiz'
],
function($, _, Backbone, Router, AppConfig, Quiz) {
var QuestionList = Backbone.Collection.extend({
model: Quiz,
url: AppConfig.api.game.quiz,
parse: function onParse(response){
var self = this;
_.each(response, function(obj, index){
_.each(obj, function(val, key, list){
if(key !== 'id'){
obj[key] = self.decode64(val);
}
});
self.push(obj);
});
return this.models;
},
decode64: function onDecode(data){
var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
var o1, o2, o3, h1, h2, h3, h4, bits, i = 0,
ac = 0,
dec = '',
tmp_arr = [];
if (!data) {
return data;
}
data += '';
do { // unpack four hexets into three octets using index points in b64
h1 = b64.indexOf(data.charAt(i++));
h2 = b64.indexOf(data.charAt(i++));
h3 = b64.indexOf(data.charAt(i++));
h4 = b64.indexOf(data.charAt(i++));
bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
o1 = bits >> 16 & 0xff;
o2 = bits >> 8 & 0xff;
o3 = bits & 0xff;
if (h3 == 64) {
tmp_arr[ac++] = String.fromCharCode(o1);
} else if (h4 == 64) {
tmp_arr[ac++] = String.fromCharCode(o1, o2);
} else {
tmp_arr[ac++] = String.fromCharCode(o1, o2, o3);
}
} while (i < data.length);
dec = tmp_arr.join('');
return dec;
}
});
return QuestionList;
});
Upvotes: 0
Views: 208
Reputation: 35790
As @Loamhoof mentioned, one approach would be to add a currentQuestion
property to your collection, then give it some sort of getNextQuestion
method which increments currentQuestion
and then returns this.at(this.currentQuestion)
.
Another approach would be to use the Backbone.Collection
shift
method:
Remove and return the first model from a collection. Takes the same options as remove.
So instead of yourCollection.getNextQuestion()
you'd just call yourCollection.shift()
. However, this modifies the collection (removing the question you shift
out), so if you want to be able to go backwards through the collection you'll probably want to use the currentQuestion
appropach.
Upvotes: 1