1

Basically I want to fetch a JSON file and store it in a model. However, when I try to access the attributes via get() it returns undefined. So lets say the JSON file has an array games that consists of objects with some attributes. It doesn't really matter. Just want to save them in the model and access them. So I'm doing something like this.

var player = Backbone.Model.extend({
   initialize: function(app, options) {
      this.app = app;
      var _this = this;

      this.fetch({
         url: "someurl",
         success: function() {
            console.log("success");
         }
      });
   }
});

var instplayer = new player();
instplayer.on('change', function(){
   console.log(model);
   console.log(model.get(games));
})

So I figured that I need an event to ensure that get() is called when the data is really available. But this still returns undefined. What do I need to do?

5
  • Do you mean that you fetch a player, and there's multidimentional data, that contains games? Is it like this: { username: "joe", games: [ { title:"Game One" }, { title: "Game Two" } ] } and then you just want to access the games property, is that right? Commented Oct 20, 2015 at 9:08
  • Yes that is right. As long as I can get anything that has been fetched from the JSON data. I mean I see the data when I look at the object through console.log but get() just simply returns undefined. Of course some values I put on the model with the defaults options can be returned without any problems. Commented Oct 20, 2015 at 9:28
  • After making sure you pass a string to the .get method, like model.get("games") in quotes, I would also suggest to use sync event instead of change. sync will make sure to fire when the content has come from the server. change will fire on any change to that model data, which might be more often than you'd want. Commented Oct 20, 2015 at 9:33
  • Thanks thats it. Makes sense so change was fired before the data was fully loaded and that why I couldn't get() it. Thanks a lot. Commented Oct 20, 2015 at 9:42
  • Great! I've also added a working example in my answer below, I hope that helps. Commented Oct 20, 2015 at 10:08

2 Answers 2

1

So I imagined you have a json for your player like this (I've mocked it here for the example below to work):

{
    "username": "joe",
    "games": [
        {
            "title": "Pacman"
        }, {
            "title": "Super Mario" } 
    ]
}

And here's a complete working example of how I would deal with managing and rendering this kind of data:

var Game = Backbone.Model.extend({
  defaults: {
    title: ''
  }
});

var Games = Backbone.Collection.extend({
  model: Game
});

var Player = Backbone.Model.extend({
  defaults: {
    username: ''
  },
  url: 'http://www.mocky.io/v2/56261127250000a01accb34f',
  initialize: function(){
    this.games = new Games();
    this.listenTo( this, "sync", this.initGames );
    this.fetch();
  },
  initGames: function(){
    this.games.add( this.get('games') );
    this.trigger('ready', this);
  }
});

var PlayerView = Backbone.View.extend({
  template: _.template('<h1><%=username%></h1> and his games: <ol class="games"></ol>'),
  render: function(){
    this.$el.html( this.template( this.model.toJSON() ) );
    this.model.games.each( this.renderGame, this );
    return this;
  },
  renderGame: function(game, i){
    var gameView = new GameView({ model: game });
    gameView.render().$el.appendTo( this.$('.games') );
  }
});

var GameView = Backbone.View.extend({
  tagName: 'li',
  template: _.template('<strong>Game:</strong> <%=title%>'),
  render: function(){
    this.$el.html( this.template( this.model.toJSON() ));
    return this;
  }
});


var dude = new Player();
dude.on('ready', function(player){
  var playerView = new PlayerView({ model: player });
  playerView.render().$el.appendTo( document.body );
});
<script src='http://code.jquery.com/jquery.js'></script>
<script src='http://underscorejs.org/underscore.js'></script>
<script src='http://backbonejs.org/backbone.js'></script>

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

1 Comment

Awesome. Much appreciated. That is exactly what I need. Pretty genius to add a collection to a model. Didn't know that that this is even possible. Thanks.
0

I don't know if it's a typo or not but you are not passing model to the callback

instplayer.on('change', function(){
  console.log(model);
  console.log(model.get(games));
})

it should be

instplayer.on('change', function(model, options){
  console.log(model);
  console.log(model.get("games"));
})

then games must be a string not a variable.

Another thing I suggest you to be aware of is what the json returns; sometimes you have to override the parse function to get the exact results.

Again if your fetching an array and not a single object, maybe you should use a collection of players

2 Comments

Thanks for the answer. Yes that is indeed a typo. Your suggestions aside this code then should give me the array back? I tried the same with a collection and then simply did parse: function(response) { return response.games; } This also populates the collection but I somehow cant access the populated attributes.
did you assign a model to the collection?

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.