Affectation de la classe 'active' à l'élément de liste sélectionné dans EmberJS

J'ai une liste et je voudrais définir un élément comme class="active" automatiquement. Étant donné le code bootstrap suivant:

<ul class="nav">
<li {{bindAttr class="atIndex:active"}}>{{#linkTo "index"}}Index{{/linkTo}}</li>
<li {{bindAttr class="atAbout:active"}}>{{#linkTo "about"}}About{{/linkTo}}</li>
<li {{bindAttr class="atLogin:active"}}>{{#linkTo "login"}}Login{{/linkTo}}</li>
</ul>

AtIndex, atAbout et atLogin résident dans mon ApplicationController.

Pour afficher comme:

<ul class="nav">
<li class="active"><a...>Index{{/linkTo}}</li>
<li><a...>About<a></li>
<li><a...>Login<a></li>
</ul>

Quelle est la meilleure façon de le faire avec Ember 1.0 pre4? Je préfère ne pas ajouter de code spécial à chaque vue ou contrôleur.

PS - atIndex: true fonctionne, mais atIndex: function() {return true; }.property().volatile() ne l'est pas. Ce qui me fait penser que je fais quelque chose de mal.

Merci!

40
demandé sur shs 2013-01-19 11:18:32

12 réponses

{{#link-to "dashboard" tagName="li" href=false}}
  <a {{bind-attr href="view.href"}}>
    Dashboard
  </a>
{{/link-to}}
75
répondu lesyk 2014-12-12 22:31:01

De loin le moyen le plus propre de résoudre ce problème est de tirer parti de la prise en charge intégrée de linkTo helper pour définir la classe active lors du rendu des liens. AFAIK ceci n'est pas encore documenté autre que dans le code source:

Mise en Œuvre: https://github.com/emberjs/ember.js/blob/master/packages/ember-routing/lib/helpers/link_to.js#L46

Exemple: https://github.com/emberjs/ember.js/blob/master/packages/ember/tests/helpers/link_to_test.js#L120

Pour profiter de cette fonctionnalité, ajustez simplement votre css au style en fonction d'une classe active sur le lien au lieu de l'élément li. Si vous avez vraiment besoin de styliser le li, Vous pouvez créer une vue personnalisée et une aide qui étend Ember.LinkView et utilise un li mais changer de css sera beaucoup plus facile.

- - - Mise à jour - - - -

, Puisque nous aimons tous twitter bootstrap juste changer le css est peut-être pas une bonne option. Dans ce cas, ce qui suit fera le astuce:

App.ApplicationView = Ember.View.extend({
  currentPathDidChange: function() {
    Ember.run.next( this, function() {
      this.$("ul.nav li:has(>a.active)").addClass('active');
      this.$("ul.nav li:not(:has(>a.active))").removeClass('active');
    });
  }.observes('controller.currentPath')
});

Exemple de travail utilisant ember linkTo helper avec Bootstrap pills: http://jsbin.com/ekobod/5/edit (nécessite ember-1.0.0-pre.4)

14
répondu Mike Grassotti 2013-01-23 03:19:47

Le chemin de l'itinéraire actif est mis à jour automatiquement dans le ApplicationController via currentPath donc j'ai fait quelque chose comme ça dans mon application... Dans ApplicationController ajouté des propriétés comme ceci:

isProductsActive: function(){
  if ( this.get('currentPath') === 'products' ) return 'active';
  else return '';
}.property('currentPath')

Et dans mon modèle ApplicationView:

<li {{bindAttr class="isProductsActive"}}>
  {{#linkTo "products"}}Products{{/linkTo}}
</li>
5
répondu colymba 2013-01-19 16:22:54

J'ai fait un addon ember-cli qui gère ceci:

Https://github.com/alexspeller/ember-cli-active-link-wrapper

5
répondu alexspeller 2015-03-18 20:37:17

Modifier : Enfin, la meilleure façon que j'ai trouvée d'utiliser la classe activate de l'élément Bootstrap li En utilisant ember.js du lien.

{{#linkTo "dives" tagName="li"}}
   <a {{bindAttr href="view.href"}}>Dives</a>
{{/linkTo}}

--------------8

Je n'ai pas le choix.]}

Je suppose que les réponses précédentes étaient pertinentes avant Ember.js a introduit l'attribut activeClass pour linkTo helper. Maintenant, je résoudrais le problème comme ceci:

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

Enber ajoutera automatiquement la classe lorsque cela est pertinent.

3
répondu user11012 2014-07-29 13:10:29

Si je peux suggérer une autre solution qui ne nécessite que des guidons:

<li {{bind-attr class="view.innerLink.active:active"}}>
    {{#link-to "path" viewName="innerLink"}}Click{{/link-to}}
</li>

Cela définit l'objet LinkView en tant que membre de la vue parent, qui est l'attribut actif que vous pouvez ensuite référencer.

2
répondu Elte Hupkes 2014-04-18 11:39:38

J'ai trouvé une Solution assez simple en utilisant des éléments liés dans un groupe de liste ( http://getbootstrap.com/components/#list-group-linked).

<div class="list-group">
{{#each thing in list}}
    {{#link-to "details" thing.id tagName="a" href="view.href" class="list-group-item" {{thing.name}} {{/link-to}}
{{/each}}
</div>

Fonctionne avec Bootstrap v3.1.1 et Ember v1.7. 0

2
répondu Karda 2014-09-16 15:14:27

Imbriquez simplement le {{link-to}} Avec un tagName sur l'extérieur. Je fais cela sur EmberJS 2.0.

{{#link-to "admin.websocket" tagName="li"}}
    {{#link-to "admin.websocket"}}WebSocket{{/link-to}}
{{/link-to}}
2
répondu Chris Carey 2015-08-17 15:57:26

Si vous voulez utiliser la navigation Bootstrap dans Ember, vous pouvez utiliser Bootstrap pour Ember qui a un support prêt à l'emploi pour ceci:

Github: https://github.com/ember-addons/bootstrap-for-ember Démo: http://ember-addons.github.io/bootstrap-for-ember/dist/#/show_components/tabs

1
répondu asaf000 2013-08-29 15:31:21

Beaucoup de ces réponses sont obsolètes. Voici une version beaucoup plus propre (et sèche) pour Bootstrap et Ember 2.x:

{{#link-to "index" tagName="li" as |link|}}
  <a href="#" class="{{if link.active 'active'}}">Index Page</a>
{{/link-to}}
1
répondu Sukima 2016-04-07 12:06:50

J'ai résolu un problème similaire en créant une vue pour chaque élément et en utilisant classNameBindings (je dois dire que je n'ai pas de liste HTML, c'est-à-dire<a>...</a> dans mon application, juste la liste de <div>).

Voici la façon dont cela fonctionne pour moi:

Dans la liste des tâches.guidon j'itère sur ma vue personnalisée

  {{#each tasks}}
    {{view App.TaskListItemView contentBinding="this"....}}
  {{/each}}

Ember insérera une vue (c'est-à-dire <div>) pour chaque élément.

La classe view pour chaque élément est définie dans task_list_item_view.js comme

App.TaskListItemView = Ember.View.extend({

  controller: null,
  classNameBindings: ['isSelected', 'isClosed'],

  isClosed: function() {
      var content = this.get('content');
      return content && !content.isOpen(new Date);
  }.property('controller.content.@each'),

  isSelected: function() {
      return (this.get('controller').isSelectedTask(this.get('content')));
  }.property('controller.taskSelection.@each'),

  ....
});

Enfin, le modèle pour la vue rend juste mon lien dans tasklistitem.guidon

<a {{action "selectTask" view.content target="view"}} rel="tooltip"
         {{bindAttr title="view.content.comment"}} class="taskListLink">
  ....
</a>

AFAIK vous devez spécifier les données source dans l'appel property() pour indiquer à ember quand (ré) évaluer la propriété.

J'espère que cela aide

0
répondu Thomas Herrmann 2013-01-19 11:39:44

, je suis allé avec:

 Ember.LinkView.reopen({
didInsertElement:function(){

    if(this.$().hasClass('active')){

        this.$().parent().addClass('active');

    }
}

});

Je ne voulais pas utiliser la réponse acceptée car je voulais garder mes éléments li comme un vieux html. Il pourrait y avoir un meilleur moyen de vérifier l'état actif, mais je n'ai pas pu accéder à la bonne propriété.

-1
répondu henryallsuch 2015-01-07 21:31:34