shearichard
shearichard

Reputation: 8372

Emberjs controller receives return value of the Route's model() method?

I'm working on Ember 2.13.0

The Ember.js doco for controllers says "The controller receives a single property from the Route – model – which is the return value of the Route's model() method." .

I'm not clear how I can access this data.

I have a route that looks like this :

export default Ember.Route.extend({
    model: function() {
      return this.store.findAll('costcentrehierarchyfortree');
    }
});

And a controller that looks like this :

export default Ember.Controller.extend({
    data: function() {
            var arrJSTreeElements = this.model.map(obj =>{ 
                /*
                 * This is the type of structure that needs to be output
                 *
                [
                    { "id" : "ajson1", "parent" : "#", "text" : "Simple root node" },
                    { "id" : "ajson2", "parent" : "#", "text" : "Root node 2" },
                    { "id" : "ajson3", "parent" : "ajson2", "text" : "Child 1" },
                    { "id" : "ajson4", "parent" : "ajson2", "text" : "Child 2" },
                ]
                */
                var rObj = {};
                rObj['id'] = obj.cchcceidchild;
                if (obj.cchcceidparent === obj.cchcceidchild)
                {
                    //This is the top of the tree
                    rObj['parent'] = "#";
                }
                else
                {
                    rObj['parent'] = obj.cchcceidparent;
                }
                rObj['text'] = obj.ccidescriptionchild;
                return rObj;

            });
            return arrJSTreeElements ;
    }
});

But when I visit the route in question I get a console error

Cannot read property 'map' of undefined

So I guess that using this.model to access the data returned from the route's model() method is not the way to go ... so what am I doing wrong ?

Thanks in advance.


EDIT: Just to make a little clearer what I'm trying to do here you can see a (somewhat) similar example in the demo app of the add on I'm using . Here's the controller https://github.com/ritesh83/ember-cli-jstree/blob/master/tests/dummy/app/dynamic/controller.js and here's the template https://github.com/ritesh83/ember-cli-jstree/blob/master/tests/dummy/app/dynamic/template.hbs .

This is , unfortunately, not a direct example because it relies upon static files rather than the data being returned due to the route being invoked but it does at least give some idea.


EDIT 2:

I was able to get this to work with the help of Lux and other resources I found.

In case this is helpful to anyone this is the version I used eventually and which works. Notice that the processing is no longer on the controller but on the route

import Ember from 'ember';

export default Ember.Route.extend({

    model: function() {
        return this.store.findAll('costcentrehierarchyfortree');
    },

    setupController(controller, model) {
        this._super(controller, model);        
        //
        this.store.findAll('costcentrehierarchyfortree').then(function (arrRawCch) {
            var idx = 0;
            var arrJSTreeElements = arrRawCch.map(obj =>{ 
                idx++;
                var rObj = {};
                rObj['id'] = obj.get('cchCceIdChild');
                if (obj.get('cchCceIdParent') === obj.get('cchCceIdChild'))
                {
                    //This is the top of the tree
                    rObj['parent'] = "#";
                }
                else
                {
                    rObj['parent'] = obj.get('cchCceIdParent');
                }
                rObj['text'] = obj.get('cceIdentifierChild');
                //
                // Add non-jstree-standard data into 'data' object
                // see this forum post for more details
                // https://groups.google.com/forum/#!topic/jstree/qBM2ZCAkPL4
                //
                rObj['data'] = {};
                rObj['data']['cchDrvId'] = obj.get('cchDrvId');
                //
                return rObj;
            });

            Ember.set(controller, 'data', arrJSTreeElements)
        });
    },
});

Upvotes: 0

Views: 71

Answers (1)

Lux
Lux

Reputation: 18240

First, when/how do you call the data function? Because such a function seems a bit strange in ember world. I would implement this code as a computed property.

So are you sure this code runs after the router has entered the route? Be careful, the router waits for promises returned by the model hook, and also waits for promises from the afterModel hook before giving the model to the controller. So ensure your functions does not run to early.

Also yes, you're doing it wrong. this.model should not be used. In general dot notation should not be used to access properties on ember objects. (note: this is only true until ember 3.1 which does introduce ES5 Getters for Computed Properties in the current released beta).

You should use Ember.get or obj.get:

// legazy import
import Ember from 'ember';
const {get} = Ember;

// import with modules syntax when using ember-cli-babel >= 6.8.0, introduced with ember 2.16
import {get} from '@ember/object'  

// use of .get to access a property. obj might be this or any other ember object. This will work for ember objects and non ember objects.
get(obj, 'foo')

// if obj is an ember object you can also use .get, but this will throw for non ember objects
obj.get('foo')

Upvotes: 1

Related Questions