【问题标题】:emberjs - how to mark active menu item using router infrastructureemberjs - 如何使用路由器基础设施标记活动菜单项
【发布时间】:2012-07-22 15:08:22
【问题描述】:

我正在尝试创建导航标签(取自Twitter Bootstrap):

<ul class="nav nav-tabs">
    <li class="active"><a href="#">Home</a></li>
    <li><a href="#">Profile</a></li>
    <li><a href="#">Messages</a></li>
</ul>

活动标签标有class="active"

http://jsfiddle.net/schawaska/pfbva/ 有一个很好的静态导航栏和路由器/插座功能示例,但是 我不明白如何创建动态导航栏/菜单/选项卡视图。

据我了解,可以在每个菜单项中使用类绑定:

 classNameBindings: ['isActive:active']

但是切换 isActive 属性的正确位置在哪里?

【问题讨论】:

标签: ember.js ember-old-router


【解决方案1】:

Ember 1.11+:

{{#link-to "dashboard" tagName="li"}}
  <a href="{{view.href}}">Dashboard</a>
{{/link-to}}

Ember bind-attr):

{{#link-to "dashboard" tagName="li"}}
  <a {{bind-attr href="view.href"}}>Dashboard</a>
{{/link-to}}

【讨论】:

  • 这必须是公认的答案。我只花了 10 分钟试图在
  • 标记上获取 bindAttr 以按名称引用 view.href,直到我找到它并意识到我把它全部倒退了。
  • 这绝对是最简单的方法
  • 绝对是我在小组中找到的最佳答案。
  • 这绝对是最简单的方法!应该是公认的答案。
  • 在链接元素上时,您需要明确地将光标设置为指针:a {cursor: pointer;} 请参阅marceldegraaf.net/2013/05/17/…
  • 【解决方案2】:

    如果您使用的是 Ember >= 1.11,那么下面的 https://stackoverflow.com/a/14501021/65542 是正确答案。


    我会创建一个NavigationView,参见http://jsfiddle.net/pangratz666/z8ssG/

    车把

    <script type="text/x-handlebars" data-template-name="navigation">
        <ul class="nav nav-tabs">
            {{#view view.NavItemView item="home" }}
                <a {{action gotoHome}} >Home</a>
            {{/view}}
            {{#view view.NavItemView item="profiles" }}
                <a {{action gotoProfiles}} >Profiles</a>
            {{/view}}
            {{#view view.NavItemView item="messages" }}
                <a {{action gotoMessages}} >Messages</a>
            {{/view}}        
        </ul>
    </script>
    

    JavaScript

    App.NavigationView = Em.View.extend({
        templateName: 'navigation',
        selectedBinding: 'controller.selected',
        NavItemView: Ember.View.extend({
            tagName: 'li',
            classNameBindings: 'isActive:active'.w(),
            isActive: function() {
                return this.get('item') === this.get('parentView.selected');
            }.property('item', 'parentView.selected').cacheable()
        })
    });
    

    在您的路线connectOutlets 中,您必须通过router.set('navigationController.selected', 'home'); 设置当前导航项...


    还可以查看 ember-bootstrap 存储库,它在 Ember.js 中包装了 Bootstrap 的这个和更多功能

    【讨论】:

    • 您能否更新您的答案以反映新路由器的变化?查看stackoverflow.com/questions/14328295/…
    • 非常感谢@pangratz。你是摇滚明星。
    • 如果你想改变标签而不改变 url 怎么办? (同时仍然使用路由器访问选项卡,例如/wizards/:wizard_id/edit,并且在向导中有 3 个步骤可以编辑,您不想更改 URL。)
    • FWIW,我更新了 pangratz 的示例,如图所示 jsfiddle
    • @bazzel:不幸的是,这不再起作用了。
    【解决方案3】:

    上面的一些建议对于 twitter bootstrap 案例仍然有效。你也可以试试这样的

    {{#link-to 'dashboard' tagName='li'}} 
      {{#link-to 'dashboard'}}Link Title{{/link-to}}
    {{/link-to}}
    
    1. link-toli tagName 将活动类应用于 li
    2. 内部link-to 将是一个anchor 元素,当您单击鼠标右键时,它会为您提供Open in New Tab 功能

    【讨论】:

    • 这就是我们所做的,非常适合 TWBS 标签
    【解决方案4】:

    最近有一个 Ember-cli 插件可用于执行此操作。它被称为ember-cli-active-link-wrapper

    安装:ember install ember-cli-active-link-wrapper

    你可以这样使用它:

    {{#active-link}}
      {{link-to "Index" "index"}}
    {{/active-link}}
    

    导致:

    <li class='active'>
        <a href="/" class='active'>Index</a>
    </li>
    

    【讨论】:

    • 这确实应该是公认的答案。在现代 Ember 中,所有支持率较高的都已损坏或无法维护。
    【解决方案5】:

    我知道这是旧帖子,但这里是 Ember 2.4.0

    的更新

    为了创建链接,你可以写

    {{#link-to 'photoGallery'}}
      Great Hamster Photos
    {{/link-to}}
    

    {{link-to 'Great Hamster Photos' 'photoGallery'}}
    

    当当前路由与链接的路由匹配时,Ember 会自动将类设置为活动状态(在此示例中为 photoGallery)。

    如果您也想控制其他路由上的“活动”类,可以通过设置current-when 属性来实现。

    {{#link-to 'photoGallery' current-when='photoGallery photoPreview'}}
      Great Hamster Photos
    {{/link-to}}
    

    此链接将在 photoGalleryphotoPreview 路由上都有 active 类。

    https://github.com/emberjs/ember.js/blob/v2.4.0/packages/ember-routing-views/lib/components/link-to.js#L140

    【讨论】:

      【解决方案6】:

      车把

      <ul class="nav">
          <li>{{#linkTo "index"}}Index{{/linkTo}}</li>
          <li>{{#linkTo "about"}}About{{/linkTo}}</li>
      </ul>
      

      Javascript

      App.Router.map(function() {
          this.route("about");
      });
      

      它会根据路由自动添加活动类。 注意:使用 ember-1.0.0-pre.4.js 测试

      【讨论】:

      • 这行得通,我遇到的唯一问题是它没有在我的根链接上设置默认值。我将我的索引模板呈现给我的“介绍”控制器,但这并没有在链接上设置类。知道该怎么做吗?
      【解决方案7】:

      你也可以把 isActive 方法改成这样:

      isActive: function() {
          return App.getPath('router.currentState.path') === "root.firms";
      }.property("App.router.currentState"),
      

      isActive: function() {
          return this.get('controller.target.currentState.path') === "root.firms";
      }.property("controller.target.currentState"),
      

      【讨论】:

        【解决方案8】:

        我看到这个问题很老了,但是如果你将 Ember.js 升级到 RC3,你可以使用tagName 属性,比如:

        {{#link-to messages tagName="li"}}Messages{{/link-to}}
        

        这里是 API - http://emberjs.com/api/classes/Ember.LinkView.html

        【讨论】:

          【解决方案9】:

          不确定它是否非常动态,但请尝试在http://codebrief.com/2012/07/anatomy-of-an-ember-dot-js-app-part-i-redux-routing-and-outlets/ 上查看解决方案 主要思想是检查您的应用程序的状态

          JavaScript:

          function stateFlag(name) {
            return Ember.computed(function() {
              var state = App.router.currentState;
              while(state) {
                if(state.name === name) return true;
                state = state.get('parentState');
              }
              return false;
            }).property('App.router.currentState');
          }
          
          ApplicationController: Ember.Controller.extend({
              isHome: stateFlag('home'),
              isSections: stateFlag('sections'),
              isItems: stateFlag('items')
            })
          

          车把:

          <li class="home" {{bindAttr class="isHome:active"}}>
          </li>
          <li class="sections" {{bindAttr class="isSections:active"}}>
          </li>
          <li class="items" {{bindAttr class="isItems:active"}}>
          </li>
          

          更新: pangratz 的解决方案看起来更漂亮

          【讨论】:

            【解决方案10】:

            这是一个完整的工作解决方案:

            查看:

            App.NavView = Ember.View.extend({
              tagName: 'li',
              classNameBindings: ['active'],
            
              active: function() {
                return this.get('childViews.firstObject.active');
              }.property()
            });
            

            模板:

            <ul>
              {{#each item in controller}}
              {{#view App.NavView}}
              {{#linkTo "item" item tagName="li"}}
                  <a {{bindAttr href="view.href"}}>
                    {{ item.name }}
                  </a>
              {{/linkTo}}
              {{/view}}
              {{/each}}
            </ul>
            

            【讨论】:

              【解决方案11】:

              从 v0.8.0 ember-bootstrap 开始支持导航,包括正确处理活动状态。而且没有任何链接到/标签名称的黑客:

              {{#bs-nav type="pills"}}
                 {{#bs-nav-item}}
                    {{#link-to "foo"}}Foo{{/link-to}}
                 {{/bs-nav-item}}
                 {{#bs-nav-item}}
                   {{#link-to "bar"}}Bar{{/link-to}}
                 {{/bs-nav-item}}
               {{/bs-nav}}
              

              http://kaliber5.github.io/ember-bootstrap/api/classes/Components.Nav.html

              【讨论】:

                【解决方案12】:

                这里提出的许多解决方案不适用于任何最新的 Ember 版本(例如,视图被弃用)。此外,仅使用 link-to 帮助程序不会解决问题,因为引导程序希望 active 类出现在 &lt;li&gt; 而不是 &lt;a&gt;

                所以我将尝试总结目前确实有效的解决方案:

                使用ember-cli-active-link-wrapper

                插件为此特殊用例提供了一个组件:

                <ul class="nav nav-tabs">
                  {{#active-link}}
                    {{#link-to "foo"}}Foo{{/link-to}}
                  {{/active-link}}
                  {{#active-link}}
                    {{#link-to "bar"}}Bar{{/link-to}}
                  {{/active-link}}
                </ul>
                

                取自https://stackoverflow.com/a/29939821/5556104

                使用ember-bootstrap

                ember-bootstrap 提供了许多将引导功能集成到您的 ember 应用程序中的组件,其中包括导航组件:

                {{#bs-nav type="tabs"}}
                   {{#bs-nav-item}}
                      {{#link-to "foo"}}Foo{{/link-to}}
                   {{/bs-nav-item}}
                   {{#bs-nav-item}}
                      {{#link-to "bar"}}Bar{{/link-to}}
                   {{/bs-nav-item}}
                 {{/bs-nav}}
                

                取自https://stackoverflow.com/a/38279975/5556104

                链接到黑客

                有点老套,但应该可以在没有任何附加插件的情况下工作:

                <ul class="nav nav-tabs">
                  {{#link-to "foo" tagName="li"}} 
                    {{#link-to "foo"}}Foo{{/link-to}}
                  {{/link-to}}
                  {{#link-to "bar" tagName="li"}} 
                    {{#link-to "bar"}}Bar{{/link-to}}
                  {{/link-to}}
                </ul>
                

                取自https://stackoverflow.com/a/23966652/5556104

                【讨论】:

                  【解决方案13】:

                  迟早要更改您的状态的命名或您必须通过代码和视图的任何内容,还为每条路线添加一个函数似乎是不可取的。 我的方法更加程序化和模块化:

                  # Parent View-Tamplate, holding the navbar DOM elements
                  App.NavView = Ember.View.extend( 
                    controller: App.NavArrayController
                    templateName: "ember-nav"
                  )
                  # We push NavItems into this array
                  App.NavArrayController = Ember.ArrayController.create(
                    content: Ember.A([])
                  )
                  # NavItem has two settable properties and 
                  # an programmatic active state depending on the router
                  App.NavItem = Ember.Object.extend(
                    title: ''
                    goto: null    # <=this is the name of the state we want to go to!
                    active: (->
                      if App.router.currentState.name == @.get "goto"
                        true
                      else
                        false
                    ).property('App.router.currentState.name').cacheable()
                  )
                  # the actual NavElement which gets the class="active" if the 
                  # property "active" is true, plus a on-click binding to
                  # make the Router transition to this state
                  App.NavItemView = Ember.View.extend(
                   tagName: "li"
                    classNameBindings: ["active"]
                    click: ->
                      App.router.transitionTo(@get('goto'))
                      false
                  )
                  

                  nav-view.hbs(用于 twitter-bootstrap 风格的导航)

                  <div class="nav-collapse collapse">
                    <ul class="nav">
                      {{#each App.NavArrayController}}
                        {{#view App.NavItemView classBinding="active" gotoBinding="goto"}}
                          <a href="#" {{bindAttr data-goto="goto"}}> {{title}}</a>
                        {{/view}}
                      {{/each}}
                    </ul>
                  </div>
                  

                  这样,我可以在路由器中创建和处理我的路由, 并排保持导航定义:

                  # put this somewhere close to the Router 
                  App.NavArrayController.pushObjects(
                    [
                      App.NavItem.create(
                        title: 'Home'
                        goto: 'home'
                      ),
                      App.NavItem.create(
                        title: 'Chat'
                        goto: 'chat'
                      ),
                      App.NavItem.create(
                        title: 'Test'
                        goto: 'test'
                      )
                    ]
                  )
                  

                  【讨论】:

                    【解决方案14】:

                    上面 baijum 的回答大部分是正确的,但是在最新版本的 Ember 中,“bind-attr”已被弃用。下面是新的写法:

                    {{#link-to "dashboard" tagName="li"}}
                        <a href="{{view.href}}">Dashboard</a>
                    {{/link-to}}
                    

                    如您所见,它更简单,而且有点像魔术......

                    【讨论】:

                      【解决方案15】:

                      正如其他人所说,使用{{#link-to}} 链接到现有的route,当该路由是当前URL 时,{{#link-to}} 会自动将active 添加到其CSS 类中。

                      Ember issue 4387

                      【讨论】:

                        猜你喜欢
                        相关资源
                        最近更新 更多
                        热门标签