Eu tenho rotas definidas no AngularJS assim:
$routeProvider
.when('/dashboard', {templateUrl:'partials/dashboard', controller:widgetsController})
.when('/lab', {templateUrl:'partials/lab', controller:widgetsController})
Eu tenho alguns links na barra superior denominados guias. Como posso adicionar a classe 'ativa' a uma guia, dependendo do modelo ou URL atual?
javascript
html
angularjs
Sergei Basharov
fonte
fonte
Respostas:
Uma maneira de resolver isso sem precisar confiar em URLs é adicionar um atributo personalizado a cada parcial durante a
$routeProvider
configuração, como este:Exponha
$route
em seu controlador:Defina a
active
classe com base na guia ativa atual:fonte
$scope.activeTab = $route.current.activetab
para que você possa manter o html um pouco mais limpo.$rootScope
truque de @ Lucas abaixo para disponibilizá-lo em todos os escopos.Uma maneira de fazer isso seria usar a diretiva ngClass e o serviço $ location. No seu modelo, você pode fazer:
onde
isActive
seria uma função em um escopo definido assim:Aqui está o jsFiddle completo: http://jsfiddle.net/pkozlowski_opensource/KzAfG/
Repetir
ng-class="{active:isActive('/dashboard')}"
em cada guia de navegação pode ser entediante (se você tiver muitas guias); portanto, essa lógica pode ser candidata a uma diretiva muito simples.fonte
Seguindo o conselho de Pavel de usar uma diretiva personalizada, aqui está uma versão que exige a adição de carga útil ao routeConfig, é super declarativa e pode ser adaptada para reagir a qualquer nível do caminho, simplesmente alterando a qual
slice()
você está prestando atenção. .Estamos alcançando nossos objetivos ouvindo o
$routeChangeSuccess
evento, em vez de colocar um$watch
no caminho. Trabalho sob a crença de que isso significa que a lógica deve ser executada com menos frequência, pois acho que assiste a tiros em cada$digest
ciclo.Chame-o passando seu argumento no nível do caminho na declaração da diretiva. Isso especifica em qual parte do $ location.path () atual você deseja comparar seu
href
atributo.Portanto, se suas guias reagirem ao nível base do caminho, defina o argumento '1'. Portanto, quando location.path () for "/ home", ele corresponderá ao "# / home" no diretório
href
. Se você tiver guias que devem reagir ao segundo nível, terceiro ou 11º do caminho, ajuste de acordo. Esse corte de 1 ou superior ignorará o nefasto '#' no href, que permanecerá no índice 0.O único requisito é que você invoque um
<a>
, pois o elemento está assumindo a presença de umhref
atributo, que será comparado ao caminho atual. No entanto, você pode se adaptar com bastante facilidade para ler / gravar um elemento pai ou filho, se preferir chamar o<li>
ou algo assim. Eu entendo isso porque você pode reutilizá-lo em muitos contextos, simplesmente variando o argumento pathLevel. Se a profundidade da leitura fosse assumida na lógica, você precisaria de várias versões da diretiva para usar com várias partes da navegação.EDIT 18/3/14: A solução foi generalizada de maneira inadequada e seria ativada se você definisse um argumento para o valor de 'activeTab' que retornava com
undefined
relação a ambos$location.path()
e ao elementohref
. Porque:undefined === undefined
. Atualizado para corrigir essa condição.Enquanto trabalhava nisso, percebi que deveria haver uma versão que você pode declarar em um elemento pai, com uma estrutura de modelo como esta:
Observe que esta versão não se parece mais remotamente com o HTML no estilo Bootstrap. Mas, é mais moderno e usa menos elementos, por isso sou parcial. Esta versão da diretiva, além da original, agora está disponível no Github como um módulo suspenso que você pode declarar apenas como uma dependência. Eu ficaria feliz em melhorá-los, se alguém realmente os usar.
Além disso, se você quiser uma versão compatível com o bootstrap que inclua
<li>
's', poderá usar o módulo Tabs angular-ui-bootstrap , que eu acho que saiu após este post original, e que talvez seja ainda mais declarativo do que este. É menos conciso para coisas básicas, mas fornece algumas opções adicionais, como guias desabilitadas e eventos declarativos que são acionados ao ativar e desativar.fonte
ul
's' e talvez devam ser apenas coleções de âncoras, envolvidas por umnav
ou outro elemento de agrupamento. Lidar com a camada intermediária deli
s é uma complexidade adicional sem retorno, principalmente agora que temos onav
elemento à nossa disposição para deixar claro o que está acontecendo.@ rob-juurlink Melhorei um pouco sua solução:
em vez de cada rota precisar de uma guia ativa; e precisando definir a guia ativa em cada controlador eu faço isso:
E o HTML fica assim. O activetab é apenas o URL relacionado a essa rota. Isso apenas elimina a necessidade de adicionar código em cada controlador (arrastar dependências como $ route e $ rootScope se esse for o único motivo pelo qual eles são usados)
fonte
Talvez uma diretiva como essa possa resolver o seu problema: http://jsfiddle.net/p3ZMR/4/
HTML
JS
fonte
Solução mais simples aqui:
Como definir a classe ativa bootstrap navbar com o Angular JS?
Qual é:
Use o ng-controller para executar um único controlador fora da ng-view:
e inclua no controllers.js:
fonte
Eu recomendo usar o módulo state.ui, que não apenas oferece suporte a visualizações múltiplas e aninhadas, mas também facilita esse tipo de trabalho (código abaixo citado):
Vale a pena ler.
fonte
Aqui está outra versão da mudança de LI do XMLillies com domi que usa uma cadeia de pesquisa em vez de um nível de caminho. Eu acho que isso é um pouco mais óbvio do que está acontecendo no meu caso de uso.
O HTML agora se parece com:
fonte
Achei a resposta do XMLilley a melhor e mais adaptável e não intrusiva.
No entanto, eu tive uma pequena falha.
Para uso com o bootstrap nav, aqui está como eu o modifiquei:
Eu adicionei "if (attrs.href! = Undefined)" porque essa função é chamada adequadamente duas vezes, a segunda vez produzindo um erro.
Quanto ao html:
fonte
Exemplo de inicialização.
Se você estiver usando o Angulars built in routing (ngview), esta diretiva poderá ser usada:
Supondo que sua marcação tenha a seguinte aparência:
Eu gosto disso, pois você pode definir o nome da classe que deseja em seu atributo.
fonte
Você também pode simplesmente injetar o local no escopo e usá-lo para deduzir o estilo da navegação:
Em seguida, use-o no seu
ng-class
:fonte
uma maneira alternativa é usar ui-sref-active
Uma diretiva trabalhando ao lado de ui-sref para adicionar classes a um elemento quando o estado da diretiva relacionada ui-sref estiver ativo e removendo-as quando estiver inativo. O principal caso de uso é simplificar a aparência especial dos menus de navegação baseados em ui-sref, fazendo com que o botão de menu do estado "ativo" apareça diferente, distinguindo-o dos itens de menu inativos.
Uso:
ui-sref-active = 'class1 classe2 classe3' - as classes "class1", "class2" e "class3" são adicionadas ao elemento diretivo quando o estado do ui-sref relacionado está ativo e removido quando está inativo.
Exemplo:
dado o seguinte modelo,
quando o estado do aplicativo é "app.user" e contém o parâmetro de estado "user" com o valor "bilbobaggins", o HTML resultante aparecerá como
O nome da classe é interpolado uma vez durante o tempo do link das diretivas (quaisquer alterações adicionais no valor interpolado são ignoradas). Várias classes podem ser especificadas em um formato separado por espaço.
Use a diretiva ui-sref-opts para passar opções para $ state.go (). Exemplo:
fonte
Eu concordo com o post de Rob sobre ter um atributo personalizado no controlador. Aparentemente, não tenho representante suficiente para comentar. Aqui está o jsfiddle que foi solicitado:
amostra html
exemplo app.js
http://jsfiddle.net/HrdR6/
fonte
E use o abaixo no modelo:
fonte
Eu precisava de uma solução que não exigisse alterações nos controladores, porque em algumas páginas renderizamos apenas modelos e não há nenhum controlador. Graças a comentaristas anteriores que sugeriram o uso,
$routeChangeSuccess
eu vim com algo assim:Não depende de URLs e, portanto, é muito fácil configurá-lo para qualquer sub-página etc.
fonte
Não me lembro onde encontrei esse método, mas é bem simples e funciona bem.
HTML:
CSS:
fonte
Se você estiver usando o ngRoute (para roteamento), seu aplicativo terá uma configuração abaixo,
Agora, basta adicionar um controlador nessa configuração, como abaixo,
Como você mencionou a guia ativa na sua configuração, agora você só precisa adicionar a classe ativa na sua tag
<li>
ou<a>
. Gostar,O que significa que, sempre que o usuário clicar na página, isso identificará automaticamente a guia atual e aplicará a classe css ativa.
Eu espero que isso ajude!
fonte
Vim aqui para a solução .. embora as soluções acima estejam funcionando bem, mas as consideram um pouco complexas e desnecessárias. Para as pessoas que ainda procuram uma solução fácil e organizada, a tarefa será executada perfeitamente.
fonte