javascript active link - Como definir a classe ativa bootstrap navbar com o Angular JS?




13 Answers

Uma maneira muito elegante é usar o ng-controller para rodar um único controlador fora da ng-view:

<div class="collapse navbar-collapse" ng-controller="HeaderController">
    <ul class="nav navbar-nav">
        <li ng-class="{ active: isActive('/')}"><a href="/">Home</a></li>
        <li ng-class="{ active: isActive('/dogs')}"><a href="/dogs">Dogs</a></li>
        <li ng-class="{ active: isActive('/cats')}"><a href="/cats">Cats</a></li>
    </ul>
</div>
<div ng-view></div>

e inclua em controllers.js:

function HeaderController($scope, $location) 
{ 
    $scope.isActive = function (viewLocation) { 
        return viewLocation === $location.path();
    };
}
routerlink routeractive

Se eu tiver uma barra de navegação no bootstrap com os itens

Home | About | Contact

Como faço para definir a classe ativa para cada item de menu quando eles estão ativos? Ou seja, como posso definir class="active" quando a rota angular está em

  1. #/ para casa
  2. #/about para a página sobre
  3. #/contact para a página de contato



Você pode dar uma olhada no AngularStrap , a diretiva navbar parece ser o que você está procurando:

https://github.com/mgcrea/angular-strap/blob/master/src/navbar/navbar.js

.directive('bsNavbar', function($location) {
  'use strict';

  return {
    restrict: 'A',
    link: function postLink(scope, element, attrs, controller) {
      // Watch for the $location
      scope.$watch(function() {
        return $location.path();
      }, function(newValue, oldValue) {

        $('li[data-match-route]', element).each(function(k, li) {
          var $li = angular.element(li),
            // data('match-rout') does not work with dynamic attributes
            pattern = $li.attr('data-match-route'),
            regexp = new RegExp('^' + pattern + '$', ['i']);

          if(regexp.test(newValue)) {
            $li.addClass('active');
          } else {
            $li.removeClass('active');
          }

        });
      });
    }
  };
});

Para usar esta diretiva:

  1. Faça o download do AngularStrap em http://mgcrea.github.io/angular-strap/

  2. Inclua o script em sua página após o bootstrap.js:
    <script src="lib/angular-strap.js"></script>

  3. Adicione as diretivas ao seu módulo:
    angular.module('myApp', ['$strap.directives'])

  4. Adicione a diretiva à sua barra de navegação:
    <div class="navbar" bs-navbar>

  5. Adicione expressões regulares em cada item de navegação:
    <li data-match-route="/about"><a href="#/about">About</a></li>




Se você estiver trabalhando com o roteador Angular, a diretiva RouterLinkActive poderá ser usada de maneira realmente elegante:

<ul class="navbar-nav">
  <li class="nav-item"><a class="nav-link" routerLink="home" routerLinkActive="active">Home</a></li>
  <li class="nav-item"><a class="nav-link" routerLink="gallery" routerLinkActive="active">Gallery</a></li>
  <li class="nav-item"><a class="nav-link" routerLink="pricing" routerLinkActive="active">Prices</a></li>
  <li class="nav-item"><a class="nav-link" routerLink="contact" routerLinkActive="active">Contact</a></li>
</ul>



Você pode realmente usar angular-ui-utils diretiva de ui-route angular-ui-utils :

<a ui-route ng-href="/">Home</a>
<a ui-route ng-href="/about">About</a>
<a ui-route ng-href="/contact">Contact</a>

ou:

Controlador de Cabeçalho

/**
 * Header controller
 */
angular.module('myApp')
  .controller('HeaderCtrl', function ($scope) {
    $scope.menuItems = [
      {
        name: 'Home',
        url:  '/',
        title: 'Go to homepage.'
      },
      {
        name:   'About',
        url:    '/about',
        title:  'Learn about the project.'
      },
      {
        name:   'Contact',
        url:    '/contact',
        title:  'Contact us.'
      }
    ];
  });

Página de índice

<!-- index.html: -->
<div class="header" ng-controller="HeaderCtrl">
  <ul class="nav navbar-nav navbar-right">
    <li ui-route="{{menuItem.url}}" ng-class="{active: $uiRoute}"
      ng-repeat="menuItem in menuItems">
      <a ng-href="#{{menuItem.url}}" title="{{menuItem.title}}">
        {{menuItem.name}}
      </a>
    </li>
  </ul>
</div>

Se você estiver usando ui-utils, talvez também esteja interessado em ui-router para gerenciar visualizações parciais / aninhadas.




Eu uso a diretiva ng-class com $ location para alcançá-lo.

<ul class="nav">
<li data-ng-class="{active: ($location.path() == '/') }">
    <a href="#/">Carpeta Amarilla</a>
</li>
<li class="dropdown" data-ng-class="{active: ($location.path() == '/auditoria' || $location.path() == '/auditoria/todos') }">
    <a class="dropdown-toggle" data-toggle="dropdown" href="#">
        Auditoria
        <b class="caret"></b>
    </a>
    <ul class="dropdown-menu pull-right">
        <li data-ng-class="{active: ($location.path() == '/auditoria') }">
            <a href="#/auditoria">Por Legajo</a>
        </li>
        <li data-ng-class="{active: ($location.path() == '/auditoria/todos') }">
            <a href="#/auditoria/todos">General</a>
        </li>
    </ul>
</li>
</ul>

Requer que a barra de navegação esteja dentro de um Controlador principal com acesso ao serviço $ location assim:

bajasApp.controller('MenuCntl', ['$scope','$route', '$routeParams', '$location', 
   function MenuCntl($scope, $route, $routeParams, $location) {
   $scope.$route = $route;
   $scope.$location = $location;
   $scope.$routeParams = $routeParams;
}]);



Se você usa o ui-router , o exemplo a seguir deve satisfazer suas necessidades com base no comentário do @ DanPantry sobre a resposta aceita sem adicionar nenhum código do lado do controlador:

<div class="collapse navbar-collapse" ng-controller="HeaderController">
    <ul class="nav navbar-nav">
        <li ui-sref-active="active"><a ui-sref="app.home()" href="/">Home</a></li>
        <li ui-sref-active="active"><a ui-sref="app.dogs()" href="/dogs">Dogs</a></li>
        <li ui-sref-active="active"><a ui-sref="app.cats()" href="/cats">Cats</a></li>
    </ul>
</div>
<div ng-view></div>

Você pode verificar os docs para mais informações sobre ele.




Aqui está minha opinião sobre isso. Um pouco de uma combinação de respostas encontradas neste post. Eu tive um caso um pouco diferente, então minha solução envolve separar o menu em seu próprio modelo para ser usado dentro do Ojbect de Definição da Diretiva, em seguida, adicionar minha barra de navegação à página que eu precisava. Basicamente, eu tinha uma página de login que eu não queria incluir meu menu, então usei ngInclude e insiro esta diretiva quando logado:

DIRETIVA:

module.directive('compModal', function(){


return {
    restrict: 'E',
    replace: true,
    transclude: true,
    scope: true,
    templateUrl: 'templates/menu.html',
    controller: function($scope, $element, $location){
        $scope.isActive = function(viewLocation){

            var active = false;

            if(viewLocation === $location.path()){
                active = true;
            }

            return active;

        }
    }
 }
});

MODELO DE DIRETIVA (templates / menu.html)

<ul class="nav navbar-nav">
  <li ng-class="{ active: isActive('/View1') }"><a href="#/View1">View 1</a></li>
  <li ng-class="{ active: isActive('/View2') }"><a href="#/View2">View 2</a></li>
  <li ng-class="{ active: isActive('/View3') }"><a href="#/View3">View 3</a></li>
</ul>

HTML QUE INCLUI A DIRECTIVA

<comp-navbar/>

Espero que isto ajude




Esta é uma solução simples

<ul class="nav navbar-nav navbar-right navbar-default menu">
  <li ng-class="menuIndice == 1 ? 'active':''">
    <a ng-click="menuIndice = 1" href="#/item1">item1</a>
  </li>
  <li ng-class="menuIndice == 2 ? 'active':''">
    <a ng-click="menuIndice = 2" href="#/item2">item2</a>
  </li>
  <li ng-class="menuIndice == 3 ? 'active':''">
    <a ng-click="menuIndice = 3" href="#/item3">item3</a>
  </li>
</ul>



JavaScript

/**
 * Main AngularJS Web Application
 */

var app = angular.module('yourWebApp', [
    'ngRoute'
]);


/**
 * Setup Main Menu
 */

app.controller('MainNavCtrl', [ '$scope', '$location', function ( $scope, $location) {
    $scope.menuItems = [
        {
            name: 'Home',
            url:  '/home',
            title: 'Welcome to our Website'
        },
        {
            name: 'ABOUT',
            url:  '/about',
            title: 'Know about our work culture'
        },
        {
            name:   'CONTACT',
            url:    '/contact',
            title:  'Get in touch with us'
        }
    ];

    $scope.isActive = function (viewLocation) {
        return viewLocation === $location.path();
    };
}]);

HTML

  <div class="navbar-collapse collapse" ng-controller="MainNavCtrl">
    <ul id="add-magic-line" class="nav navbar-nav navbar-right">
      <li data-ng-class="{current_page_item: isActive('{{ menuItem.url }}')}" data-ng-repeat="menuItem in menuItems">
        <a data-ng-href="#{{menuItem.url}}" title="{{menuItem.title}}">
          {{menuItem.name}}
        </a>
      </li>
    </ul>
  </div>



Use um objeto como uma variável de switch.
Você pode fazer isso inline simplesmente com:

<ul class="nav navbar-nav">
   <li ng-class="{'active':switch.linkOne}" ng-click="switch = {linkOne: true}"><a href="/">Link One</a></li>
   <li ng-class="{'active':switch.linkTwo}" ng-click="switch = {link-two: true}"><a href="/link-two">Link Two</a></li>
</ul>

Cada vez que você clica em um link, o objeto switch é substituído por um novo objeto, no qual apenas a propriedade correta do objeto switch é verdadeira. As propriedades indefinidas serão avaliadas como falsas e, portanto, os elementos que dependem delas não terão a classe ativa designada.




Sugiro usar uma diretiva em um link. Here está o violino.

Mas não é perfeito ainda. Cuidado com os hashbangs;)

Aqui está o javascript para diretiva:

angular.module('link', []).
  directive('activeLink', ['$location', function(location) {
    return {
      restrict: 'A',
      link: function(scope, element, attrs, controller) {
        var clazz = attrs.activeLink;
        var path = attrs.href;
        path = path.substring(1); //hack because path does not return including hashbang
        scope.location = location;
        scope.$watch('location.path()', function(newPath) {
          if (path === newPath) {
            element.addClass(clazz);
          } else {
            element.removeClass(clazz);
          }
        });
      }
    };
  }]);

e aqui está como seria usado em html:

<div ng-app="link">
  <a href="#/one" active-link="active">One</a>
  <a href="#/two" active-link="active">One</a>
  <a href="#" active-link="active">home</a>
</div>

depois estilizando com css:

.active{ color:red; }



Isso fez o truque para mim:

  var domain = '{{ DOMAIN }}'; // www.example.com or dev.example.com
  var domain_index =  window.location.href.indexOf(domain);
  var long_app_name = window.location.href.slice(domain_index+domain.length+1); 
  // this turns http://www.example.com/whatever/whatever to whatever/whatever
  app_name = long_app_name.slice(0, long_app_name.indexOf('/')); 
  //now you are left off with just the first whatever which is usually your app name

então você usa jquery (trabalha com o angular também) para adicionar classe ativa

$('nav a[href*="' + app_name+'"]').closest('li').addClass('active');

e claro o css:

.active{background:red;}

isso funciona se você tiver o seu html assim:

<ul><li><a href="/ee">ee</a></li><li><a href="/dd">dd</a></li></ul>

isso irá adicionar atemicamente a classe ativa usando o URL da página e colorir seu plano de fundo para vermelho se o seu em www.somesite.com/ee thaen ee for o 'app' e ele estará ativo




Aqui está outra solução para qualquer pessoa que possa estar interessada. A vantagem disso é que tem menos dependências. Heck, funciona sem um servidor web também. Então é completamente do lado do cliente.

HTML:

<nav class="navbar navbar-inverse" ng-controller="topNavBarCtrl"">
<div class="container-fluid">
    <div class="navbar-header">
        <a class="navbar-brand" href="#"><span class="glyphicon glyphicon-home" aria-hidden="true"></span></a>
    </div>
    <ul class="nav navbar-nav">
        <li ng-click="selectTab()" ng-class="getTabClass()"><a href="#">Home</a></li>
        <li ng-repeat="tab in tabs" ng-click="selectTab(tab)" ng-class="getTabClass(tab)"><a href="#">{{ tab }}</a></li>
    </ul>
</div>

Explicação:

Aqui estamos gerando os links dinamicamente a partir de um modelo angular usando a diretiva ng-repeat . A mágica acontece com os métodos selectTab() e getTabClass() definidos no controlador para esta barra de navegação apresentados abaixo.

Controlador:

angular.module("app.NavigationControllersModule", [])

// Constant named 'activeTab' holding the value 'active'. We will use this to set the class name of the <li> element that is selected.
.constant("activeTab", "active")

.controller("topNavBarCtrl", function($scope, activeTab){
    // Model used for the ng-repeat directive in the template.
    $scope.tabs = ["Page 1", "Page 2", "Page 3"];

    var selectedTab = null;

    // Sets the selectedTab.
    $scope.selectTab = function(newTab){
       selectedTab = newTab;
    };

    // Sets class of the selectedTab to 'active'.
    $scope.getTabClass = function(tab){
       return selectedTab == tab ? activeTab : "";
    };
});

Explicação:

selectTab() método selectTab() é chamado usando ng-click diretiva ng-click . Portanto, quando o link é clicado, a variável selectedTab é definida como o nome desse link. No HTML, você pode ver que esse método é chamado sem nenhum argumento para a guia Início, para que ele seja destacado quando a página for carregada.

O método getTabClass() é chamado pela diretiva ng-class no HTML. Este método verifica se a guia em que está é igual ao valor da variável selectedTab . Se verdadeiro, retorna "ativo" senão retorna "" que é aplicado como o nome da classe pela diretiva ng-class . Então, qualquer css aplicado à turma active será aplicado à guia selecionada.




Related