Cómo preventDefault en las etiquetas de anclaje?


Digamos que tengo una etiqueta de anclaje como

<a href="#" ng-click="do()">Click</a>

¿Cómo puedo evitar que el navegador navegue a # in AngularJS ?

Author: Damjan Pavlica, 2012-06-07

26 answers

ACTUALIZACIÓN: Desde entonces he cambiado de opinión sobre esta solución. Después de más desarrollo y tiempo dedicado a trabajar en esto, creo que una mejor solución a este problema es hacer lo siguiente:

<a ng-click="myFunction()">Click Here</a>

Y luego actualiza tu css para tener una regla adicional:

a[ng-click]{
    cursor: pointer;
}

Es mucho más simple y proporciona exactamente la misma funcionalidad y es mucho más eficiente. Espero que pueda ser útil para cualquier otra persona que busque esta solución en el futuro.


Las la siguiente es mi solución anterior, que dejo aquí solo para propósitos heredados:

Si está teniendo este problema mucho, una directiva simple que solucionaría este problema es la siguiente:

app.directive('a', function() {
    return {
        restrict: 'E',
        link: function(scope, elem, attrs) {
            if(attrs.ngClick || attrs.href === '' || attrs.href === '#'){
                elem.on('click', function(e){
                    e.preventDefault();
                });
            }
        }
   };
});

Comprueba todas las etiquetas de anclaje (<a></a>) para ver si su atributo href es una cadena vacía ("") o un hash ('#') o si hay una asignación ng-click. Si encuentra alguna de estas condiciones, captura el evento y evita el comportamiento predeterminado.

El único down lado es que ejecuta esta directiva para todas las etiquetas de anclaje. Por lo tanto, si tiene muchas etiquetas de anclaje en la página y solo desea evitar el comportamiento predeterminado para un pequeño número de ellas, esta directiva no es muy eficiente. Sin embargo, casi siempre quiero preventDefault, así que uso esta directiva en todas partes en mis aplicaciones AngularJS.

 252
Author: tennisgent,
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-02-26 15:06:43

De acuerdo con los documentos para ngHref debería ser capaz de dejar el href o hacer href="".

<input ng-model="value" /><br />
<a id="link-1" href ng-click="value = 1">link 1</a> (link, don't reload)<br />
<a id="link-2" href="" ng-click="value = 2">link 2</a> (link, don't reload)<br />
<a id="link-4" href="" name="xx" ng-click="value = 4">anchor</a> (link, don't reload)<br />
<a id="link-5" name="xxx" ng-click="value = 5">anchor</a> (no link)<br />
 319
Author: Chris,
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-26 15:37:30

Puede pasar el objeto event event a su método, y llamar a $event.preventDefault() en él, para que el procesamiento predeterminado no se produzca:

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

// then in your controller.do($event) method
$event.preventDefault()
 231
Author: mna,
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-06-07 12:20:39

Prefiero usar directivas para este tipo de cosas. He aquí un ejemplo

<a href="#" ng-click="do()" eat-click>Click Me</a>

Y el código de directiva para eat-click:

module.directive('eatClick', function() {
    return function(scope, element, attrs) {
        $(element).click(function(event) {
            event.preventDefault();
        });
    }
})

Ahora puede agregar el atributo eat-click a cualquier elemento y obtendrá preventDefault()'ed automáticamente.

Beneficios:

  1. No tienes que pasar el objeto feo $event a tu función do().
  2. Su controlador es más comprobable por unidad porque no necesita extraer el objeto $event
 108
Author: djsmith,
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
2018-03-03 23:20:19

Aunque Renaud dio una gran solución

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

Personalmente encontré que también necesitas event evento.stopPropagation () en algunos casos para evitar algunos de los efectos secundarios

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

Será mi solución

 53
Author: zainengineer,
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-05-26 19:18:30
ng-click="$event.preventDefault()"
 33
Author: The Whiz of Oz,
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-06-26 19:48:34

La solución más fácil que he encontrado es esta:

<a href="#" ng-click="do(); $event.preventDefault()">Click</a>
 33
Author: Clément Renaud,
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-11-01 17:46:25

Así que leyendo estas respuestas, @Chris todavía tiene la respuesta más "correcta", supongo, pero tiene un problema, no muestra el "puntero"....

Así que aquí hay dos maneras de resolver este problema sin necesidad de agregar un cursor: estilo de puntero:

  1. Use javascript:void(0) en lugar de #:

    <a href="javascript:void(0)" ng-click="doSomething()">Do Something</a>
    
  2. Use $event.preventDefault() en la directiva ng-click (para que no deseche su controlador con referencias relacionadas con el DOM):

    <a href="#dontGoHere" ng-click="doSomething(); $event.preventDefault()">Do Something</a>
    

Personalmente prefiero el el primero sobre el segundo. javascript:void(0)tiene otros beneficios que son discutidos aquí. También hay una discusión de "JavaScript discreto" en ese enlace que es terriblemente reciente, y no necesariamente se aplica directamente a una aplicación angular.

 10
Author: Ben Lesh,
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:02:45

Puedes hacer lo siguiente

1.Remove href attribute from anchor (a) tag

2.Establecer puntero cursor en css a ng click elements

 [ng-click],
 [data-ng-click],
 [x-ng-click] {
     cursor: pointer;
 }
 9
Author: Fizer Khan,
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-12-20 13:33:54

HTML

Aquí angularjs puro: cerca de la función ng-click puede escribir la función preventDefault() separando punto y coma

<a href="#" ng-click="do(); $event.preventDefault(); $event.stopPropagation();">Click me</a>

JS

$scope.do = function() {
    alert("do here anything..");
}

(o)

Puede proceder de esta manera, esto ya se discute aquí.

HTML

<a href="#" ng-click="do()">Click me</a>

JS

$scope.do = function(event) {
    event.preventDefault();
    event.stopPropagation()
}
 8
Author: vallepu veerendra kumar,
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-03-06 18:25:35

Pruebe esta opción que puedo ver que aún no está en la lista anterior:

<a href="" ng-click="do()">Click</a>
 6
Author: pollux1er,
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-11-03 14:09:10

Ya que está haciendo una aplicación web, ¿por qué necesita enlaces?

¡Cambia tus anclas por botones!

<button ng-click="do()"></button>
 5
Author: sidonaldson,
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-18 11:20:55

Si sigue siendo pertinente:

<a ng-click="unselect($event)" />

...

scope.unselect = function( event ) {
 event.preventDefault();
 event.stopPropagation();
}

...
 5
Author: xac,
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-05 16:42:59

Yo iría con:

<a ng-click="do()">Click</a>
  • porque de acuerdo con los documentos que debe ser capaz de salir de la href y luego Angular se encargará de prevenir por defecto para usted!

Todo esto prevenir por defecto ha sido confuso para mí, así que He creado un JSFiddle allí se ilustra cuándo y dónde Angular está previniendo el valor predeterminado .

El JSFiddle está usando la directiva a de Angular, por lo que debería ser EXACTAMENTE la misma. Puedes ver el código fuente aquí: a etiqueta código fuente

Espero que esto ayude a clarificar a algunos.

Me hubiera gustado publicar el documento en ngHref, pero no puedo debido a mi reputación.

 4
Author: martinmose,
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-01-15 07:57:03

Esto es lo que siempre hago. Funciona como un encanto!

<a href ng-click="do()">Click</a>
 4
Author: Catfish,
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-12-18 17:40:58

La forma más segura de evitar eventos en un href sería definirlo como

<a href="javascript:void(0)" ....>
 4
Author: Michael Drob,
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-11-01 17:47:02

O si necesita en línea, puede hacer esto:

<a href="#" ng-click="show = !show; $event.preventDefault()">Click to show</a>
 3
Author: ntekka,
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-06-25 16:17:04

Muchas respuestas parecen ser exageradas. PARA MÍ, esto funciona

 <a ng-href="#" ng-click="$event.preventDefault();vm.questionContainer($index)">{{question.Verbiage}}</a>
 3
Author: Tom Stickel,
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-07-10 20:55:10

Necesito una presencia del valor del atributo href para la degradación (cuando js está desactivado), por lo que no puedo usar el atributo href vacío (o "#"), pero el código anterior no funcionó para mí, porque necesito una variable event (e). Creé mi propia directiva:

angular.module('MyApp').directive('clickPrevent', function() {
  return function(scope, element, attrs) {
    return element.on('click', function(e) {
      return e.preventDefault();
    });
  };
});

En HTML:

<a data-click-prevent="true" href="/users/sign_up" ng-click="openSignUpModal()">Sign up</a>
 1
Author: focused,
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-16 15:23:54

Tomando prestado de la respuesta de tennisgent. Me gusta que no tengas que crear una directiva personalizada para agregar todos los enlaces. Sin embargo, no pude conseguir su trabajo en IE8. Esto es lo que finalmente funcionó para mí (usando angular 1.0.6).

Observe que 'bind' le permite usar jqLite proporcionado por angular, por lo que no es necesario envolver con jQuery completo. También requiere el método stopPropogation.

.directive('a', [
    function() {
        return {
            restrict: 'E',
            link: function(scope, elem, attrs) {

                elem.bind('click', function(e){
                    if (attrs.ngClick || attrs.href === '' || attrs.href == '#'){
                        e.preventDefault();
                        e.stopPropagation();
                    }
                })
            }
        };
    }
])
 1
Author: Lukus,
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-19 22:31:25

Me encontré con este mismo problema al usar anclas para un desplegable de arranque angular. La única solución que encontré que evitó los efectos secundarios no deseados (es decir. el menú desplegable que no se cierra debido al uso de preventDefault()) era usar lo siguiente:

 <a href="javascript:;" ng-click="do()">Click</a>
 1
Author: cjackson,
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-11-19 20:42:06

Si nunca quieres ir a href... debes cambiar tu marcado y usar un botón, no una etiqueta de anclaje, porque semánticamente no es un anclaje o un enlace. Inversamente, si tiene un botón que hace algunas comprobaciones y luego redirige, debería ser una etiqueta de enlace / anclaje y no un botón... para fines de SEO, así como pruebas [insertar suite de prueba aquí].

Para enlaces que solo desea redirigir condicionalmente como solicitar que se guarden los cambios, o reconocer el estado sucio... usted debe utilizar ng-click= " someFunction (event event)" y en someFunction en su ValidationError preventDefault y / o stopPropagation.

También solo porque puedas no significa que debas. javascript: void (0) funcionó bien en su día... pero debido a los hackers / crackers nefastos navegadores bandera aplicaciones / sitios que utilizan javascript dentro de un href... ver ninguna razón para ducktype arriba..

Es 2016 desde 2010 no debe haber ninguna razón en cualquier lugar para utilizar enlaces que actúan como botones... si todavía tiene para apoyar IE8 y por debajo de lo que necesita para volver a evaluar su lugar de negocio.

 1
Author: PDA,
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-01-05 04:25:37
/* NG CLICK PREVENT DEFAULT */

app.directive('ngClick', function () {
    return {
        link: function (scope, element, attributes) {
            element.click(function (event) {
                event.preventDefault();
                event.stopPropagation();
            });
        }
    };
});
 0
Author: ,
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-03-31 21:30:04

Lo que debes hacer es omitir el atributo href por completo.

Si nos fijamos en el código fuente para la directiva elemento a (que es una parte del núcleo angular), dice en la línea 29 - 31:

if (!element.attr(href)) {
    event.preventDefault();
}

Lo que significa que Angular ya está resolviendo el problema de los enlaces sin un href. El único problema que todavía tiene es el problema css. Todavía puede aplicar el estilo de puntero a los anclajes que tienen ng-clicks, por ejemplo:

a[ng-click] {
    /* Styles for anchors without href but WITH ng-click */
    cursor: pointer;
}

Por lo tanto, incluso podría hacer que su sitio más accesible marcando enlaces reales con un estilo sutil y diferente a continuación, enlaces que realizan funciones.

Feliz codificación!

 0
Author: Justus Romijn,
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-04-13 11:58:29

Puede desactivar la redirección de url dentro del modo HTML5 de location location para lograr el objetivo. Puede definirlo dentro del controlador específico utilizado para la página. Algo como esto:

app.config(['$locationProvider', function ($locationProvider) {
    $locationProvider.html5Mode({
        enabled: true,
        rewriteLinks: false,
        requireBase: false
    });
}]);
 0
Author: Dash,
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-08-30 13:39:15

Una alternativa podría ser:

<span ng-click="do()">Click</span>
 -2
Author: Terence Bandoian,
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-05-10 21:11:32