href substitui ng-click em Angular.js


118

Quando ambos, os atributos href e ng-click são definidos:

<a href="#" ng-click="logout()">Sign out</a>

o hrefatributo tem precedência sobre o clique do ng.

Estou procurando uma maneira de aumentar a prioridade do ng-click.

href é necessário para o Twitter Bootstrap, não consigo removê-lo.


Você poderia explicar "href é necessário para o Twitter Bootstrap"? Qual parte disso? CSS ou JavaScript?
pkozlowski.opensource

O "widget" de navegação do Twitter Bootstrap está configurado para usar links; se você adicionar um botão a ele, mesmo um que tenha o estilo de um link, ele quebra o estilo da navegação. Provavelmente não é HTML semântico, mas a solução de @sketfemme faz o que eu (e provavelmente Paul) queremos fazer.
BenCr

Ignore tudo que eu disse, navbar funciona perfeitamente com botões se você usar o HTML e as classes corretas. getbootstrap.com/components/#navbar
BenCr

Você deve aceitar a resposta de Mithu, que é usar um URL vazio
Peter Morris

1
@Paul O autor da postagem original perguntou como fazer um <a href> não navegar. A resposta aceita diz para mudar para um botão. Embora funcione, não é a solução para o problema, especialmente se, como eu, você é forçado a usar <a href> porque é um menu de bootstrap ou algo assim. A solução correta para esta questão específica é usar um url vazio <a href="" ng-click="whatever()"> Sair </a> - eu testei e posso confirmar se funciona. Felizmente, outra pessoa deu a resposta correta ou eu ainda estaria preso.
Peter Morris

Respostas:


35

Você provavelmente deve usar apenas uma tag de botão se não precisar de um uri.


Sim, se você puder explicar como o Twitter Bootstrap requer isso, talvez eu possa ajudar mais.
Geoff

Como isso funciona com os mecanismos de pesquisa? Estou usando o roteamento AngularJS e preciso manter o estado em um serviço, portanto, para todos os meus links de aplicativos internos, uso $ location, mas a remoção de href torna impossível para os mecanismos de pesquisa acompanharem o site.
Darrrrrren

2
os botões não podem ter outro elemento dentro deles, portanto, para estilização, você não gostaria de fazer isso - se precisar de coisas dentro deles.
sheriffderek de

246

Este exemplo do site de documentação angular simplesmente funciona, hrefmesmo sem atribuí-lo a uma string vazia:

[<a href ng-click="colors.splice($index, 1)">X</a>]

http://docs.angularjs.org/api/ng.directive:select


3
Quando tento fazer isso, todos os links parecem ter sido visitados, o que não é o comportamento que procuro. A outra forma ( href="#") causa o recarregamento da página, o que também está errado.
Rhys van der Waerden

4
Isso faz com que o IE9 não mostre um cursor de mão. Usar href=""resolve isso.
Juampy NR

1
@juampy, a transferência do link pode ser feita com CSS. Essa resposta dada é a maneira oficial do AngularJS de fazer isso.
entãoetimp

O # será tratado como um link hash.
sheriffderek,

3
<a href="javscript:void(0)" ng-click="logout()">Sign out</a>irá atendê-lo bem também
Marios Fakiolas

88

Você pode simplesmente evitar o comportamento padrão do evento de clique diretamente no seu modelo.

<a href="#" ng-click="$event.preventDefault();logout()" />

Pela documentação angular ,

Diretivas como ngClick e ngFocus expõem um objeto $ event dentro do escopo dessa expressão.


11
Esta é uma otima soluçao. Se você tiver um href, pode clicar com o botão direito para abri-lo em uma nova guia, mas com o clique esquerdo chama ng-click. Exatamente o que eu estava procurando
Tom Grant

Mais uma vez, uma excelente resposta. Ambos os cliques esquerdo e direito funcionam
Jay Jay Jay

Funcionou muito bem para permitir controles de carrossel Bootstrap sem acionar o roteamento. Obrigado!
Jason Maggard

Perfeito! Posso continuar com links e obter mais índice no Google e usar o ng-click para chamar Ajax. Obrigado.
Guilherme IA

Ótima solução, rápida e útil. Obrigado!
Josué Rocha

72

Aqui está outra solução:

<a href="" ng-click="logout()">Sign out</a>

ou seja, basta remover o # do atributo href


1
Para a pergunta feita, esta deve ser a solução. Também trabalhou no Angular 1.1.5
Sindre

18
Parece que <a href="" ng-click=""> impedirá o ng-click no navegador Android 2.3.x. Finalmente uso <a href="javascript:void(0)" ng-click="">
duckegg

1
A sugestão de Duckegg é a melhor
Jiří Vypědřík

26

Só mais uma dica. Se precisar de um URL real (para oferecer suporte à acessibilidade do navegador), você pode fazer o seguinte:

modelo:

<a ng-href="{{link}}" ng-click="$event.preventDefault(); linkClicked(link)">{{link}}</a>

diretiva:

$scope.linkClicked = function(link){
    // your code here
    $location.path(link);
};

Desta forma, seu código em linkClicked () terá a chance de ser executado antes de navegar para o link


Esta solução funciona e apenas altera o comportamento do clique esquerdo, o clique direito permanece intacto (menu de contexto), incluindo a possibilidade de um link em href. Portanto, essa é uma solução mais geral em comparação com TooMuchTenacious, que na verdade responde à pergunta de forma mais direta.
Exocom

21

Em Angular, <a>s são diretivas . Assim, se você tiver um vazio hrefou não href, o Angular ligará event.preventDefault.

Da fonte :

    element.on('click', function(event){
      // if we have no href url, then don't navigate anywhere.
      if (!element.attr(href)) {
        event.preventDefault();
      }
    });

Aqui está um plnkr demonstrando o hrefcenário ausente .


13

Isso funcionou para mim no IE 9 e no AngularJS v1.0.7:

<a href="javascript:void(0)" ng-click="logout()">Logout</a>

Obrigado ao comentário de duckeggs para a solução de trabalho!


Funciona, o link não altera o seu url e não está marcado como visitado. Melhor resposta!
Jim109

10

Existem tantas respostas para esta pergunta aqui, mas parece que há um pouco de confusão sobre o que realmente está acontecendo aqui.

Em primeiro lugar, sua premissa

"href substitui ng-click em Angular.js"

está errado. O que está realmente acontecendo é que, após o seu clique, o evento de clique é primeiro tratado pelo angular (definido pela ng-clickdiretiva no angular 1.x e clickno angular 2.x +) e então continua a se propagar (o que eventualmente aciona o navegador para navegar até o url definido com hrefatributo). (Veja isto para mais informações sobre propagação de eventos em javascript)

Se você quiser evitar isso, deverá cancelar a propagação do evento usando o método da interface The EventpreventDefault() :

<a href="#" ng-click="$event.preventDefault();logout()" />

(Esta é pura funcionalidade de javascript e nada a ver com angular)

Agora, isso já resolverá seu problema, mas não é a solução ideal. Angular, com razão, promove o padrão MVC . Com esta solução, seu template html é misturado com a lógica javascript. Você deve tentar evitar isso tanto quanto possível e colocar sua lógica em seu controlador angular. Então, a melhor maneira seria

<a href="#" ng-click="logout($event)" />

E em seu método logout ():

logout($event) {
   $event.preventDefault();
   ...
}

Agora o evento click não alcançará o navegador, portanto não tentará carregar o link apontado por href. (No entanto, observe que se o usuário clicar com o botão direito do mouse no link e abri-lo diretamente, não haverá nenhum evento de clique. Em vez disso, ele carregará diretamente o url apontado pelo hrefatributo.)

Em relação aos comentários sobre a cor do link visitado nos navegadores. Novamente, isso não tem nada a ver com angular, se você href="..."apontar para uma url visitada pelo seu navegador por padrão, a cor do link será diferente. Isso é controlado por CSS: visitado o seletor , você pode modificar seu css para substituir este comportamento:

a {
   color:pink;
}

PS1 :

Algumas respostas sugerem o uso:

<a href .../>

hrefé uma diretiva angular. Quando o seu modelo é processado pelo angular, ele será convertido para

<a href="" .../>

Essas duas maneiras são essencialmente as mesmas.


5

Basta escrever ng-click antes de href .. Funcionou para mim

<!DOCTYPE html>
<html>

  <head>
    <script data-require="angular.js@1.5.0" data-semver="1.5.0" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.js"></script>
    <script>
    angular.module("module",[])
.controller("controller",function($scope){
  
  $scope.func =function(){
    console.log("d");
  }
  
})</script>
  </head>

  <body ng-app="module" ng-controller="controller">
    <h1>Hello ..</h1>
    <a ng-click="func()" href="someplace.html">Take me there</a>
  </body>

</html>


2

Não acho que você precise remover "#" de href. Seguindo trabalhos com Angularjs 1.2.10

<a href="#/" ng-click="logout()">Logout</a>

1

Você também pode tentar isso:

<div ng-init="myVar = 'www.thesoftdesign'">
        <h1>Tutorials</h1>
        <p>Go to <a ng-href="{{myVar}}">{{myVar}}</a> to learn!</p>
</div>

0

Vou adicionar para você um exemplo que funciona para mim e você pode alterá-lo como quiser.

Eu adiciono o código abaixo dentro do meu controlador.

     $scope.showNumberFct = function(){
        alert("Work!!!!");
     }

e para minha página de visualização, adiciono o código abaixo.

<a  href="" ng-model="showNumber" ng-click="showNumberFct()" ng-init="showNumber = false" >Click Me!!!</a>

0

Você tentou redirecionar dentro da própria função de logout? Por exemplo, digamos que sua função de logout seja a seguinte

$scope.logout = function()
{
  $scope.userSession = undefined;
  window.location = "http://www.yoursite.com/#"
}

Então você pode apenas ter

<a ng-click="logout()">Sign out</a>

0

Por favor, checar isto

<a href="#" ng-click="logout(event)">Logout</a>

 $scope.logout = function(event)


 {
event.preventDefault();
alert("working..");
}

0
//for dynamic elements - if you want it in ng-repeat do below code

angular.forEach($scope.data, function(value, key) {
     //add new value to object
    value.new_url  = "your url";
});

 <div ng-repeat="row in data"><a ng-href="{{ row.url_content }}"></a></div>

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.