Digamos que tengo una etiqueta de anclaje como
<a href="#" ng-click="do()">Click</a>
¿Cómo puedo evitar que el navegador navegue a # en AngularJS ?
href=''
para mantener el comportamiento del puntero del mouse.
Digamos que tengo una etiqueta de anclaje como
<a href="#" ng-click="do()">Click</a>
¿Cómo puedo evitar que el navegador navegue a # en AngularJS ?
href=''
para mantener el comportamiento del puntero del mouse.
Respuestas:
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 actualice su 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.
La siguiente es mi solución anterior, que dejo aquí solo para fines heredados:
Si tiene mucho este problema, 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 href
atributo es una cadena vacía ( ""
) o un hash ( '#'
) o si hay una ng-click
asignación. Si encuentra alguna de estas condiciones, detecta el evento y evita el comportamiento predeterminado.
El único inconveniente es que ejecuta esta directiva para todas las etiquetas de anclaje. Entonces, 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, entonces esta directiva no es muy eficiente. Sin embargo, casi siempre quiero hacerlo preventDefault
, así que uso esta directiva en todas mis aplicaciones de AngularJS.
href
atributo en blanco tiene un comportamiento variable en diferentes navegadores. Aunque estoy de acuerdo en que es, con mucho, la solución más limpia y eficiente, tiene algunos problemas entre navegadores. El uso del enfoque directivo permite que el navegador maneje la <a>
etiqueta como lo haría normalmente, pero aún así le da al OP la respuesta que estaba buscando.
De acuerdo con los documentos para ngHref , debería poder dejar el href o do 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 />
Puede pasar el objeto $ event a su método y llamarlo $event.preventDefault()
para que no se produzca el procesamiento predeterminado:
<a href="#" ng-click="do($event)">Click</a>
// then in your controller.do($event) method
$event.preventDefault()
$event.preventDefault()
... impuesto de IE.
ng-click="do(); $event.preventDefault()
por ejemplo ... aunque, no es necesario porque la respuesta de @ Chris a continuación es la correcta. $event.stopPropagation()
Sin embargo, esto podría ayudar a las personas en situaciones en las que han anidado ngClicks y desean llamar .
Prefiero usar directivas para este tipo de cosas. Aquí hay un ejemplo
<a href="#" ng-click="do()" eat-click>Click Me</a>
Y el código directivo para eat-click
:
module.directive('eatClick', function() {
return function(scope, element, attrs) {
$(element).click(function(event) {
event.preventDefault();
});
}
})
Ahora puede agregar el eat-click
atributo a cualquier elemento y obtendrápreventDefault()
automáticamente.
Beneficios:
$event
objeto feo a tudo()
función.$event
objetoError: $ is not defined
. ¿Qué me estoy perdiendo?
angular.element(element).bind('click', function(event){...});
. Funcionó. Ref: jQLite
Aunque Renaud dio una gran solución
<a href="#" ng-click="do(); $event.preventDefault()">Click</a>
Personalmente descubrí que también necesitas $ event.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
ng-click="$event.preventDefault()"
La solución más fácil que he encontrado es esta:
<a href="#" ng-click="do(); $event.preventDefault()">Click</a>
Entonces, leyendo estas respuestas, @Chris todavía tiene la respuesta más "correcta", supongo, pero tiene un problema, no muestra el "puntero" ...
Aquí hay dos formas de resolver este problema sin necesidad de agregar un cursor: estilo de puntero:
Usar en javascript:void(0)
lugar de #
:
<a href="javascript:void(0)" ng-click="doSomething()">Do Something</a>
Úselo $event.preventDefault()
en la ng-click
directiva (para no desechar su controlador con referencias relacionadas con DOM):
<a href="#dontGoHere" ng-click="doSomething(); $event.preventDefault()">Do Something</a>
Personalmente prefiero el primero sobre el segundo. javascript:void(0)
tiene otros beneficios que se discuten aquí . También hay una discusión sobre "JavaScript discreto" en ese enlace que es terriblemente reciente y no necesariamente se aplica directamente a una aplicación angular.
javascript:;
Puedes hacer lo siguiente
1.Eliminar href
atributo de la a
etiqueta anchor ( )
2.Ajuste el cursor del puntero en CSS a ng elementos de clic
[ng-click],
[data-ng-click],
[x-ng-click] {
cursor: pointer;
}
HTML
aquí angularjs puro: cerca de la función ng-click puede escribir la función preventDefault () separando el punto y coma
<a href="#" ng-click="do(); $event.preventDefault(); $event.stopPropagation();">Click me</a>
JS
$scope.do = function() {
alert("do here anything..");
}
(o)
puedes proceder de esta manera, esto ya se discutió aquí.
HTML
<a href="#" ng-click="do()">Click me</a>
JS
$scope.do = function(event) {
event.preventDefault();
event.stopPropagation()
}
Ya que está haciendo una aplicación web, ¿por qué necesita enlaces?
¡Cambia tus anclas por botones!
<button ng-click="do()"></button>
La forma más segura de evitar eventos en un href sería definirlo como
<a href="javascript:void(0)" ....>
Yo iría con:
<a ng-click="do()">Click</a>
Todo esto impide que lo predeterminado me haya resultado confuso, por lo que he creado un JSFiddle para ilustrar cuándo y dónde Angular está evitando el incumplimiento .
El JSFiddle está utilizando Angular es una directiva, por lo que debe ser EXACTAMENTE igual. Puede ver el código fuente aquí: un código fuente de etiqueta
Espero que esto ayude a aclarar algunos.
Me hubiera gustado publicar el documento en ngHref pero no puedo debido a mi reputación.
Muchas respuestas parecen ser excesivas. PARA MÍ, esto funciona
<a ng-href="#" ng-click="$event.preventDefault();vm.questionContainer($index)">{{question.Verbiage}}</a>
Necesito una presencia del valor del atributo href para la degradación (cuando js está apagado), por lo que no puedo usar el atributo href vacío (o "#"), pero el código anterior no funcionó para mí, porque necesito un evento ( e) variable. 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>
Tomando prestado de la respuesta de tennisgent. Me gusta que no tenga que crear una directiva personalizada para agregar todos los enlaces. Sin embargo, no pude conseguir que trabajara en IE8. Esto es lo que finalmente funcionó para mí (usando angular 1.0.6).
Tenga en cuenta que 'bind' le permite usar jqLite proporcionado por angular, por lo que no es necesario envolverlo con jQuery completo. También se 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();
}
})
}
};
}
])
dropdown
, quiero la propagación pero no el comportamiento predeterminado. Este fragmento NO se recomienda.
Me encontré con este mismo problema al usar los anclajes para un menú desplegable angular. La única solución que encontré que evitó los efectos secundarios no deseados (es decir, que el menú desplegable no se cerró debido al uso de preventDefault ()) fue usar lo siguiente:
<a href="javascript:;" ng-click="do()">Click</a>
si nunca quiere ir a href ... debe cambiar su marcado y usar un botón, no una etiqueta de ancla porque semánticamente no es un ancla o un enlace. Inversamente, si tiene un botón que realiza algunas comprobaciones y luego lo redirige, debe ser una etiqueta de enlace / ancla y no un botón ... para fines de SEO y pruebas [inserte aquí el paquete de pruebas].
para los enlaces que solo desea redirigir condicionalmente, como solicitar que se guarden los cambios, o reconocer el estado sucio ... debe usar ng-click = "someFunction ($ event)" y en someFunction en su validationError preventDefault y / o stopPropagation.
También sólo porque puede no significa que debe . javascript: void (0) funcionó bien en el pasado ... pero debido a los nefastos hackers / crackers, los navegadores señalan aplicaciones / sitios que usan javascript dentro de un href ... no veo razón para ducktype arriba ...
es 2016, ya que 2010 no debería ser motivo para usar enlaces que actúen como botones ... si aún tiene que admitir IE8 y, a continuación, debe reevaluar su lugar de trabajo.
/* NG CLICK PREVENT DEFAULT */
app.directive('ngClick', function () {
return {
link: function (scope, element, attributes) {
element.click(function (event) {
event.preventDefault();
event.stopPropagation();
});
}
};
});
Lo que debe hacer es omitir el href
atributo por completo.
Si observa el código fuente de la a
directiva del elemento (que es parte del núcleo angular), se indica 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 href. El único problema que aún tiene es el problema de 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 sea más accesible marcando enlaces reales con un estilo sutil y diferente, luego enlaces que realizan funciones.
¡Feliz codificación!
Puede deshabilitar la redirección de URL dentro del Html5Mode de $ 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
});
}]);
Si está utilizando Angular 8 o más, puede crear una directiva:
import { Directive, HostListener } from '@angular/core';
@Directive({
selector: '[preventDefault]'
})
export class PreventDefaultDirective {
@HostListener("click", ["$event"])
public onClick(event: any): void
{
console.log('click');
debugger;
event.preventDefault();
}
}
En su etiqueta de anclaje en el componente, puede cablearlo así:
<a ngbDropdownToggle preventDefault class="nav-link dropdown-toggle" href="#" aria-expanded="false" aria-haspopup="true" id="nav-dropdown-2">Pages</a>
El módulo de aplicación debe tener su declaración:
import { PreventDefaultDirective } from './shared/directives/preventdefault.directive';
@NgModule({
declarations: [
AppComponent,
PreventDefaultDirective
Una alternativa podría ser:
<span ng-click="do()">Click</span>
span
para hacer clic. Simplemente busque la respuesta de @ tennisgent: anclas sin href
definir.
href
.