0

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});

....
3
  • Um, several things going on here, but first, where's your code for InitView? Commented Jan 11, 2012 at 1:11
  • Thanks JayC! i update my post with the View!! Commented Jan 11, 2012 at 8:55
  • Glad you figured it out. Commented Jan 12, 2012 at 18:31

2 Answers 2

1
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.

Sign up to request clarification or add additional context in comments.

1 Comment

Great Comment JayC and thank you for that!! but "this.initial.clefs" always return "undefined" really dont understand why!! no matter if "clefs" an Attributes or Properties!! :(
1

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") });}
  });

1 Comment

Thanks Andreas! I update my code! I still have errors with your example too!!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.