【问题标题】:ember.js, ember-cli: Outlets not nesting properlyember.js、ember-cli:插座未正确嵌套
【发布时间】:2014-11-12 03:02:37
【问题描述】:

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

  • 应用程序(所有资源的列表,其中 client_availability 是其中之一)
  • - client_availabilities.index(client_availabilities 列表)
  • --client_availability(单个client_availability)

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

很简单,对吧?这是默认行为,也是我们都喜欢 Ember 的原因。但是,我似乎无法让它工作。当我在 client_availabilities.index 中明确定位我命名的子插座并单击单个 client_availability 时,两个插座中都没有显示:

场景 1:在 client_availabilities 中渲染 suboutlet

/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:在应用程序内渲染 suboutlet

/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;

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

【问题讨论】:

    标签: ember.js ember-cli


    【解决方案1】:

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

    我对 Ember 渲染风格的看法是,模板文件夹(即 /templates/users.hbs)中的每个把手文件都代表了应用程序的整体状态从一个主题更改为另一个主题(例如:从新闻提要到用户)。 模板文件夹中的相应子文件夹会更改主题本身的状态。

    例如:

    • 所需模板
      • 用户容器或应用程序范围内唯一需要的用户页面位于 /templates/users.hbs
    • 可选模板
      • 用户索引将位于 /templates/users/index.hbs
      • Users Show 将位于 /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 ],您的应用将需要定义这些模板,以便 ember 可以深入研究它们。

    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 会为您提供这些代码。

    如果您需要更多关于从这里去哪里的建议,请告诉我。我非常乐意添加更多您需要的模板、控制器和路由示例,以实现这一目标。

    【讨论】:

    • 谢谢!这非常有帮助。我的应用程序比 sn-ps 所提供的这些代码要复杂一些,但这让我更好地了解了 outlet 的工作原理并且我最终对其进行了排序。
    猜你喜欢
    • 2012-12-20
    • 2015-05-15
    • 2011-03-08
    • 2014-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多