emberjs - cómo marcar elemento de menú activo usando la infraestructura del router
Estoy tratando de crear pestañas de navegación (tomadas de 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>
La pestaña activa está marcada con class="active"
.
Hay un gran ejemplo de la barra de navegación estática y la función Router/Outlet en http://jsfiddle.net/schawaska/pfbva / , pero No puedo entender cómo crear una vista dinámica de barra de navegación / menú / pestaña.
Por lo que entiendo, es posible usar enlaces de clase en cada elemento del menú:
classNameBindings: ['isActive:active']
Pero ¿dónde está el lugar correcto para cambiar isActive atributos ?
15 answers
Si estás usando Ember > = 1.11, entonces https://stackoverflow.com/a/14501021/65542 abajo está la respuesta correcta.
Crearía un NavigationView
, véase http://jsfiddle.net/pangratz666/z8ssG/:
Manillar:
<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()
})
});
Y dentro de su ruta connectOutlets
tiene que configurar el elemento de navegación actual a través de router.set('navigationController.selected', 'home');
...
También eche un vistazo al repositorio ember-bootstrap, que envuelve esto y más características de Bootstrap inside Ember.js
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:47:12
Ember 1.11+:
{{#link-to "dashboard" tagName="li"}}
<a href="{{view.href}}">Dashboard</a>
{{/link-to}}
Ember bind-attr requerido):
{{#link-to "dashboard" tagName="li"}}
<a {{bind-attr href="view.href"}}>Dashboard</a>
{{/link-to}}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-24 16:50:59
Algunas de las sugerencias anteriores siguen siendo válidas para el caso bootstrap de twitter. También puedes probar algo como esto
{{#link-to 'dashboard' tagName='li'}}
{{#link-to 'dashboard'}}Link Title{{/link-to}}
{{/link-to}}
- El
link-to
conli
tagName aplica la clase activa al li - El interior
link-to
sería un elementoanchor
que le daOpen in New Tab
funcionalidad cuando se hace clic con el botón derecho
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-08 14:30:05
Recientemente un complemento Ember-cli vino disponible para hacer esto. Se llama ember-cli-active-link-wrapper.
Instalar: ember install ember-cli-active-link-wrapper
Puedes usarlo así:
{{#active-link}}
{{link-to "Index" "index"}}
{{/active-link}}
Que resulta en:
<li class='active'>
<a href="/" class='active'>Index</a>
</li>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-25 07:38:05
Sé que este es un post antiguo, pero aquí hay actualizaciones para Ember 2.4.0
Para crear enlaces puede escribir
{{#link-to 'photoGallery'}}
Great Hamster Photos
{{/link-to}}
O
{{link-to 'Great Hamster Photos' 'photoGallery'}}
Ember establecerá automáticamente la clase como activa cuando la ruta actual coincida con la ruta del enlace (en este ejemplo photoGallery
).
Si también desea controlar la clase 'active' en otras rutas, puede hacerlo configurando el atributo current-when
.
{{#link-to 'photoGallery' current-when='photoGallery photoPreview'}}
Great Hamster Photos
{{/link-to}}
Este enlace tendrá active
clase en ambos photoGallery
y photoPreview
ruta.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-02 10:41:01
Manillares
<ul class="nav">
<li>{{#linkTo "index"}}Index{{/linkTo}}</li>
<li>{{#linkTo "about"}}About{{/linkTo}}</li>
</ul>
Javascript
App.Router.map(function() {
this.route("about");
});
Agregará la clase activa automáticamente en función de la ruta. Nota: Se prueba usando ember-1.0.0-pre.4.js
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-16 12:51:09
También puedes cambiar el método isActive a algo como esto:
isActive: function() {
return App.getPath('router.currentState.path') === "root.firms";
}.property("App.router.currentState"),
O
isActive: function() {
return this.get('controller.target.currentState.path') === "root.firms";
}.property("controller.target.currentState"),
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-20 11:29:39
Veo que esta pregunta es bastante antigua, pero si actualizas Ember.js al RC3 puedes usar la propiedad tagName
, como:
{{#link-to messages tagName="li"}}Messages{{/link-to}}
Aquí está la API - http://emberjs.com/api/classes/Ember.LinkView.html
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-03 01:21:41
No estoy seguro de si es muy dinámico, pero trate de ver la solución en http://codebrief.com/2012/07/anatomy-of-an-ember-dot-js-app-part-i-redux-routing-and-outlets/ La idea principal es comprobar el estado de su aplicación
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')
})
Manillar:
<li class="home" {{bindAttr class="isHome:active"}}>
</li>
<li class="sections" {{bindAttr class="isSections:active"}}>
</li>
<li class="items" {{bindAttr class="isItems:active"}}>
</li>
Actualización: la solución de pangratz se ve más bonita
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-24 11:43:18
Aquí hay una solución de trabajo completa:
Vista:
App.NavView = Ember.View.extend({
tagName: 'li',
classNameBindings: ['active'],
active: function() {
return this.get('childViews.firstObject.active');
}.property()
});
Plantilla:
<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>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-14 21:20:04
Tarde o temprano desea cambiar el nombre de sus estados o lo que sea que tenga que pasar por el código Y la vista también, también agregar una función a la transiciónpara cada ruta no parece deseable. Mi enfoque es un poco más programático y modularizado:
# 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 (para twitter-bootstrap-estilo navs)
<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>
De esta manera, puedo crear y jugar con mis rutas en el enrutador, y mantener las definiciones de Navegación lado a lado:
# 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'
)
]
)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-27 19:18:04
La respuesta de Baijum anterior es mayormente correcta, sin embargo en las últimas versiones de Ember el "bind-attr" está en desuso. Aquí está la nueva forma de escribirlo:
{{#link-to "dashboard" tagName="li"}}
<a href="{{view.href}}">Dashboard</a>
{{/link-to}}
Como puedes ver, es aún más fácil y funciona como magia..
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-21 16:35:03
Comenzando con v0.8.0 ember-bootstrap soporta navs, incluyendo el manejo correcto del estado activo. Y que sin ningún tipo de hacks de enlace a/tagName:
{{#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}}
Véase http://kaliber5.github.io/ember-bootstrap/api/classes/Components.Nav.html
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-09 08:37:32
Muchas de las soluciones propuestas aquí no funcionan para ninguna versión reciente de Ember (por ejemplo, las vistas están obsoletas). Además, solo usar el ayudante link-to
no resolverá el problema, ya que bootstrap espera que la clase active
esté presente en el <li>
no en el <a>
!
Así que trataré de resumir las soluciones que de hecho funcionan a partir de ahora:
Use ember-cli-active-link-wrapper
El complemento proporciona un componente para este caso de uso especial:
<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>
Tomada de https://stackoverflow.com/a/29939821/5556104
Use ember-bootstrap
Ember-bootstrap proporciona muchos componentes que integran la funcionalidad de bootstrap en su aplicación ember, entre ellos los componentes nav:
{{#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}}
Tomado de https://stackoverflow.com/a/38279975/5556104
Enlace-para hackear
Algo hacky, pero debería funcionar sin ningún complemento adicional:
<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>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:18:07
Como otras personas dijeron, usando {{#link-to}}
para enlazar a un route
existente, cuando esa ruta es URL actual, {{#link-to}}
agregará automáticamente active
a sus clases CSS.
Véase Ember issue 4387
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-31 19:55:11