Angenommen, ich habe ein Ankertag wie
<a href="#" ng-click="do()">Click</a>
Wie kann ich verhindern, dass der Browser in AngularJS zu # navigiert ?
href=''
um das Verhalten des Mauszeigers beizubehalten.
Angenommen, ich habe ein Ankertag wie
<a href="#" ng-click="do()">Click</a>
Wie kann ich verhindern, dass der Browser in AngularJS zu # navigiert ?
href=''
um das Verhalten des Mauszeigers beizubehalten.
Antworten:
UPDATE : Seitdem habe ich meine Meinung zu dieser Lösung geändert. Nach mehr Entwicklung und Zeitaufwand glaube ich, dass eine bessere Lösung für dieses Problem darin besteht, Folgendes zu tun:
<a ng-click="myFunction()">Click Here</a>
Und aktualisieren Sie dann Ihre css
, um eine zusätzliche Regel zu haben:
a[ng-click]{
cursor: pointer;
}
Es ist viel einfacher und bietet genau die gleiche Funktionalität und ist viel effizienter. Ich hoffe, dass dies für alle anderen hilfreich sein kann, die in Zukunft nach dieser Lösung suchen.
Das Folgende ist meine vorherige Lösung, die ich hier nur aus Legacy-Gründen lasse:
Wenn Sie dieses Problem häufig haben, ist eine einfache Anweisung, die dieses Problem beheben würde, die folgende:
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();
});
}
}
};
});
Es überprüft alle Ankertags ( <a></a>
), um festzustellen, ob ihr href
Attribut entweder eine leere Zeichenfolge ( ""
) oder ein Hash ( '#'
) ist oder ob eine ng-click
Zuweisung vorliegt. Wenn eine dieser Bedingungen gefunden wird, wird das Ereignis abgefangen und das Standardverhalten verhindert.
Der einzige Nachteil ist, dass diese Anweisung für alle Ankertags ausgeführt wird. Wenn Sie also viele Ankertags auf der Seite haben und das Standardverhalten nur für eine kleine Anzahl von Tags verhindern möchten, ist diese Anweisung nicht sehr effizient. Ich möchte dies jedoch fast immer preventDefault
, daher verwende ich diese Anweisung überall in meinen AngularJS-Apps.
href
Attribut in verschiedenen Browsern ein unterschiedliches Verhalten. Obwohl ich der Meinung bin, dass es bei weitem die sauberste und effizienteste Lösung ist, gibt es einige browserübergreifende Probleme. Die Verwendung des Direktivenansatzes ermöglicht es dem Browser, das <a>
Tag wie gewohnt zu behandeln , dem OP jedoch die Antwort zu geben, nach der er gesucht hat.
Gemäß den Dokumenten für ngHref sollten Sie in der Lage sein, die href wegzulassen oder href = "" zu tun.
<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 />
Sie können das $ event-Objekt an Ihre Methode übergeben und es aufrufen $event.preventDefault()
, damit die Standardverarbeitung nicht erfolgt:
<a href="#" ng-click="do($event)">Click</a>
// then in your controller.do($event) method
$event.preventDefault()
$event.preventDefault()
... IE-Steuer erforderlich ist .
ng-click="do(); $event.preventDefault()
Zum Beispiel ... obwohl dies nicht erforderlich ist, da die Antwort von @ Chris unten die richtige ist. Dies kann Personen in Situationen helfen, in denen sie ngClicks verschachtelt haben und aufrufen möchten $event.stopPropagation()
.
Ich bevorzuge es, Anweisungen für solche Dinge zu verwenden. Hier ist ein Beispiel
<a href="#" ng-click="do()" eat-click>Click Me</a>
Und der Direktivencode für eat-click
:
module.directive('eatClick', function() {
return function(scope, element, attrs) {
$(element).click(function(event) {
event.preventDefault();
});
}
})
Jetzt können Sie das eat-click
Attribut jedem Element hinzufügen und es wird preventDefault()
automatisch bearbeitet.
Leistungen:
$event
Objekt nicht an Ihre do()
Funktion übergeben.$event
Objekt nicht ausgeblendet werden mussError: $ is not defined
. Was vermisse ich?
angular.element(element).bind('click', function(event){...});
. Es funktionierte. Ref: jQLite
Obwohl Renaud eine tolle Lösung gab
<a href="#" ng-click="do(); $event.preventDefault()">Click</a>
Ich persönlich habe festgestellt, dass Sie in einigen Fällen auch $ event.stopPropagation () benötigen, um einige der Nebenwirkungen zu vermeiden
<a href="#" ng-click="do(); $event.preventDefault(); $event.stopPropagation();">
Click</a>
wird meine Lösung sein
ng-click="$event.preventDefault()"
Die einfachste Lösung, die ich gefunden habe, ist diese:
<a href="#" ng-click="do(); $event.preventDefault()">Click</a>
Wenn Sie diese Antworten durchlesen, hat @Chris immer noch die "richtigste" Antwort, aber es gibt ein Problem: Der "Zeiger" wird nicht angezeigt.
Es gibt also zwei Möglichkeiten, um dieses Problem zu lösen, ohne einen Cursor hinzufügen zu müssen: Zeigerstil:
Verwenden Sie javascript:void(0)
anstelle von #
:
<a href="javascript:void(0)" ng-click="doSomething()">Do Something</a>
Verwendung $event.preventDefault()
in der ng-click
Direktive (damit Sie Ihren Controller nicht mit DOM-bezogenen Referenzen überladen):
<a href="#dontGoHere" ng-click="doSomething(); $event.preventDefault()">Do Something</a>
Ich persönlich bevorzuge das erstere gegenüber dem letzteren. javascript:void(0)
hat andere Vorteile, die hier diskutiert werden . Es gibt auch eine Diskussion über "unauffälliges JavaScript" in diesem Link, der erschreckend neu ist und nicht unbedingt direkt auf eine Winkelanwendung zutrifft.
javascript:;
Sie können wie folgt vorgehen
1.Entfernen Sie das href
Attribut vom anchor ( a
) -Tag
2. Setzen Sie den Zeigercursor in CSS auf ng click-Elemente
[ng-click],
[data-ng-click],
[x-ng-click] {
cursor: pointer;
}
HTML
hier pure anglejs: In der Nähe der ng-click-Funktion können Sie die Funktion prepareDefault () schreiben, indem Sie das Semikolon trennen
<a href="#" ng-click="do(); $event.preventDefault(); $event.stopPropagation();">Click me</a>
JS
$scope.do = function() {
alert("do here anything..");
}
(oder)
Sie können so vorgehen, dies wird hier bereits besprochen.
HTML
<a href="#" ng-click="do()">Click me</a>
JS
$scope.do = function(event) {
event.preventDefault();
event.stopPropagation()
}
Warum benötigen Sie Links, da Sie eine Web-App erstellen?
Tauschen Sie Ihre Anker gegen Knöpfe!
<button ng-click="do()"></button>
Der sicherste Weg, Ereignisse auf einer href zu vermeiden, besteht darin, sie als zu definieren
<a href="javascript:void(0)" ....>
Ich würde gehen mit:
<a ng-click="do()">Click</a>
Insgesamt war dies für mich verwirrend, daher habe ich dort eine JSFiddle erstellt, die zeigt, wann und wo Angular die Standardeinstellung verhindert .
Die JSFiddle verwendet Angulars Direktive - daher sollte sie genau gleich sein. Sie können den Quellcode hier sehen: einen Tag-Quellcode
Ich hoffe, dass dies für einige zur Klärung beiträgt.
Ich hätte das Dokument gerne bei ngHref gepostet, kann es aber aufgrund meines Rufs nicht.
Viele Antworten scheinen übertrieben zu sein. Für mich funktioniert das
<a ng-href="#" ng-click="$event.preventDefault();vm.questionContainer($index)">{{question.Verbiage}}</a>
Ich benötige den Wert des href-Attributs für die Verschlechterung (wenn js ausgeschaltet ist), daher kann ich kein leeres href-Attribut (oder "#") verwenden, aber der obige Code hat bei mir nicht funktioniert, da ich ein Ereignis benötige ( e) variabel. Ich habe meine eigene Direktive erstellt:
angular.module('MyApp').directive('clickPrevent', function() {
return function(scope, element, attrs) {
return element.on('click', function(e) {
return e.preventDefault();
});
};
});
In HTML:
<a data-click-prevent="true" href="/users/sign_up" ng-click="openSignUpModal()">Sign up</a>
Aus der Antwort von Tennisgent entlehnt. Ich finde es gut, dass Sie keine benutzerdefinierte Direktive erstellen müssen, um alle Links hinzuzufügen. Ich konnte ihn jedoch nicht dazu bringen, in IE8 zu arbeiten. Hier ist, was endlich für mich funktioniert hat (mit Angular 1.0.6).
Beachten Sie, dass Sie mit 'bind' jqLite verwenden können, das von angle bereitgestellt wird, sodass Sie nicht mit der vollständigen jQuery umbrechen müssen. Erforderlich ist auch die stopPropogation-Methode.
.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
, möchte ich die Weitergabe, aber nicht das Standardverhalten. Dieses Snippet wird NICHT empfohlen.
Ich bin auf dasselbe Problem gestoßen, als ich Anker für ein eckiges Bootstrap-Dropdown verwendet habe. Die einzige Lösung, die ich gefunden habe, um unerwünschte Nebenwirkungen zu vermeiden (dh das Dropdown-Menü, das aufgrund der Verwendung von präventDefault () nicht geschlossen wurde), war die Verwendung der folgenden:
<a href="javascript:;" ng-click="do()">Click</a>
Wenn Sie niemals zu href gehen möchten, sollten Sie Ihr Markup ändern und eine Schaltfläche verwenden, die kein Ankertag ist, da es sich semantisch nicht um einen Anker oder einen Link handelt. Umgekehrt, wenn Sie eine Schaltfläche haben, die einige Überprüfungen durchführt und diese dann umleitet, sollte es sich um ein Link- / Anker-Tag und nicht um eine Schaltfläche handeln ... auch für SEO-Zwecke [Test-Suite hier einfügen].
Für Links, die Sie nur unter bestimmten Bedingungen umleiten möchten, z. B. die Aufforderung zum Speichern von Änderungen oder das Bestätigen des fehlerhaften Status ... sollten Sie ng-click = "someFunction ($ event)" und in someFunction für validationError verhindernDefault und / oder stopPropagation verwenden.
auch nur weil du kannst, heißt das nicht, dass du es solltest . Javascript: void (0) hat früher gut funktioniert ... aber wegen der schändlichen Hacker / Cracker-Browser kennzeichnen Apps / Websites, die Javascript in einem href verwenden ... siehe oben keinen Grund, sich zu ducken.
Es ist 2016, seit 2010 sollte es keinen Grund geben, Links zu verwenden, die wie Schaltflächen wirken. Wenn Sie IE8 und darunter noch unterstützen müssen, müssen Sie Ihren Geschäftssitz neu bewerten.
/* NG CLICK PREVENT DEFAULT */
app.directive('ngClick', function () {
return {
link: function (scope, element, attributes) {
element.click(function (event) {
event.preventDefault();
event.stopPropagation();
});
}
};
});
Was Sie tun sollten, ist das href
Attribut vollständig wegzulassen .
Wenn Sie sich den Quellcode für die a
Elementanweisung ansehen (die Teil des Angular-Kerns ist), heißt es in Zeile 29 - 31:
if (!element.attr(href)) {
event.preventDefault();
}
Das heißt, Angular löst bereits das Problem der Links ohne href. Das einzige Problem, das Sie noch haben, ist das CSS-Problem. Sie können den Zeigerstil weiterhin auf Anker mit ng-Klicks anwenden, z.
a[ng-click] {
/* Styles for anchors without href but WITH ng-click */
cursor: pointer;
}
Sie können Ihre Website also sogar zugänglicher machen, indem Sie echte Links mit einem subtilen, anderen Stil als Links markieren, die Funktionen ausführen.
Viel Spaß beim Codieren!
Sie können die URL-Umleitung im Html5Mode von $ location deaktivieren, um das Ziel zu erreichen. Sie können es innerhalb des spezifischen Controllers definieren, der für die Seite verwendet wird. Etwas wie das:
app.config(['$locationProvider', function ($locationProvider) {
$locationProvider.html5Mode({
enabled: true,
rewriteLinks: false,
requireBase: false
});
}]);
Wenn Sie Angular 8 oder höher verwenden, können Sie eine Direktive erstellen:
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();
}
}
Auf Ihrem Ankertag auf der Komponente können Sie es wie folgt verkabeln:
<a ngbDropdownToggle preventDefault class="nav-link dropdown-toggle" href="#" aria-expanded="false" aria-haspopup="true" id="nav-dropdown-2">Pages</a>
App-Modul sollte seine Erklärung haben:
import { PreventDefaultDirective } from './shared/directives/preventdefault.directive';
@NgModule({
declarations: [
AppComponent,
PreventDefaultDirective
Eine Alternative könnte sein:
<span ng-click="do()">Click</span>
span
zum Klicken zu missbrauchen . Gehen Sie einfach zur Antwort von @ Tennisgent - Anker ohne href
Definition.
href
.