Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access data from routes in an Ember application template?

I'm following along the docs for Ember 2.3 and can't seem to find anywhere something very basic: how does one access a value provided by the route's model hook inside the main template: application.hbs?

routes/client.js

// ...
export default Ember.Route.extend({
    model() {
        return {
            navigation: [
                {
                    title: "Projects",
                    link: "projects"
                },
                {
                    title: "My Specifications",
                    link: "specs"
                }
            ]
        }
    }
});

templates/application.hbs

<nav>
   {{#each navigation as |navItem|}}
      <li>{{#link-to navItem.link}} {{navItem.title}} {{/link-to}}</li>
   {{/each}}
</nav>
{{outlet}}

As it is now, the navigation object is accessible to the route's template (client.hbs) but not to the application template.

like image 593
Slavic Avatar asked Feb 03 '16 16:02

Slavic


2 Answers

Here's how it's done (unless ember comes up with a better way in future releases):

routes/client.js

// ...
export default Ember.Route.extend({
    setupController() {
        this.controllerFor('application').set('navigation', ["nav1", "nav2"]);
    }
});

Thanks, Ivan, for the answer!

like image 195
Slavic Avatar answered Nov 15 '22 07:11

Slavic


How does one access a value provided by the route's model hook inside the main template

By default, inside the setupController hook of the route, Ember will set the property model on your controller to the resolved value of the promise returned from the model hook of the route.

Meaning you can just use the property model in your template to access model.navigation:

<nav>
   {{#each model.navigation as |navItem|}}
      <li>{{#link-to navItem.link}} {{navItem.title}} {{/link-to}}</li>
   {{/each}}
</nav>

If you want to use a different name, you can override the setupController hook and set the name yourself:

export default Ember.Route.extend({
  // ... 
  setupController(controller, model) {
    this.set('navigation', Ember.get(model, 'navigation'));
  }
  // ... rest of the code
})

Which means you can now use navigation instead of model.navigation inside you template. Another way could be to add an alias inside your controller for the model property:

export default Ember.Controller.extend({
  navigation: Ember.computed.alias('model.navigation')
  // ... rest of the code
})

Which will allow you as well to use navigation instead of model.navigation.

However, if you want to have some sort of global navigation in your application, the better way would be to use a Service which you would inject into any controller that needs navigation. Something like:

// app/services/navigation.js
export default Ember.Service.extend({
  items: null,

  init() {
    this._super(...arguments);
    this.set('items', [{
      title: "Projects",
      link: "projects"
    }, {
      title: "My Specifications",
      link: "specs"
    }]);
  }
});

And then inject it in your controllers:

export default Ember.Controller.extend({
    navigation: Ember.service.inject()
});

And now you have access to navigation in that controller's template as well.

like image 2
nem035 Avatar answered Nov 15 '22 08:11

nem035