Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access model association from view

Tags:

ember.js

I have user and workspace models with a belongsTo / hasMany relationship:

App.User = DS.Model.extend({
  name: DS.attr('string'),
  workspace: DS.belongsTo('App.Workspace')
});

App.Workspace = DS.Model.extend({
  name: DS.attr('string'),
  users: DS.hasMany('App.User')
});

I have a controller and view setup with the controller's model property set to a valid user.

App.ApplicationRoute = Ember.Route.extend({
  setupController: function() {
    this.controllerFor('test').set('model', App.User.find(1));
  }
});

The following code and output shows that the belongsTo association has not been loaded at the time the code is executed. What is the proper way to access the workspace (through the user) from the view class?

App.TestView = Ember.View.extend({

  didInsertElement: function() {
    var self = this;

    console.log('first try: ');
    console.log(this.get('controller.model.workspace'));

    setTimeout(function() {
      console.log('second try: ');
      console.log(self.get('controller.model.workspace'));
    }, 1000);
  }
});

Outputs;

// first try: 
// null 
// second try: 
// Class { ... }

I can access the workspace in the template via {{model.workspace}} — how do I do the same thing in the view class?

like image 282
Sean Rucker Avatar asked Dec 27 '22 10:12

Sean Rucker


1 Answers

What is the proper way to access the workspace (through the user) from the view class?

Your method this.get('controller.model.workspace') is the right way to access the workspace from your view. But as your example shows the didInsertElement() hook is the wrong place to do it. Since App.User.find(1) is asynchronous, you cannot count on model.workspace (or even model itself) being available when the template is being rendered. That's why your console.log returns null the first time.

This is perhaps not obvious since Ember works very hard to eliminate explicit forms of asynchronous behavior. Since it returns a model reference right away we might expect App.User.find() to be synchronous but it's not. Have a look at managing-asynchrony for a closer look at the details.

I can access the workspace in the template via {{model.workspace}} — how do I do the same thing in the view class?

Behind the scenes, handlebars is binding {{model.workspace}} to your model and re-rendering the template when the value changes. You should use a similar technique from your view class. Depending on what you are looking to accomplish, you may want to use a binding, computed property, or an observer. For example:

App.TestView = Ember.View.extend({

  workspaceChanged: function() {
    console.log('workspaceChanged to: ');
    console.log(this.get('controller.model.workspace'));        
  }.observes('controller.model.workspace')

});

Also see Bindings. Observers, Computed Properties: What Do I Use When?

like image 138
Mike Grassotti Avatar answered Dec 29 '22 13:12

Mike Grassotti