Search code examples
javascriptember.jsember-dataember-cli

Access model from controller in ember.js


I have a simple application with a model, route and controller. I can't access the data from the model in my controller. I use ember-cli so I have the following structure:

/app/router.js

var Router = Ember.Router.extend({
  location: config.locationType
});
Router.map(function() {
  this.route('logs',{path: '/'});
});
export default Router;

/app/routes/logs.js

export default Ember.Route.extend({
  controllerName: 'logs',
  model: function() {
    return this.store.find('logs');
  }
});

/app/models/logs.js

export default DS.Model.extend({
  ip: DS.attr('string'),
  timestamp: DS.attr('number'),
  visited_resource: DS.attr('string'),
  pretty_string: DS.attr('string')
});

/app/controllers/logs.js

export default Ember.Controller.extend({
  url: function() {
    var model = this.get('model');
    var basePath = "http://example.com";
    var path = model.visited_resource;
    return basePath+path
  }.property('visited_resource')
});

My problem is that the model.visited_resources, or this.get('model.visited_resources') or this.get('model.[any param]') is undefined.

If I log the whole model object and inspect it, all my data is there! ! https://i.sstatic.net/nkvyT.png

It's just that the controller can't access it. What am I doing wrong?


Solution

  • Your model is an array from looking at that screenshot (content: Array[5]), so you need to get the first object if you want a single item:

    export default Ember.Controller.extend({
      url: Ember.computed('model', function() {
        var logs = this.get('model');
        var firstLog = logs.get('firstObject');
        var path = firstLog.get('visited_resource');
        var basePath = 'http://example.com';
        return basePath + path; 
      });
    });
    

    or iterate over each item and return an array:

    export default Ember.Controller.extend({
      urls: Ember.computed('model', function() {
        var logs = this.get('model');
        var basePath = 'http://example.com';
        var urls = logs.map(function(model) {
          var path = model.get('visited_resource');
          return basePath + path;
        });
        return urls;
       })
    });
    

    To create a computed property on the model, then do it on the model:

    export default DS.Model.extend({
      ip: DS.attr('string'),
      timestamp: DS.attr('number'),
      visited_resource: DS.attr('string'),
      pretty_string: DS.attr('string'),
      url: Ember.computed('visited_resource', function() {
        var basePath = 'http://example.com';
        var path = this.get('visited_resource');
        return basePath + path;
      })
    });
    

    and you'll be to access the url property like any other property:

       export default Ember.Controller.extend({
          url: Ember.computed('model', function() {
            var logs = this.get('model');
            var firstLog = logs.get('firstObject');
            return firstLog.get('url');
          })
        })
    

    You can also explicitly set the model using setupController:

    export default Ember.Route.extend({
      controllerName: 'logs',
      model: function() {
        return this.store.find('logs');
      },
      setupController: function(controller, model) {
        controller.set('model', model);
    
        // or first item only
        controller.set('model', model.get('firstObject'));
      }
    });