ember.js transitiontoroute emberjs-Wie markiert man einen aktiven Menüpunkt über die Router-Infrastruktur?




ember transitiontoroute (12)

Ich versuche Navigationsregisterkarten zu erstellen (aus 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>

Die aktive Registerkarte ist mit class="active" .

Es gibt ein großartiges Beispiel für statische Navbar und Router / Outlet-Funktion unter http://jsfiddle.net/schawaska/pfbva/ , aber ich kann nicht verstehen, wie man eine dynamische Navbar / Menü / Tab-Ansicht erstellt.

Soweit ich weiß, ist es möglich, Klassenbindungen in jedem Menüpunkt zu verwenden:

 classNameBindings: ['isActive:active']

Aber wo ist der richtige Ort, um isActive Attribute zu wechseln?


Ich weiß, das ist ein alter Post, aber hier sind Updates für Ember 2.4.0

Zum Erstellen von Links können Sie schreiben

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

oder

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

Ember setzt die Klasse automatisch auf aktiv, wenn die aktuelle Route der Link-Route entspricht (in diesem Beispiel photoGallery ).

Wenn Sie die Klasse "aktiv" auch auf anderen Routen steuern möchten, können Sie dies tun, indem Sie das Attribut current-when .

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

Dieser Link enthält eine active Klasse sowohl für photoGallery als auch für photoPreview Routen.

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


Wenn Sie Ember> = 1,11 verwenden, ist https://.com/a/14501021/65542 unten die richtige Antwort.

Ich würde eine NavigationView erstellen, siehe http://jsfiddle.net/pangratz666/z8ssG/ :

Lenker :

<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()
    })
});

Und in den connectOutlets Ihrer Route connectOutlets Sie das aktuelle Navigationselement über router.set('navigationController.selected', 'home'); ...

Sehen Sie sich auch das ember-bootstrap Repository an, das diese und weitere Funktionen von Bootstrap in Ember.js umschließt


Früher oder später wollen Sie die Benennung Ihrer Zustände ändern oder was auch immer Sie durch den Code UND die Ansicht gehen müssen, auch das Hinzufügen einer Funktion zum Übergang zu jeder Route scheint nicht wünschenswert. Mein Ansatz ist etwas programmatischer und modularer:

# 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 (für Twitter-Bootstrap-Navi)

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

Auf diese Weise kann ich einfach mit meinen Routen im Router arbeiten und herumfahren und die Nav-Definitionen nebeneinander aufbewahren:

# 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'
    )
  ]
)

Baijums Antwort oben ist größtenteils korrekt, aber in den neuesten Versionen von Ember ist das "bind-attr" veraltet. Hier ist die neue Art, es zu schreiben:

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

Wie Sie sehen können, ist es noch einfacher und funktioniert wie Magie.


Viele der hier vorgeschlagenen Lösungen funktionieren nicht für eine aktuelle Ember-Version (z. B. werden Ansichten veraltet). Außerdem wird das Problem nicht gelöst, wenn nur der link-to Helfer verwendet wird, da Bootstrap erwartet, dass die active Klasse auf dem <li> nicht auf dem <a> !

Also werde ich versuchen, die Lösungen, die tatsächlich funktionieren, zusammenzufassen:

Verwenden Sie ember-cli-active-link-wrapper

Das Addon bietet eine Komponente für diesen speziellen Anwendungsfall:

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

Entnommen von https://.com/a/29939821/5556104

benutze ember-bootstrap

ember-bootstrap bietet viele Komponenten, die die Bootstrap-Funktionalität in Ihre ember App integrieren, darunter die nav-Komponenten:

{{#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}}

Entnommen von https://.com/a/38279975/5556104

Link zu Hack

Etwas hacky, sollte aber ohne zusätzliches Addon funktionieren:

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

Genommen von https://.com/a/23966652/5556104


Ember 1.11+:

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

Ember <1,11 ( bind-attr erforderlich):

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

Nicht sicher, ob es sehr dynamisch ist, aber versuchen Sie eine Lösung zu finden unter http://codebrief.com/2012/07/anatomy-of-an-ember-dot-js-app-part-i-redux-routing-and-outlets/ Die Hauptidee besteht darin, den Status Ihrer App zu überprüfen

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

Lenker:

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

Update: Pangratz Lösung sieht schöner aus


Hier ist eine voll funktionsfähige Lösung:

Aussicht:

App.NavView = Ember.View.extend({
  tagName: 'li',
  classNameBindings: ['active'],

  active: function() {
    return this.get('childViews.firstObject.active');
  }.property()
});

Vorlage:

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

Wie andere Leute sagten, wenn {{#link-to}} zu einer bestehenden route verlinkt wird, wird {{#link-to}} automatisch zu seinen CSS Klassen hinzugefügt, wenn diese Route die aktuelle URL ist.

Siehe Ember Ausgabe 4387


Sie können die isActive-Methode auch folgendermaßen ändern:

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

oder

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

Ich sehe, diese Frage ist ziemlich alt, aber wenn Sie Ember.js auf die RC3 tagName , können Sie tagName Eigenschaft verwenden, wie:

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

Hier ist die API - http://emberjs.com/api/classes/Ember.LinkView.html


Lenker

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

Javascript

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

Basierend auf der Route wird automatisch eine aktive Klasse hinzugefügt. Hinweis: Es wird mit ember-1.0.0-pre.4.js getestet