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!
12 réponses
{{#link-to "dashboard" tagName="li" href=false}}
<a {{bind-attr href="view.href"}}>
Dashboard
</a>
{{/link-to}}
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)
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>
J'ai fait un addon ember-cli qui gère ceci:
Https://github.com/alexspeller/ember-cli-active-link-wrapper
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: Enber ajoutera automatiquement la classe lorsque cela est pertinent.<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>
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.
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
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}}
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
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}}
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
, 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é.