3

Solution in my route

Myapp.Routes = Backbone.Router.extend({
   init: function(){
        user = new User();
        user.fetch({user,
                     success: function(response){
                             user.classlist = new classes(response.attributes.classes);
           });

   }

});

I've got a serialized json array being returned from my server, and I am trying to put the nested objects into my nested collections.

This answer, I thought was going to get me there, but I'm missing something. How to build a Collection/Model from nested JSON with Backbone.js

The json which I am trying to populate my nested model with is

{first_name: "Pete",age: 27, classes: [{class_name: "math", class_code: 42},{class_name: "french", class_code: 18}]}

I create my user model

MyApp.Models.Users = = Backbone.Model.extend({

    initialize: function(){
        this.classlist = new MyApp.Collections.ClassList();

        this.classlist.parent = this;

    }

});

I had tried to follow the example on the other page, and use

      this.classlist = new MyApp.Collections.ClassList(this.get('classes'));

        this.classlist.parent = this;

but this.get('classes') returns undefined.

I've also tried getting the classes array through this.attributes.classes, but that is also undefined.

------------updated to include re-initialize -------------------- The function where I am initializing the user and classes is in the User routes and is called re-initialize. I use this function to fetch the user and their classes and store the object.

re_initialize: function(id){
            user = new MyApp.Models.User();
            MyApp.editingClasses.url = 'classes/'+id;
            MyApp.editingClasses.fetch({
                        success: function(response){
                        MyApp.editingClasses.parse(response);
                        }
            });

        new MyApp.Views.ClassesInput();
    },

As you can see, I'm calling the parse explicitly in the success function, but it isn't adding the classes to the collection.

I can't include the 'collection' because for some reason I can't access it in backbone. the user model, after getting returned to backbone includes the classes array, which I am trying to put into the ClassList collection.

The user model object copied from the javascript terminal looks like this.

attributes: Object
created_at: "2012-01-05T16:05:19Z"
id: 63
classes: Array[3]
   0: Object
   created_at: "2012-01-18T20:53:34Z"
   id: 295
   teacher_id: 63
   class_code: 42
   updated_at: "2012-01-18T20:53:34Z"
   class_name: math
   __proto__: Object
  1: Object
  2: Object
  length: 3
  __proto__: Array[0]
Community
  • 1
  • 1
pedalpete
  • 21,076
  • 45
  • 128
  • 239
  • can you post more codes? the collection for example? – 3logy Jan 17 '12 at 03:37
  • @trouble, I've updated the question to include my 're-initailize' function and the object as backbone sees it, though as I mention above, I can't access the classes through `user.attributes.classes` – pedalpete Jan 18 '12 at 21:11

2 Answers2

9

You can use the parse function to pre-process the server response:

MyApp.Models.Users = Backbone.Model.extend({
  parse: function(response) {
    var classesJSON = response.classes;
    var classesCollection = MyApp.Collections.ClassList(classesJSON);
    response.classes = classesCollection;
    return response;
  }
});

var user = new MyApp.Models.Users();
user.fetch();

// You should now be able to get the classlist with:
user.get('classes');

That said, the approach suggested in the other question should also work. It could be that when your initialize function is called, the model hasn't yet been populated with the data?

For example, if you're doing:

var user = new MyApp.Models.Users();

It won't have any attributes yet to give to the classlist collection. Could that be your problem?

satchmorun
  • 12,487
  • 2
  • 41
  • 27
  • still no luck, I am getting the user model through `fetch()`, but of course, as you said, it doesn't have any attributes when I initialize, before running fetch, which is I'm guessing why I am not seeing the result. Is there a way to create the model and fetch at the same time? – pedalpete Jan 17 '12 at 12:19
  • you can use the `parse` method from the first part of my answer. – satchmorun Jan 17 '12 at 23:00
  • unfortunately, the `parse` method isn't working either. do i need to call it explicitly? – pedalpete Jan 18 '12 at 12:10
  • calling it explicity with `user.fetch({success(response):function(){user.parse(response)}}` still doesn't populate the classes. – pedalpete Jan 18 '12 at 14:21
  • this was close, but what I ended up with was the `parse` statment within my route. I've updated my question with the code form my solution. – pedalpete Jan 19 '12 at 13:03
  • 1
    I'm no expert but should var classesCollection = MyApp.Collections.ClassList(classesJSON); be var classesCollection = new MyApp.Collections.ClassList(classesJSON); – Chris Barry Apr 18 '12 at 14:10
4

Okay! you can maybe fetch the classes this way :

Model :

window.person = Backbone.Model.extend({
 defaults: { }
});

Collection :

window.ClassesCollection = Backbone.Collection.extend({
 model: person,  
 url: "http://your/url/data.json",
 parse: function(response){
   return response.classes;
 }
});

Router :

window.AppRouter = Backbone.Router.extend({
 routes: {
  ""  : "init"
 },

 init: function(){      
   this.classesColl = new ClassesCollection();
   this.classesColl.fetch();
   this.classesView = new ClassesView({collection: this.classesColl});     
 }
 });

View : (for rendering every classes)

window.ClassesView = Backbone.View.extend({
  el: $('...'),
  template: _.template($("...").html()),

  initialize: function() {
    this.collection.bind("reset", this.render, this);
  },
  render: function(collection) {

    _.each( collection.models, function(obj){ 
      ...
      //obj.get('class_name') or obj.get('class_code')
      ... 
    }, this );
       ...
    return this;
  }
});
3logy
  • 2,634
  • 8
  • 46
  • 99
  • Close, but not quite (though I'll give you the win anyway for your hard effort, and thank you, as you lead me to the answer. The problem with this solution (from what I see) is that you are suggesting that I make a second `fetch` for the classes, and that isn't right. I've commented on the above solution, as that was much closer to what I ended up with. – pedalpete Jan 19 '12 at 13:02