【问题标题】:Best way to implement a tabpanel in ember?在 ember 中实现标签面板的最佳方法是什么?
【发布时间】:2012-10-08 19:22:10
【问题描述】:

我是 ember 新手,正在尝试构建一个 Ember 驱动的 Web 应用程序。我已经阅读了各种 tuts 并研究了几个例子。基本概念很清楚,但现在我一直在尝试实现标签面板。我的做法如下:

查看

Configurator.TabPanelView = Ember.View.extend({
    classNames: ['tabPanel'],
    templateName: 'tabPanel'
});

模板

<script type="text/x-handlebars" data-template-name='tabPanel'>
  <div class='tabHead'>
      <ul>
          {{#each tabViews}}
          <li {{action "{{this.actionName}}" target="{{this.value}}"}} >{{this.title}}</li>
          {{/each}}
      </ul>
      <div class="tab-content">{{outlet}}</div>
  </div>
</script>

在应用中的使用

var tab= Configurator.TabPanelView.create({

            classNames: ['assortment'],
            tabViews: [{ title: 'First', value:'Foo', actionName: 'firstTab' },{title: 'Second', value:'Foo', actionName: 'secondTab' }],

            firstTab: Ember.View.extend({
                templateName: 'first'
            }),
            secondTab: Ember.View.extend({
                templateName: 'second'
            })
        });
        tab.appendTo("body");

TabTemplate 已正确呈现,但如果我尝试单击 li 元素,则会引发以下错误

未捕获的错误:断言失败:目标 没有动作 {{this.actionName}}

我也很好奇是否应该使用路由器来实现标签。但据我所知,路由器作用于应用程序级别,旨在用于单个 UI 组合。

【问题讨论】:

  • Ember disquss 论坛发布了一个有用的bootstrap nav-tabs 实现,非常容易实现。

标签: tabs ember.js


【解决方案1】:

问题出在您的模板中:

<li {{action "{{this.actionName}}" target="{{this.value}}"}} >{{this.title}}</li>

AFAIK,动作不能被绑定,所以当你写这个时,它会尝试调用方法{{this.actionName}}而不是firstTab,例如。

我认为这是一个典型的例子,你应该使用 Ember.CollectionViewitemViewClass,它具有 click 方法,即:

App.MyCollectionView = Ember.CollectionView.extend({
  tagName: 'ul',
  templateName: 'the-template-name',
  itemViewClass: Ember.View.extend({
    click: function() {
      var actionName = this.get('content.actionName'),
          target = this.get('controller.target');
      target.send(actionName);
    }
  })
});

上面的代码肯定不对,但是思路就在这里。

但我认为路由器是做到这一点的正确方法。我建议你看一下Ember Router example by @ghempton,它用Ember.Router 定义选项卡。

【讨论】:

  • 路由器似乎是正确的道路。集合视图很复杂,必须添加状态必须代表自己进行管理。顺便说一句,很好的例子。
【解决方案2】:

你有两个选择:

1)每个标签页都有自己的控制器,视图,也必须在路由器中定义

<script type="text/x-handlebars" data-template-name="tabs"> 
    <div> 
      <ul class="nav nav-tabs"> 
        {{#view Bootstrap.TabItem item="info"}} 
          <a {{action gotoInfo}}>Info</a> 
        {{/view}} 
        {{#view Bootstrap.TabItem item="anamnese"}} 
          <a {{action gotoAnamnese}}>Anamnese</a> 
        {{/view}} 
        {{#view Bootstrap.TabItem item="medication"}} 
          <a {{action gotoMedication}}>Medication</a>  
        {{/view}} 
      </ul> 
      {{outlet}} 
    </div> 
</script>      

Bootstrap.TabItem = Ember.View.extend({
    tagName: 'li',
    classNameBindings: ['isActive:active'],

    isActive: function() {
        return this.get('item') === this.get('controller.selectedTab');
    }.property('item', 'controller.selectedTab').cacheable()
}); 

2)所有标签页都在一个大视图中,标签页将被隐藏或显示

{{#view Ember.TabContainerView currentView="info"}}
  <ul class="nav nav-tabs">
    {{#view Bootstrap.TabView value="info"}}<a>Info</a>{{/view}}
    {{#view Bootstrap.TabView value="anamnese"}}<a>Anamnese</a>{{/view}}
    {{#view Bootstrap.TabView value="medication"}}<a>Medication</a>{{/view}}
  </ul>
  {{#view Ember.TabPaneView viewName="info"}}
  {{view EEPD.InfoView}}
  {{/view}}
  {{#view Ember.TabPaneView viewName="anamnese"}}
  {{view EEPD.AnamneseView}}
  {{/view}}
  {{#view Ember.TabPaneView viewName="medication"}}
  {{view EEPD.MedicationView}}
  {{/view}} 
{{/view}}

Bootstrap.TabView = Ember.TabView.extend({
    tagName: 'li',
    classNameBindings: ['isActive:active'],

    isActive: function() {
        return this.get('value') === this.get('tabsContainer.currentView');
    }.property('tabsContainer.currentView').cacheable()
});

【讨论】:

  • Ember.TabView 和朋友在 1.0.pre 中被弃用。
  • 它们已被弃用,因为它们将被移动到Ember Controls
  • 不,它们将被完全删除,请参阅Issue #409
【解决方案3】:

有两种方法可以实现标签面板。

如果您希望您的标签可以添加书签,那么您应该使用路由器来实现它们:

模板

<script type="text/x-handlebars" data-template-name="application">  
  <div class="tabpanel">
    <div class="tabs">
      <div {{action "goToFirstTab"}}>First tab</div>
      <div {{action "goToSecondTab"}}>Second tab</div>
    </div>
    {{outlet}}
  </div>
</script> 

<script type="text/x-handlebars" data-template-name="firstTab">
  First Tab content
</script>

<script type="text/x-handlebars" data-template-name="secondTab">
  Second Tab content
</script>

代码

var App = Ember.Application.create();
App.ApplicationController = Ember.Controller.extend();
App.ApplicationView = Ember.View.extend();
App.FirstTabView = Ember.View.extend({templateName: "firstTab"});
App.FirstTabController = Ember.Controller.extend();
App.SecondTabView = Ember.View.extend({templateName: "secondTab"});
App.SecondTabController = Ember.Controller.extend();
App.Router = Ember.Router.create({
  root: Ember.Route.extend({
    goToFirstTab: Ember.Route.transitionTo("firstTab"),
    goToSecondTab: Ember.Route.transitionTo("secondTab"),
    index: Ember.Route.extend({
      route: "/",
      redirectsTo: "firstTab"
    }),
    firstTab: Ember.Route.extend({
      route: "/firstTab",
      connectOutlets: function (router) {
        router.get('applicationController').connectOutlet('firstTab');
      }
    }),
    secondTab: Ember.Route.extend({
      route: "/secondTab",
      connectOutlets: function (router) {
        router.get('applicationController').connectOutlet('secondTab');
      }      
    })    
  })
});
App.initialize(App.Router);

第二种方式,没有Router。

模板(请注意,动作的目标已更改)

<script type="text/x-handlebars" data-template-name="application">  
  <div class="tabpanel">
    <div class="tabs">
      <div {{action "goToFirstTab" target="controller"}}>First tab</div>
      <div {{action "goToSecondTab" target="controller"}}>Second tab</div>
    </div>
    {{outlet}}
  </div>
</script> 

<script type="text/x-handlebars" data-template-name="firstTab">
  First Tab content
</script>

<script type="text/x-handlebars" data-template-name="secondTab">
  Second Tab content
</script>

代码(几乎相同,只是现在将与选项卡相关的代码移至 ApplicationController。

var App = Ember.Application.create();
App.ApplicationView = Ember.View.extend();
App.Router = Ember.Route.create();
App.FirstTabView = Ember.View.extend({templateName: "firstTab"});
App.FirstTabController = Ember.Controller.extend();
App.SecondTabView = Ember.View.extend({templateName: "secondTab"});
App.SecondTabController = Ember.Controller.extend();
App.ApplicationController = Ember.Controller.extend({
  view: App.FirstTabView.create(),
  goToFirstTab: function () {
    this.connectOutlet("firstTab");
  },
  goToSecondTab: function () {
    this.connectOutlet("secondTab");
  }
});
App.initialize(App.Router);

【讨论】:

    猜你喜欢
    • 2010-12-24
    • 1970-01-01
    • 1970-01-01
    • 2021-12-25
    • 1970-01-01
    • 1970-01-01
    • 2011-05-24
    • 1970-01-01
    • 2011-07-03
    相关资源
    最近更新 更多