Tengo rutas establecidas en AngularJS como esta:
$routeProvider
.when('/dashboard', {templateUrl:'partials/dashboard', controller:widgetsController})
.when('/lab', {templateUrl:'partials/lab', controller:widgetsController})
Tengo algunos enlaces en la barra superior con el estilo de pestañas. ¿Cómo puedo agregar la clase 'activa' a una pestaña dependiendo de la plantilla o URL actual?
javascript
html
angularjs
Sergei Basharov
fuente
fuente
Respuestas:
Una forma de resolver esto sin tener que depender de las URL es agregar un atributo personalizado a cada parcial durante la
$routeProvider
configuración, de esta manera:Exponer
$route
en su controlador:Establezca la
active
clase en función de la pestaña activa actual:fuente
$scope.activeTab = $route.current.activetab
para que pueda mantener el html un poco más limpio.$rootScope
truco de @ Lucas a continuación para que esté disponible en todos los ámbitos.Una forma de hacerlo sería mediante el uso de la directiva ngClass y el servicio $ location. En su plantilla puede hacer:
donde
isActive
sería una función en un ámbito definido así:Aquí está el jsFiddle completo: http://jsfiddle.net/pkozlowski_opensource/KzAfG/
Repetir
ng-class="{active:isActive('/dashboard')}"
en cada pestaña de navegación puede ser tedioso (si tiene muchas pestañas), por lo que esta lógica podría ser un candidato para una directiva muy simple.fuente
Siguiendo el consejo de Pavel de usar una directiva personalizada, aquí hay una versión que requiere no agregar carga útil a routeConfig, es súper declarativa y puede adaptarse para reaccionar a cualquier nivel de la ruta, simplemente cambiando a cuál
slice()
de ellos le está prestando atención. .Estamos logrando nuestros objetivos al escuchar el
$routeChangeSuccess
evento, en lugar de colocar un$watch
en el camino. Trabajo bajo la creencia de que esto significa que la lógica debería ejecutarse con menos frecuencia, ya que creo que los relojes se disparan en cada$digest
ciclo.Invoque pasando su argumento de nivel de ruta en la declaración de directiva. Esto especifica con qué parte del $ location.path () actual con el que desea hacer coincidir su
href
atributo.Entonces, si sus pestañas deben reaccionar al nivel base de la ruta, haga el argumento '1'. Por lo tanto, cuando location.path () es "/ home", coincidirá con "# / home" en el
href
. Si tiene pestañas que deberían reaccionar al segundo nivel, al tercero o al undécimo del camino, ajústelo en consecuencia. Este corte de 1 o mayor evitará el nefasto '#' en el href, que vivirá en el índice 0.El único requisito es que invoque en un
<a>
, ya que el elemento está asumiendo la presencia de unhref
atributo, que se comparará con la ruta actual. Sin embargo, puede adaptarse con bastante facilidad para leer / escribir un elemento primario o secundario, si prefiere invocar en<li>
o algo. Excavo esto porque puedes reutilizarlo en muchos contextos simplemente variando el argumento pathLevel. Si la profundidad para leer se asumiera en la lógica, necesitaría múltiples versiones de la directiva para usar con múltiples partes de la navegación.EDITAR 18/03/14: La solución se generalizó de manera inadecuada y se activaría si definiera un argumento para el valor de 'activeTab' que se devolvió
undefined
contra ambos$location.path()
y el elementohref
. Debido a que:undefined === undefined
. Actualizado para corregir esa condición.Mientras trabajaba en eso, me di cuenta de que debería haber una versión que puede declarar en un elemento principal, con una estructura de plantilla como esta:
Tenga en cuenta que esta versión ya no se parece remotamente al HTML de estilo Bootstrap. Pero, es más moderno y usa menos elementos, así que soy parcial. Esta versión de la directiva, más el original, ahora están disponibles en Github como un módulo desplegable que puede declarar como una dependencia. Estaría encantado de darles energía, si alguien realmente los usa.
Además, si quieres una versión compatible con bootstrap que incluya la versión
<li>
's', puedes usar el módulo de pestañas angular-ui-bootstrap , que creo que salió después de esta publicación original, y que quizás sea aún más declarativo que este. Es menos conciso para cosas básicas, pero le proporciona algunas opciones adicionales, como pestañas deshabilitadas y eventos declarativos que se activan al activar y desactivar.fuente
ul
absoluto, y tal vez deberían ser solo colecciones de anclas, envueltas por unonav
u otro elemento de agrupación. Tratar con la capa intermedia deli
's es una complejidad añadida sin resultado, particularmente ahora que tenemos elnav
elemento a nuestra disposición para dejar en claro lo que está sucediendo.@ rob-juurlink He mejorado un poco tu solución:
en lugar de que cada ruta necesite una pestaña activa; y necesitando configurar la pestaña activa en cada controlador hago esto:
Y el HTML se ve así. La pestaña activa es solo la url que se relaciona con esa ruta. Esto simplemente elimina la necesidad de agregar código en cada controlador (arrastrando dependencias como $ route y $ rootScope si esta es la única razón por la que se usan)
fuente
Tal vez una directiva como esta podría resolver su problema: http://jsfiddle.net/p3ZMR/4/
HTML
JS
fuente
La solución más simple aquí:
¿Cómo configurar la clase activa bootstrap navbar con Angular JS?
Cual es:
Use ng-controller para ejecutar un solo controlador fuera de ng-view:
e incluir en controllers.js:
fuente
Recomiendo usar el módulo state.ui que no solo admite vistas múltiples y anidadas, sino que también hace que este tipo de trabajo sea muy fácil (se cita el siguiente código):
Vale la pena leer.
fuente
Aquí hay otra versión de XMLillies w / domi LI change que usa una cadena de búsqueda en lugar de un nivel de ruta. Creo que esto es un poco más obvio lo que está sucediendo para mi caso de uso.
HTML ahora se ve así:
fuente
Encontré la respuesta de XMLilley la mejor y más adaptable y no intrusiva.
Sin embargo, tuve un pequeño problema técnico.
Para usar con el navegador de arranque, así es como lo modifiqué:
Agregué "if (attrs.href! = Undefined)" porque esta función se llama dos veces, la segunda vez produce un error.
En cuanto al html:
fuente
Ejemplo de Bootstrap.
Si está utilizando enrutadores angulares integrados (ngview), esta directiva se puede utilizar:
Suponiendo que su marcado se vea así:
Me gusta que esto fuera así, ya que puedes establecer el nombre de la clase que deseas en tu atributo.
fuente
También puede simplemente inyectar la ubicación en el alcance y usarla para deducir el estilo para la navegación:
Luego úsalo en tu
ng-class
:fuente
una forma alternativa es usar ui-sref-active
Una directiva que trabaja junto con ui-sref para agregar clases a un elemento cuando el estado de la directiva ui-sref relacionada está activo, y eliminarlos cuando está inactivo. El caso de uso principal es simplificar la apariencia especial de los menús de navegación que dependen de ui-sref, haciendo que el botón de menú del estado "activo" aparezca diferente, distinguiéndolo de los elementos de menú inactivos.
Uso:
ui-sref-active = 'class1 class2 class3' - las clases "class1", "class2" y "class3" se agregan al elemento directivo cuando el estado del ui-sref relacionado está activo, y se eliminan cuando está inactivo.
Ejemplo:
dada la siguiente plantilla,
cuando el estado de la aplicación es "app.user" y contiene el parámetro de estado "usuario" con el valor "bilbobaggins", el HTML resultante aparecerá como
El nombre de la clase se interpola una vez durante el tiempo de enlace de las directivas (se ignoran los cambios adicionales al valor interpolado). Se pueden especificar varias clases en un formato separado por espacios.
Use la directiva ui-sref-opts para pasar opciones a $ state.go (). Ejemplo:
fuente
Estoy de acuerdo con la publicación de Rob sobre tener un atributo personalizado en el controlador. Aparentemente no tengo suficiente representante para comentar. Aquí está el jsfiddle que se solicitó:
html de muestra
app.js de muestra
http://jsfiddle.net/HrdR6/
fuente
Y use lo siguiente en la plantilla:
fuente
Necesitaba una solución que no requiera cambios en los controladores, porque para algunas páginas solo mostramos plantillas y no hay ningún controlador. Gracias a los comentaristas anteriores que sugirieron usar, se
$routeChangeSuccess
me ocurrió algo como esto:No depende de las URL y, por lo tanto, es muy fácil configurarlo para cualquier subpágina, etc.
fuente
No recuerdo dónde encontré este método, pero es bastante simple y funciona bien.
HTML:
CSS:
fuente
Si está utilizando ngRoute (para el enrutamiento), su aplicación tendrá la siguiente configuración,
Ahora, solo agregue un controlador en esta configuración como se muestra a continuación,
Como mencionó la pestaña activa en su configuración, ahora solo tiene que agregar la clase activa en su etiqueta
<li>
o<a>
. Me gusta,Lo que significa que cada vez que el usuario haga clic en la página Acerca de, esto identificará automáticamente la pestaña actual y aplicará la clase css activa.
¡Espero que esto ayude!
fuente
Vine aquí para la solución ... aunque las soluciones anteriores están funcionando bien pero las encontraron un poco complejas innecesarias. Para las personas que todavía buscan una solución fácil y ordenada, hará la tarea perfectamente.
fuente