0

我有一个这样的集合视图(CoffeeScript):

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 应用于当前选择的项目。

这是要走的路吗?如果是,那么这个 isSelected 方法怎么实现呢?如果不是,那么实现相同目标的另一种方法是什么?

4

2 回答 2

1

我认为它通过不断变化的列表解决了您正在寻找的情况。

我们所做的与上面的解决方案类似,但 selected 标志是基于集合的控制器,而不是 selected 标志。这让我们可以通过点击、url、按键等更改“选定”部分,因为它只关心 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>

这和你要找的很接近吗?

于 2012-11-21T18:15:51.410 回答
0

执行此操作的简单(或最知名)方法是让您的子视图(导航栏项目)观察绑定到控制器的父视图(导航栏)中的“选定”属性,因此在您的路线中您告诉控制器选择了哪个项目。检查这个小提琴的全部内容。

例子:

导航栏的把手模板

<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....
        })
    })
})

希望这可以帮助

于 2012-11-20T22:31:04.093 回答