Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing parent route model in Ember.js

I'm trying to write a route that need access to its parent's model. I use this.modelFor(), but when I do that, the parent's model isn't completely loaded, so all its properties contains null.

This is the router, with two dynamic segments:

MGames.Router.map(function () {
    this.resource('games', function () {
        this.resource ('game', {path: '/:game_id'}, function () {
            this.resource('board', {path: '/boards/:board_id'});
        });
    });
});

This is my GameRoute, who works perfectly:

MGames.GameRoute = Ember.Route.extend ({
    model: function (params) {
        return MGames.Game.find(params.game_id);
    }
});

And finally this is the child route, who need access to the Game model, and this is what I wrote. But no matters what I do, the console.log() always prints null. If I check the game variable, the isLoad property is always null:

MGames.BoardRoute = Ember.Route.extend ({
    model: function (params) {
        var game = this.modelFor ('game');
        console.log (game.get("id"));
        return MGames.Board.find(game.get("id"), params.board_id);
    }
});

Am I doing something wrong, or (as I suspect) I'm missing some Ember concept?

like image 470
César García Tapia Avatar asked Jul 07 '13 19:07

César García Tapia


1 Answers

This part of your code looks good. Your assumptions are correct in that, the nested route should get the model of the parent via modelFor.

I suspect your find method is the source of the bug. I looked at your previous question, and I'm assuming the same Game.find is used here(?)

The problem is to do with Promises. Ember's router understands the async nature of the model hook. But it relies on you returning a Promise to do it's work. Currently you are using the jQuery promise but returning the game object immediately in it's uninitialized state. The query loads from the server but the model() hook is assumed to have resolved before that happens.

You want to directly return the jQuery Promise from your model hook + Do the parsing in the first then and return that as the result.

Here's your modified Game.find. Same principles apply to the other finders.

find: function (game, board) {
  url = [MGames.GAMES_API_URL];
  url.push ('games');
  url.push (game);
  url.push ('boards');
  url.push (board);
  url = url.join('/');

  return $.getJSON(url)
    .then(function(response) {
      var game = MGames.Game.create({isLoaded: false});
      game.setProperties(response);
      game.set('isLoaded', true);

      return game;
    });
}

Note that, the game object is returned as is. Ember understands that when the promise is resolved(by returning anything other than a promise), that result is the model for the model() hook. This game object is the model that will be now be available in modelFor in the nested route.

like image 194
Darshan Sawardekar Avatar answered Sep 30 '22 18:09

Darshan Sawardekar