Diciamo che ho un tag anchor come
<a href="#" ng-click="do()">Click</a>
Come posso impedire al browser di navigare su # in AngularJS ?
href=''
per mantenere il comportamento del puntatore del mouse.
Diciamo che ho un tag anchor come
<a href="#" ng-click="do()">Click</a>
Come posso impedire al browser di navigare su # in AngularJS ?
href=''
per mantenere il comportamento del puntatore del mouse.
Risposte:
AGGIORNAMENTO : Da allora ho cambiato idea su questa soluzione. Dopo più sviluppo e tempo impiegato a lavorare su questo, credo che una soluzione migliore a questo problema sia quella di fare quanto segue:
<a ng-click="myFunction()">Click Here</a>
E quindi aggiorna il tuo css
per avere una regola extra:
a[ng-click]{
cursor: pointer;
}
È molto più semplice e offre esattamente la stessa funzionalità ed è molto più efficiente. Spero che possa essere utile a chiunque cerchi questa soluzione in futuro.
Quella che segue è la mia soluzione precedente, che lascio qui solo per scopi legacy:
Se riscontri molto questo problema, una semplice direttiva che risolve questo problema è la seguente:
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();
});
}
}
};
});
Controlla tutti i tag anchor ( <a></a>
) per vedere se il loro href
attributo è una stringa vuota ( ""
) o un hash ( '#'
) o se esiste un ng-click
compito. Se rileva una di queste condizioni, rileva l'evento e impedisce il comportamento predefinito.
L'unico lato negativo è che esegue questa direttiva per tutti i tag di ancoraggio. Pertanto, se nella pagina sono presenti molti tag di ancoraggio e si desidera solo impedire il comportamento predefinito per un numero limitato di essi, questa direttiva non è molto efficace. Tuttavia, quasi sempre lo voglio preventDefault
, quindi uso questa direttiva ovunque nelle mie app AngularJS.
href
attributo vuoto ha un comportamento variabile nei diversi browser. Sebbene sia d'accordo che sia di gran lunga la soluzione più pulita ed efficiente, presenta alcuni problemi tra browser. L'uso dell'approccio direttiva consente al browser di gestire il <a>
tag come farebbe normalmente, ma ottenendo comunque l'OP la risposta che stavano cercando.
Secondo i documenti per ngHref dovresti essere in grado di lasciare fuori href o fare 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 />
È possibile passare l'oggetto $ event al proprio metodo e richiamarlo $event.preventDefault()
, in modo che l'elaborazione predefinita non si verifichi:
<a href="#" ng-click="do($event)">Click</a>
// then in your controller.do($event) method
$event.preventDefault()
$event.preventDefault()
... IE tax.
ng-click="do(); $event.preventDefault()
ad esempio ... anche se non è necessario perché la risposta di @ Chris di seguito è quella corretta. Ciò potrebbe aiutare le persone in situazioni in cui hanno nidificato ngClicks e che vogliono chiamare $event.stopPropagation()
, tuttavia.
Preferisco usare le direttive per questo tipo di cose. Ecco un esempio
<a href="#" ng-click="do()" eat-click>Click Me</a>
E il codice direttiva per eat-click
:
module.directive('eatClick', function() {
return function(scope, element, attrs) {
$(element).click(function(event) {
event.preventDefault();
});
}
})
Ora puoi aggiungere l' eat-click
attributo a qualsiasi elemento e verrà preventDefault()
"ed automagicamente".
Benefici:
$event
oggetto brutto nella tua do()
funzione.$event
oggettoError: $ is not defined
. Cosa mi sto perdendo?
angular.element(element).bind('click', function(event){...});
. Ha funzionato. Rif: jQLite
Anche se Renaud ha dato un'ottima soluzione
<a href="#" ng-click="do(); $event.preventDefault()">Click</a>
Personalmente ho scoperto che è necessario anche $ event.stopPropagation () in alcuni casi per evitare alcuni degli effetti collaterali
<a href="#" ng-click="do(); $event.preventDefault(); $event.stopPropagation();">
Click</a>
sarà la mia soluzione
ng-click="$event.preventDefault()"
La soluzione più semplice che ho trovato è questa:
<a href="#" ng-click="do(); $event.preventDefault()">Click</a>
Quindi, leggendo queste risposte, @Chris ha ancora la risposta più "corretta", suppongo, ma ha un problema, non mostra il "puntatore" ....
Quindi qui ci sono due modi per risolvere questo problema senza bisogno di aggiungere un cursore: stile puntatore:
Usa javascript:void(0)
invece di #
:
<a href="javascript:void(0)" ng-click="doSomething()">Do Something</a>
Utilizzare $event.preventDefault()
nella ng-click
direttiva (quindi non eseguire il junk del controller con riferimenti relativi al DOM):
<a href="#dontGoHere" ng-click="doSomething(); $event.preventDefault()">Do Something</a>
Personalmente preferisco il primo al secondo. javascript:void(0)
ha altri vantaggi che sono discussi qui . Si discute anche di "JavaScript discreto" in quel link che è spaventosamente recente e non si applica necessariamente direttamente a un'applicazione angolare.
javascript:;
Puoi fare come segue
1.Rimuovere l' href
attributo dal a
tag anchor ( )
2.Impostare il cursore del puntatore in CSS per fare clic sugli elementi clic
[ng-click],
[data-ng-click],
[x-ng-click] {
cursor: pointer;
}
HTML
qui pure angularjs: vicino alla funzione ng-click puoi scrivere la funzione preventDefault () separando il punto e virgola
<a href="#" ng-click="do(); $event.preventDefault(); $event.stopPropagation();">Click me</a>
JS
$scope.do = function() {
alert("do here anything..");
}
(o)
puoi procedere in questo modo, ne abbiamo già discusso qui.
HTML
<a href="#" ng-click="do()">Click me</a>
JS
$scope.do = function(event) {
event.preventDefault();
event.stopPropagation()
}
Dal momento che stai creando un'app Web, perché hai bisogno di link?
Scambia le tue ancore in bottoni!
<button ng-click="do()"></button>
Il modo più sicuro per evitare eventi su un href sarebbe definirlo come
<a href="javascript:void(0)" ....>
Vorrei andare con:
<a ng-click="do()">Click</a>
Tutto questo per prevenire la cosa predefinita mi ha confuso, quindi ho creato un JSFiddle che illustra quando e dove Angular impedisce la default .
JSFiddle sta usando Angular come una direttiva, quindi dovrebbe ESATTAMENTE essere lo stesso. Puoi vedere il codice sorgente qui: un codice sorgente tag
Spero che questo possa aiutare a chiarire alcuni.
Mi sarebbe piaciuto pubblicare il documento su ngHref ma non posso a causa della mia reputazione.
Questo è quello che faccio sempre. Funziona come un fascino!
<a href ng-click="do()">Click</a>
Molte risposte sembrano eccessive. PER ME, funziona
<a ng-href="#" ng-click="$event.preventDefault();vm.questionContainer($index)">{{question.Verbiage}}</a>
Ho bisogno di una presenza del valore dell'attributo href per il degrado (quando js è spento), quindi non posso usare l'attributo href vuoto (o "#"), ma il codice sopra non ha funzionato per me, perché ho bisogno di un evento ( e) variabile. Ho creato la mia direttiva:
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>
Prendendo in prestito dalla risposta di tennisgent. Mi piace che non sia necessario creare una direttiva personalizzata da aggiungere a tutti i collegamenti. Tuttavia, non sono riuscito a farlo funzionare in IE8. Ecco cosa finalmente ha funzionato per me (usando l'angolare 1.0.6).
Si noti che 'bind' consente di utilizzare jqLite fornito da angular, quindi non è necessario eseguire il wrapping con jQuery completo. Richiesto anche il metodo 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
, voglio la propagazione ma non il comportamento predefinito. Questo frammento NON è raccomandato.
Ho riscontrato questo stesso problema durante l'utilizzo delle ancore per un menu a discesa angolare del bootstrap. L'unica soluzione che ho scoperto che ha evitato effetti collaterali indesiderati (ad es. Il menu a discesa non chiuso a causa dell'utilizzo di preventDefault ()) è stato quello di utilizzare quanto segue:
<a href="javascript:;" ng-click="do()">Click</a>
se non vuoi mai andare su href ... dovresti cambiare il tuo markup e usare un pulsante non un tag anchor perché semanticamente non è un anchor o un link. Inversamente se si dispone di un pulsante che esegue alcuni controlli e quindi reindirizza dovrebbe essere un tag link / anchor e non un pulsante ... per scopi SEO e test [inserire la suite di test qui].
per i collegamenti che desideri reindirizzare solo in modo condizionale come la richiesta di salvare le modifiche o riconoscere lo stato sporco ... dovresti usare ng-click = "someFunction ($ event)" e in someFunction sulla tua convalidaError preventDefault e o stopPropagation.
anche solo perché puoi non significa che dovresti . javascript: void (0) ha funzionato bene nel passato ... ma a causa dei malvagi hacker / cracker i browser contrassegnano app / siti che usano javascript in un href ... non vedo alcun motivo per ducktype sopra ..
è il 2016 dal 2010 non dovrebbe essere un motivo per utilizzare i collegamenti che agiscono come pulsanti ... se devi ancora supportare IE8 e al di sotto devi rivalutare la tua sede di attività.
/* NG CLICK PREVENT DEFAULT */
app.directive('ngClick', function () {
return {
link: function (scope, element, attributes) {
element.click(function (event) {
event.preventDefault();
event.stopPropagation();
});
}
};
});
Quello che dovresti fare è omettere completamente l' href
attributo.
Se guardi il codice sorgente per la a
direttiva element (che fa parte del nucleo angolare), indica alla riga 29 - 31:
if (!element.attr(href)) {
event.preventDefault();
}
Il che significa che Angular sta già risolvendo il problema dei collegamenti senza un href. L'unico problema che hai ancora è il problema CSS. Puoi ancora applicare lo stile del puntatore alle ancore che hanno ng-clic, ad esempio:
a[ng-click] {
/* Styles for anchors without href but WITH ng-click */
cursor: pointer;
}
Quindi, potresti persino rendere il tuo sito più accessibile contrassegnando collegamenti reali con uno stile sottile e diverso rispetto ai collegamenti che svolgono funzioni.
Buona programmazione!
È possibile disabilitare il reindirizzamento dell'URL all'interno della modalità Html5 di $ location per raggiungere l'obiettivo. È possibile definirlo all'interno del controller specifico utilizzato per la pagina. Qualcosa come questo:
app.config(['$locationProvider', function ($locationProvider) {
$locationProvider.html5Mode({
enabled: true,
rewriteLinks: false,
requireBase: false
});
}]);
Se si utilizza Angular 8 o più, è possibile creare una direttiva:
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();
}
}
Sul tuo tag di ancoraggio sul componente puoi collegarlo in questo modo:
<a ngbDropdownToggle preventDefault class="nav-link dropdown-toggle" href="#" aria-expanded="false" aria-haspopup="true" id="nav-dropdown-2">Pages</a>
Il modulo app dovrebbe avere la sua dichiarazione:
import { PreventDefaultDirective } from './shared/directives/preventdefault.directive';
@NgModule({
declarations: [
AppComponent,
PreventDefaultDirective
Un'alternativa potrebbe essere:
<span ng-click="do()">Click</span>
span
scopo di clic. Prova la risposta di @ tennisgent: ancore senza href
definizione.
href
.