【问题标题】:How to access data from routes in an Ember application template?如何从 Ember 应用程序模板中的路由访问数据?
【发布时间】:2018-12-17 06:32:40
【问题描述】:

我正在关注 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) 访问,但不能被应用程序模板访问。

【问题讨论】:

  • 首先你应该在模板中使用 {{#each model.navigation ...}} 来引用模型数据。其次,每条路线都对应其模板。在您的情况下,您需要应用程序路由来显示应用程序 hbs 中模型的数据。
  • 这正是我不感兴趣的,@kristjan。我有一个(非常常见的)情况,我需要一个通常的路线来提供要在父模板(application.hbs)内访问的数据。例如活动导航列表。
  • @Slavic 每个模板都有自己的路由是 ember 方式。约定优于配置,但如果您想在应用程序路由中显示导航模型,为什么不为您的应用程序路由返回多个模型?
  • @Craicerjack 假设我想遵循 ember 的方式,我该如何解决手头的问题?问题仍然存在:application.hbs 甚至没有自己的路由器,即使有,它的路由器也不知道数据,因为根据问题的定义,数据是特定于子路由的。跨度>
  • 您能否提供一些额外的文字您想要实现的目标。也许有更好的方法来解决您的问题以及您从错误的角度看待它。因为你现在在做什么对我来说没有任何意义。

标签: javascript ember.js ember.js-2


【解决方案1】:

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

routes/client.js

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

感谢伊万的回答!

【讨论】:

  • 焦点不是 controllerFor 方法的正确位置,但是,是的 - 我同意这不是最好的地方
【解决方案2】:

如何访问主模板中路由模型钩子提供的值

默认情况下,在路由的 setupController 钩子内,Ember 会将 set the property model on your controller 解析为从路由的 model 钩子返回的 promise 的解析值。

意味着您可以在模板中使用属性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()
});

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

【讨论】:

  • 我不关心使用其他名称访问数据。对我来说 model.navigation 完全没问题。任务就是掌握这些数据。
  • @Slavic 好的,我明白我是如何误解了你,我更正了我的答案。如有必要,我还添加了关于如何实现更多全局导航的建议。
  • 不幸的是,一项服务似乎无法解决手头的问题。它源于这样一个事实,即每个控制器都会对导航有发言权(例如,将导航项标记为活动,但不仅如此)。现在我倾向于 setupController 解决方案,虽然我还不知道它是否能解决我所有的导航问题,但它肯定是一个解决方案,具体来说。你有我的赞成票。
【解决方案3】:

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

模板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')

还有custom-navigation.hbs

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

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

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

client.js

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

some-different-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: []
        });

【讨论】:

    【解决方案4】:

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

    首先,这是我在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 中的 isHidden 属性都为真。

    【讨论】:

      猜你喜欢
      • 2014-06-10
      • 2014-02-16
      • 1970-01-01
      • 2013-06-12
      • 2016-02-29
      • 1970-01-01
      • 1970-01-01
      • 2015-03-20
      • 1970-01-01
      相关资源
      最近更新 更多