如何从 Ember 应用程序模板中的路由访问数据?

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

我正在关注 Ember 2.3 的文档,但似乎无法在任何地方找到一些非常基本的东西:如何访问主模板内路由模型挂钩提供的值: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}}

就像现在一样,导航对象可供路由模板 (client.hbs) 访问,但不能供应用程序模板访问。

这是如何完成的(除非 ember 在未来的版本中提出更好的方法):

routes/client.js

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

谢谢 Ivan 的回答!

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

默认情况下,在 setupController hook of the route, Ember will set the property model on your controller 内从路由的 model 钩子返回的承诺的解析值。

意味着您可以在模板中使用 属性 model 来访问 model.navigation:

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

如果您想使用不同的名称,您可以覆盖 setupController 挂钩并自己设置名称:

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

这意味着您现在可以在模板中使用 navigation 而不是 model.navigation。另一种方法是在控制器中为 model 添加一个 alias 属性:

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

这将允许您使用 navigation 而不是 model.navigation

但是,如果您想在您的应用程序中进行某种全局导航,更好的方法是使用 Service,您可以将其注入到任何需要导航的控制器中。类似于:

// 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"
    }]);
  }
});

然后将其注入您的控制器中:

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

现在您也可以访问该控制器模板中的导航。

我会这样解决这个问题。创建一个接受自定义参数的导航组件。

模板application.hbs

{{custom-navigation url=apiURL user=user}}

现在在你的client.js

apiURL: 'navigations/client'

还有你的自定义组件custom-navigation.js

resolvedRouteNavs: function() {
   return DS.PromiseArray.create({
            promise: store.query(this.get('url'), { user? : userID?? });
   })
}.property('apiURL')

自定义-navigation.hbs.

{{#each resolvedRouteNavs as |navItem|}}
  {{navItem.name}}
{{/each}}

如果您将静态数组作为导航处理

然后不需要解析,只需输出绑定数组,每个路由都不同。

client.js

navs: [{ name: '1', route: 'foo'}, { name: '2', route: 'bar' }]

有些不同-place.js

navs: [{ name: 'blah', route: 'foo.bar'}, { name: 'meh', route: 'bar.foo' }]

真正的模型挂钩应该包含从服务器检索的数据。否则使用 setupController 钩子。

setupController: function(controller, model) {
        this._super(controller, model);

        controller.setProperties({
            nav: []
        });

我最近需要解决这个问题,我就是这样做的。

首先,这是我的 application.hbs 模板中的内容:

`    <!-- app/templates/application.hbs -->
<div class="page">
     {{!-- Main site navigation menu --}}
     {{app-navbar isHidden=hidesNavbar}}
         {{!-- Site content overrides this block --}}
         {{outlet}}
     {{!-- Main site footer --}}
     {{app-footer isHidden=hidesFooter}}
</div>`

在我的应用程序中,app-navbarapp-footer 都是知道如何使用 isHidden 属性 使自己可见或不可见的组件。有不同的方式来切换可见性,但为了简洁起见,让我们将任一组件的内容包装在一个条件块中,如下所示:

`<!-- app-navbar and app-footer -->
{{#unless isHidden}} 
     <!-- component HTML here --> 
{{/unless}}
`

现在,从我不想看到 app-navbarapp-footer 的路线,在我的情况下这是 login.js,我可以调用 setupController()并切换应用程序控制器的 hidesNavbarhidesFooter 属性。看起来像这样:

`// app/routes/login.js
import Route from '@ember/routing/route';
export default Route.extend({
    setupController() {
      this.controllerFor('application').set('hidesNavbar', true);
      this.controllerFor('application').set('hidesFooter', true);
    }
});`

现在,每当我们转换到登录路由时,都会在应用程序控制器上设置 hidesNavbarhidesFooter 属性,从而在 app-navbarapp-footer 都是真的。