ember.js,ember-cli:奥特莱斯没有正确嵌套

时间:2014-11-12 03:02:37

标签: ember.js ember-cli

我遇到了一个问题,我无法让嵌套的插座在我的Ember CLI应用中正确显示。我想要的视图树如下:

  • 应用程序(所有资源的列表,其中client_availability为1)
  • - client_availabilities.index(client_availabilities列表)
  • - client_availability(个人client_availability)

这与Ember Starter Kit中的“application> posts.index> post”层次结构非常相似。我想要的行为是当我导航到client_availabilities.index时出现在“mainoutlet”中的client_availability列表,然后当我在“suboutlet”中调出一个单独的client_availability时,它会持续存在。

简单,对吗?这是默认行为&为什么我们都喜欢Ember。但是,我似乎无法让它发挥作用。当我在client_availabilities.index中明确指定我的命名子outlet并单击某个client_availability时,任何一个出口都没有显示:

场景1:在client_availabilities

中渲染子输出

/app/template/application.hbs:

    {{link-to 'Client Availabilities' 'client_availabilities'}}

    {{outlet 'mainoutlet'}}

/app/template/client-availabilities/index.hbs:

    {{outlet 'suboutlet'}}

/app/routes/client-availabilities/index.js:

    import Ember from 'ember';

    export default Ember.Route.extend({

      renderTemplate: function(){
          this.render({
            into: "application",
            outlet: "mainoutlet"
          });
      },

      model: function() {
        return this.store.find('client_availability');
      }

    });

/app/routes/client-availability.js:

    import Ember from 'ember';

    export default Ember.Route.extend({

      renderTemplate: function(){
          this.render('client_availability', {
            into: "client_availabilities",
            outlet: "suboutlet"
          });
      },

      model: function(params) {
        return this.store.find('client_availability', params.client_availability_id);
      }

    });

或者,当我在应用程序中定位我的mainoutlet时,client_availability出现在“suboutlet”client_availabilities.index从“mainoutlet”中消失:

场景2:在应用程序

中渲染子输出

/app/template/application.hbs:

    {{link-to 'Client Availabilities' 'client_availabilities'}}

    {{outlet 'mainoutlet'}}

    {{outlet 'suboutlet'}}

/app/template/client-availabilities/index.hbs :(空)

/app/routes/client-availabilities/index.js:

    import Ember from 'ember';

    export default Ember.Route.extend({

      renderTemplate: function(){
          this.render({
            into: "application",
            outlet: "mainoutlet"
          });
      },

      model: function() {
        return this.store.find('client_availability');
      }

    });

/app/routes/client-availability.js:

    import Ember from 'ember';

    export default Ember.Route.extend({

      renderTemplate: function(){
          this.render('client_availability', {
            into: "application",
            outlet: "suboutlet"
          });
      },

      model: function(params) {
        return this.store.find('client_availability', params.client_availability_id);
      }

    });

这是我的路由器,两种情况都是一样的:

/app/router.js:

    import Ember from 'ember';

    var Router = Ember.Router.extend({
      location: 'auto'
    });

    Router.map(function() {
      this.resource('client_availabilities', function() {
        this.resource('client_availability', { path: ':client_availability_id' });
      });
    });

    export default Router;

我很高兴分享更多代码,但应用程序被分成几个文件,遗憾的是我不能完整发布。谁能看到我做错了什么?该应用程序的其余部分工作正常,我似乎无法让这个基本行为工作。

1 个答案:

答案 0 :(得分:8)

你有一个只有{{outlet}}的/app/templates/client-availibilities.hbs模板吗?如果没有这个,应用程序将失去它在插座树中的位置。 Ember-CLI和Ember Starter Kit在结构上彼此非常不同,所以我可以看到混乱的来源。

我想如何看待Ember的渲染风格是模板文件夹中的每个把手文件(即/templates/users.hbs)表示应用程序从一个主题到另一个主体的整体状态的变化(例如:从新闻源到用户)。 templates文件夹中的相应子文件夹会更改主题本身的状态。

例如:

  • 必需的模板
    • 用户容器或应用程序范围内唯一的用户页面位于/templates/users.hbs
  • 可选模板
    • 用户索引位于/templates/users/index.hbs
    • 用户展示将在/templates/users/show.hbs
    • 用户新手将在/templates/users/new.hbs

您可以在没有[/templates/users/*.hbs]的情况下拥有[/templates/users.hbs]并仍然可以跟踪您的数据;但是,如果没有[/templates/users.hbs],您不能拥有[templates / users / index.hbs],并且仍然可以跟踪您的数据。为什么?想象一下,如果你导航到somesite.com/users。目前没有顶级模板,其中Ember可以呈现[users / index.hbs]模板。 [/templates/users.hbs]模板填补了这一空白,同时也充当了 / templates / users 文件夹中所有其他页面的容器。

例如,就您的应用而言,为了在用户访问http://www.yourwebsite.com/client-availibilities时呈现[/app/templates/client-availibilities/index.hbs],您的应用将需要定义这些模板,以便余烬可以钻进它们。

application.hbs                     // and in its outlet, it will render...
--client-availibilities.hbs         // and in its outlet, it will render by default...
----client-availibilities/index.hbs // then, for the client-availability (singular), you can have ember render it in
----client-availibilities/show.hbs  // will render also in the client-availabilites as it is a separate state of the subject. Can also be nested inside the index route within the router so that it renders inside the index template.

实际上,我会构建你的应用程序......

<强> /app/router.js

... // previous code

  Router.map(function() {
    this.resource('client_availabilities', function() {
      this.route('show', { path: '/:client_availability_id' });
      // this.route('new');  ! if needed !
      // this.route('edit', { path: '/:client_availability_id/edit' ); ! if needed !
    });
  });

... // code

<强> /app/templates/application.hbs

{{link-to 'Client Availabilities' 'client_availabilities'}}

{{outlet}}

<强> /app/templates/client-availabilities.hbs

{{outlet}}

<强> /app/templates/client-availabilities/index.hbs

<ul>
  {{#each}}
    {{#if available}}       
      <li>
        {{#link-to #link-to 'client-availabilities.show' this}}
          {{firstName}} {{lastName}}
        {{/link-to}}
      </li>
    {{/if}}
  {{else}}  <!-- we want this to only render if the each loop returns nothing, which is why it's outside the if statement -->
    <li>Nobody is available</li>
  {{/each}}
</ul>

<!-- Note: you don't need to put an outlet here because you're at the end of the tree -->

<强> /app/templates/client-availabilities/show.hbs

<!-- Everything you want to show about each availability -->>
<!-- Note: you don't need to put an outlet here because you're at the end of the tree -->

<强> /app/routes/client-availabilities/index.js

import Ember from 'ember';

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

<强> /app/routes/client-availabilities/show.js

import Ember from 'ember';

export default Ember.Route.extend({
  model: function(params) {
    return this.store.find('client-availability', params.client_availability_id);
  }
});

<强> /app/models/client-availability.js

import DS from 'ember-data';

var client-availability = DS.Model.extend({
  firstName: DS.attr('string'),
  lastname:  DS.attr('string'), 
  available: DS.attr('boolean'),
  available_on: DS.attr('date')
});

export default client-availability;

但是,您确定要根据每个客户的可用性来构建应用程序吗?由每个客户构建它然后过滤每个客户端以显示它们是否可用是不是更有意义?资源应该是名词,路径应该是形容词。因此,最好使用客户端作为模型而不是其可用性,并在模型上具有isAvailable属性(如上例所示)或与其他可用性模型的一对多关联(如果您想要显示具有多种可用性的客户(如下所示)。

例如,

<强> /app/models/client.js

import DS from 'ember-data';

var Client = DS.Model.extend({
  firstName: DS.attr('string'),
  lastName:  DS.attr('string'), 
  availabilities: DS.hasMany('availability')
});

export default Client;

<强> /app/models/availability.js

 import DS from 'ember-data';

 var Availability = DS.Model.extend({
   date:   DS.attr('date'),
   client: DS.belongsTo('client')
 });

 export default Availability;

从长远来看,后一种方法会将您的应用设置为立即显示所有可用性并允许用户通过客户端进行过滤,此外它还允许用户查看客户端并查看其所有可用性。使用原始方法(客户端模型上的isAvailable属性),用户只能从客户端模型本身获取可用性,但如果用户想要查看3月3日中午可用的所有客户端,该怎么办?好吧,如果没有与客户端模型相关联的可用性模型,您将不得不将大量代码放入客户端控制器中,如果沿着一对多路径,ember会默认为您提供这些代码。

如果您需要更多建议,请告知我们。我非常乐意添加您需要的模板,控制器和路由的更多示例,以便实现此目的。