I have an app in backbone where I want to find inside a Json some records and print out.
my JSON is like this:
[
{
\"id\" : \"r1\",
\"hotel_id\
Based on @Bergi's answer, I came up with this. It should solve your problem.
Here is a demo: http://plnkr.co/edit/NHE9V5?p=preview
Updated I have modified some things to accomodate your separate JSON files.
Cartesian Product Helper (http://en.wikipedia.org/wiki/Cartesian_product)
function cartesian(arg) {
arg = arg || [];
var r = [],
max = arg.length - 1;
function helper(arr, i) {
for (var j = 0, l = arg[i].length; j < l; j++) {
var a = arr.slice(0); // clone arr
a.push(arg[i][j]);
if (i == max) {
r.push(a);
} else helper(a, i + 1);
}
}
if(arg.length > 0)
helper([], 0);
return r;
}
Nested Collection Solution
HotelModel = Backbone.Model.extend({
initialize: function() {
// because initialize is called after parse
_.defaults(this, {
rooms: new RoomCollection()
});
},
parse: function(response) {
if (_.has(response, "rooms")) {
this.rooms = new RoomCollection(response.rooms, {
parse: true
});
delete response.rooms;
}
return response;
},
toJSON: function() {
var json = _.clone(this.attributes);
json.rooms = this.rooms.toJSON();
return json;
},
addRoom: function(rooms, options) {
return this.rooms.add(rooms, options);
},
removeRoom: function(rooms, options) {
return this.rooms.remove(rooms, options);
},
createRoom: function(attributes, options) {
return this.rooms.create(attributes, options);
},
getCombinations: function() {
return cartesian(_.values(this.rooms.groupBy('level')));
}
});
RoomModel = Backbone.Model.extend({});
HotelCollection = Backbone.Collection.extend({
model: HotelModel,
getAllCombinations: function(){
return this.map(function(hotel){
return _.extend(hotel.toJSON(), {
combinations: hotel.getCombinations()
});
});
}
});
RoomCollection = Backbone.Collection.extend({
model: RoomModel,
getRoomsByHotelId: function(hotelId) {
return this.where({
hotelId: hotelId
});
}
});
Loading of the Separate JSON
var hotels = new HotelCollection([], {
url: 'hotels.json'
});
var rooms = new RoomCollection([], {
url: 'rooms.json'
});
hotels.fetch({
success: function() {
rooms.fetch({
success: function() {
hotels.each(function(hotel) {
hotel.addRoom(rooms.getRoomsByHotelId(hotel.id));
});
// all done here
var combos = hotels.getAllCombinations();
$(function() {
$('body').append('<pre>' + JSON.stringify(combos, null, 2) + '</pre>');
});
}
});
}
});
hotels.json
[{
"id": 1,
"name": "Hotel One"
}, {
"id": 2,
"name": "Hotel Two"
}, {
"id": 3,
"name": "Hotel Three"
}]
rooms.json
[{
"level": 1,
"name": "Room A",
"hotelId": 1
}, {
"level": 1,
"name": "Room B",
"hotelId": 1
}, {
"level": 2,
"name": "Room A",
"hotelId": 1
}, {
"level": 2,
"name": "Room B",
"hotelId": 1
}, {
"level": 1,
"name": "Room A",
"hotelId": 2
}, {
"level": 1,
"name": "Room B",
"hotelId": 2
}, {
"level": 2,
"name": "Room A",
"hotelId": 2
}, {
"level": 2,
"name": "Room B",
"hotelId": 2
}, {
"level": 1,
"name": "Room A",
"hotelId": 3
}, {
"level": 1,
"name": "Room B",
"hotelId": 3
}, {
"level": 1,
"name": "Room C",
"hotelId": 3
}]
First you should split your rooms list by hotels and levels:
var rooms = _(allRooms.groupBy, "hotel_id");
for (var hotelid in rooms)
rooms[hotelid] = _.groupBy(rooms[hotelid], "level");
The "combinations" you're looking for is the cartesian product of the levels (for each hotel). You can use this helper function for example. Use it like this:
_.each(this.collection.models, function(hotel) {
var levels = rooms[hotel.id];
var combinations = cartesian(_.values(levels));
// put them on the hotel
});