2012-11-20 67 views
0

我有这样(的CoffeeScript)的集合视图:设置一个Ember.CollectionView的所选项目

App.SearchSuggestionsList = Ember.CollectionView.extend 
    tagName: 'ul' 
    contentBinding: 'controller.controllers.searchSuggestionsController.content' 
    itemViewClass: Ember.View.extend 
    template: Ember.Handlebars.compile('{{view.content.title}}') 
    isSelected: (-> 
     /* This is where I don't know what to do */ 
     this.index == controller's selected index 
    ).property('controller.controllers.searchSuggestionsController.selectedIndex') 
    emptyView: Ember.View.extend 
    template: Ember.Handlerbars.compile('<em>No results</em>') 

正如你可以看到有该isSelected方法里面的一些伪代码。我的目标是通过这个尚未实现的isSelected属性定义当前选定项目的概念。这将允许我将条件className应用于当前选定的项目。

这是要走的路吗?如果是,那么这是如何实现Select方法的?如果不是,那么实现同样目标的另一种方法是什么?

回答

0

这样做的琐碎(或最知名的)方法是让你的子视图(navbar项)遵守绑定到控制器的父视图(navbar)中的“selected”属性,所以在你的路由中你告诉控制器哪个项目被选中。检查这fiddle整件事情。

例子:

把手导航栏的模板

<script type="text/x-handlebars" data-template-name="navbar"> 
    <ul class="nav nav-list"> 
     <li class="nav-header">MENU</li> 
     {{#each item in controller}}    
      {{#view view.NavItemView 
        itemBinding="item"}} 
       <a {{action goto item target="view"}}> 
        <i {{bindAttr class="item.className"}}></i> 
        {{item.displayText}} 
       </a> 
      {{/view}} 
     {{/each}} 
    </ul>  
</script> 

导览列控制器应该有,你还可以绑定在你看来

App.NavbarController = Em.ArrayController.extend({ 
    content: [ 
     App.NavModel.create({ 
      displayText: 'Home', 
      className: 'icon-home', 
      routeName: 'home', 
      routePath: 'root.index.index' 
     }), 
     App.NavModel.create({ 
      displayText: 'Tasks', 
      className: 'icon-list', 
      routeName: 'tasks', 
      routePath: 'root.index.tasks' 
     }) 
    ], 
    selected: 'home' 
}); 

然后,“选择”属性,你具有与此类似的视图结构,其中子视图检查父视图“选定”是否具有子视图的相同名称

App.NavbarView = Em.View.extend({ 
    controllerBinding: 'controller.controllers.navbarController', 
    selectedBinding: 'controller.selected', 
    templateName: 'navbar', 
    NavItemView: Em.View.extend({ 
     tagName: 'li', 
     // this will add the "active" css class to this particular child 
     // view based on the result of "isActive" 
     classNameBindings: 'isActive:active', 
     isActive: function() { 
      // the "routeName" comes from the nav item model, which I'm filling the 
      // controller's content with. The "item" is being bound through the 
      // handlebars template above 
      return this.get('item.routeName') === this.get('parentView.selected'); 
     }.property('item', 'parentView.selected'), 
     goto: function(e) { 
      App.router.transitionTo(this.get('item.routePath'), e.context.get('routeName')); 
     } 
    }) 
}); 

然后,设置它在你的路线是这样的:

App.Router = Em.Router.extend({ 
    enableLogging: true, 
    location: 'hash', 
    root: Em.Route.extend({ 
     index: Em.Route.extend({ 
      route: '/', 
      connectOutlets: function(r, c) { 
       r.get('applicationController').connectOutlet('navbar', 'navbar'); 
      }, 
      index: Em.Route.extend({ 
       route: '/', 
       connectOutlets: function (r, c) { 
        // Here I tell my navigation controller which 
        // item is selected 
        r.set('navbarController.selected', 'home'); 

        r.get('applicationController').connectOutlet('home'); 
       } 
      }), 
      // other routes.... 
     }) 
    }) 
}) 

希望这有助于

+0

此解决方案适用于静态项目列表,如应用导航栏菜单中的不同选项。您为每一个标签或名称分配一个标签或名称,然后控制器中的选定属性被赋予您想要选择的项目的值。 但我打算在用户输入文本字段时动态生成的建议列表上执行此操作。这并不意味着你的答案不会起作用,我只需要尝试一下,看看有什么不同,以及如何应对它们。我会带着我的发现回到这里。 – Ernesto

+0

另外,所选元素更改的方式也不同。在导航栏中,它是触发改变的点击事件,并且在建议列表中,用户在键盘上键入向上和向下箭头键,从而允许他选择他想要的建议。再次,不是一个不可逾越的差异,只有当您的答案适应我的需求时才需要考虑。 – Ernesto

+0

好吧,我不知道这将在用户类型或方向键上。这可能还有几件事要实施,但如果不相同,这个概念应该非常相似。 – MilkyWayJoe

1

我认为它解决了你正在寻找,以改变列表的情况。

我们所做的与上述解决方案类似,但所选标志基于集合的控制器,而不是所选标志。这可以让我们通过点击,网址,按键等来改变“选定”的作品,因为它只关心itemController中的内容。

所以SearchListController引用的项目和项目控制器(记住调用connectController路由器)

App.SearchListController = Em.ObjectController.extend 
    itemsController: null 
    itemController: null 

App.SearchListView = Em.View.extend 
    templateName: "templates/search_list" 

中的各个项目需要有自己的看法。如果它们的上下文(它是一个项目)与itemController中的项目匹配,则它们将被选择添加为类。

App.SearchListItemView = Em.View.extend 
    classNameBindings: ['selected'] 
    tagName: 'li' 
    template: Ember.Handlebars.compile('<a {{action showItem this href="true" }}>{{name}}</a>') 
    selected:(-> 
    true if @get('context.id') is @get('controller.itemController.id') 
).property('controller.itemController.id') 

的SearchList模板然后就循环遍历上述ItemsController所有的项目和他们是在单个项目视图中的上下文。

<ul> 
    {{each itemsController itemViewClass="App.SearchListItemView"}} 
</ul> 

这与您要找的内容接近吗?

相关问题