Question

I have a JSON File looking like this:

JSON :

{
 "clefs": [ 
           {"title": "..", "path": ".."},
           ... , 
           {"title": "..", "path": ".."}
          ],

  ....

 "rests": [ 
           {"title": "..", "path": ".."}, 
           ... , 
           {"title": "..", "path": ".."}
          ]

} 

This is a nested JSON, right? So I try to convert that into Model/Collections nested into Backbone.js like this:

Backbone.js :

window.initModel = Backbone.Model.extend({
  defaults: {
    "title": "",
    "path": ""
  }
});

window.CustomCollection = Backbone.Collection.extend({
  model: initModel
});

window.Init = Backbone.Model.extend({
  url : function(){
  return  "/api/data.json"      
},

parse: function(response) {

  clefs = new CustomCollection();
  clefs.add(response.clefs);        
  this.set({clefs: clefs});

  .....

  rests = new CustomCollection();
  rests.add(response.rests);        
  this.set({rests: rests});
} 
});

Now I came out with a Model and into its Attributes my Collection: clefs, ..., rests.

When it's come to pass my Collection to a View I cannot!

I made this

Router :

$(document).ready(function() {
  var AppRouter = Backbone.Router.extend({
  routes: {
    ""  : "init"
  },

  init: function(){
    this.initial = new Init();      
    this.initialView = new InitView({model: this.initial});
    this.initial.fetch();

 }
});

var app = new AppRouter();
Backbone.history.start();
});

View :

window.InitView = Backbone.View.extend({
  initialize : function() {
    this.model.bind("reset", this.render, this);//this.model.attributes send my 4 Collections Models back! But impossible to extract with "get" these Attributes

},

  render : function() {
    console.log("render");
  }
});

It's an ugly situation right now!! I have a Backbone Model with Attributes(Collections) but I can't extract these Attributes, I try with JSON(), get, _.each, _.map but no success!

What i want is to extract my Collections out from the Model name's "initial"!! this.initial.attributes return an Object with my collections into it! but i cannot pass those to the View!

Update 1 :

Now the Model is passed to the View but i always cannot access his attributes with get or send his attributes to other Views! the render can not be fired too!!!

Update 2 : After several Days of headaches i take the resolution to make it simple!

Why? cause i just have 4 Collections for now : clefs, accidentals, notes and rests

MODEL :

window.initModel = Backbone.Model.extend({
  defaults: {
   "title": "",
   "path": ""
  }
});

window.ClefsCollection = Backbone.Collection.extend({
  model: initModel,
  url: "/api/data.json",
  parse: function(response){
    return response.clefs;
  }
});
...
and so on

ROUTER :

....

this.clefsColl = new ClefsCollection();
this.clefsColl.fetch();
this.clefsCollView = new ClefsView({collection: this.clefsColl});

....
Was it helpful?

Solution

init: function(){
  this.initial = new Init();      
  this.initialView = new InitView({model: this.initial});
  this.initial.fetch();
}

looks as I'd expected, but this:

clefs = new CustomCollection();
clefs.add(response.clefs);        
this.set({clefs: clefs});

Not so much. I'm a bit of a Backbone.js newb myself, so I'm still learning the best way to deal with composite models as well. What I've done previously is have a view keep track of two models (as it showed a list of lists, but with only one of the sublists viewable at any given time). Whenever an item of the first list was clicked, the model containing the sublist was selected, and from that model would "get" the field, toJSON() it (which is a really unfortunate name because it's not a JSON string but the object representation), and then reset a model bound to a view for the current sublist to be displayed. That's a bit hard to explain without code but I'm a little short on time at the moment. Later I may try to explain better (maybe with another answer).

EDIT 1

Just to clarify, my objection was to assigning through set and later retrieving through get. I'm just not sure how Backbone.js would handle that. I'd love to know, though.

EDIT 2

You might want to look at: backbone.js structuring nested views and models

Basically, he suggests instead of assigning through set, you just make the sub models properties of the composite model

so instead of

parse: function(response) {

  clefs = new CustomCollection();
  clefs.add(response.clefs);        
  this.set({clefs: clefs});

  .....

You'd have

parse: function(response) {

  this.clefs = new CustomCollection();
  this.clefs.add(response.clefs);
     /*Or maybe you really mean this.clefs.reset(response.clefs)*/

  .....  /* something similar for rests, etc */

}

And then if you wanted to bind a specific view, in your Router, assuming you've defined CleftsView, RestsView, etc.

  init: function(){
    this.initial = new Init();      
    this.initialView = new InitView({model: this.initial});
    this.clefsView = new ClefsView({model: this.initial.clefs});
    this.restsView = new RestsView({model: this.initial.rests});

    .....

    this.initial.fetch();
    .....

  }

I might have suggested this earlier, but I wasn't sure if this was a common practice or not. I'mt still not sure if I like the suggestion, as I'd be tempted to put the rests and clefts models under a "models" property of Init instead of directly under Init.

OTHER TIPS

This two lines make no sense at all:

init: function(){
  this.init = new Init();
  this.initView = new InitView({collection: this.init.get("rests") });
  this.init.fetch();

First you have a init function in your Router while calling this.init = new Init(); will overwrite this function, so when ever the route is called again init sint your function anymore but your Model. Next you create a new model without any data, so its empty. Than you try to get "rests" out of the empty model. After that you fill the model. Maybe you wanna something like this:

init: function(){
  //create a new model, fetch the data from the server. On success create a new view passing data from the model.
  var init = new Init().fetch({
      success: function(){new InitView({collection: init.get("rests") });}
  });
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top