Fare clic su un pulsante all'interno di un modulo provoca l'aggiornamento della pagina


217

Ho un modulo in Angular che contiene due tag pulsanti. Un pulsante invia il modulo ng-click. L'altro pulsante serve esclusivamente per la navigazione ng-click. Tuttavia, quando si fa clic su questo secondo pulsante, AngularJS sta causando un aggiornamento della pagina che attiva un 404. Ho lasciato cadere un punto di interruzione nella funzione e sta attivando la mia funzione. Se eseguo una delle seguenti operazioni, si interrompe:

  1. Se rimuovo il ng-click, il pulsante non provoca un aggiornamento della pagina.
  2. Se commento il codice nella funzione, non provoca un aggiornamento della pagina.
  3. Se cambio il tag del pulsante in un tag anchor ( <a>) con href="", allora non provoca un aggiornamento.

Quest'ultimo sembra la soluzione più semplice, ma perché AngularJS sta eseguendo un codice dopo la mia funzione che fa ricaricare la pagina? Sembra un bug.

Ecco il modulo:

<form class="form-horizontal" name="myProfile" ng-switch-when="profile">
  <fieldset>
    <div class="control-group">
      <label class="control-label" for="passwordButton">Password</label>
      <div class="controls">
        <button id="passwordButton" class="secondaryButton" ng-click="showChangePassword()">Change</button>
      </div>
    </div>

    <div class="buttonBar">
      <button id="saveProfileButton" class="primaryButton" ng-click="saveUser()">Save</button>
    </div>
  </fieldset>
</form>

Ecco il metodo del controller:

$scope.showChangePassword = function() {
  $scope.selectedLink = "changePassword";
};

Verifica se questo è il tuo problema github.com/angular/angular.js/issues/1238 (Sfortunatamente, non conosco abbastanza il modo per aggirare Github per essere in grado di dire se questa correzione è nella versione 1.0.1 o no) .
Mark Rajcok,

L'ho visto, ma non sto cambiando la posizione, quindi non credo che si applichi. A meno che questo altro pulsante non lo stia in qualche modo causando l'invio, ma non è definito come un tipo di invio e quando tolgo il clic, il pulsante non invia il modulo.
Chubbsondubs,

Sarebbe bello poter fornire una demo funzionante di questo problema. Forse a partire da: Angular Plnkr
Pete BD,


Risposte:


471

Se dai un'occhiata alle specifiche del W3C , sembrerebbe ovvio provare a contrassegnare gli elementi del tuo pulsante type='button'quando non vuoi che vengano inviati.

La cosa da notare in particolare è dove si dice

Un elemento pulsante senza l'attributo type specificato rappresenta la stessa cosa di un elemento button con l'attributo type impostato su "submit"


4
Ho lo stesso problema di OP, ma i miei pulsanti hanno il tipo specificato - e ancora clic provoca l'aggiornamento. Qualche altro posto dove potrei guardare?
Mateo Velenik,

Questo mi suggerisce che il tuo problema è in JavaScript. Il problema che la mia risposta sta affrontando è più una questione tra dom e browser. Alcuni javascript che gestiscono il clic del tuo pulsante probabilmente causano il ricaricamento che vedi. Buona caccia;)
LOAS

Questo e 'esattamente quello che stavo cercando. È stato molto fastidioso sulla mia pagina perché doveva mostrare solo gli errori e non inviare.
reaper_unique,

Ho i miei pulsanti contrassegnati con type = "button" e ho anche il problema. Nel mio gestore ng-click, ho $ event.stopPropagation (). Quando lo rimuovo, non si ricarica. Ne ho bisogno però. Qualche idea sul perché provoca un ricaricamento della pagina ?!
felixfbecker,

@freshfelicio: prova anche ad aggiungere $event.preventDefault(), che mi ha aiutato nel mio caso. Ma non ho spiegazioni sul perché: - \
Tim Büthe

72

Puoi provare a prevenire il gestore predefinito:

html:

<button ng-click="saveUser($event)">

js:

$scope.saveUser = function (event) {
  event.preventDefault();
  // your code
}

Bello! Ha davvero recuperato il mio scenario!
Richard,

2
Questo ha funzionato per noi, quando si utilizza AngularJS all'interno di un modulo di SharePoint. Ho dovuto aggiungere "event.stopPropagation ();" anche se.
Nick DeMayo,

19

Dovresti dichiarare l'attributo ng-submit={expression}nel tuo <form>tag.

Dai documenti di ngSubmit http://docs.angularjs.org/api/ng.directive:ngSubmit

Consente di associare espressioni angolari a eventi di invio.

Inoltre impedisce l'azione predefinita (che per modulo significa inviare la richiesta al server e ricaricare la pagina corrente).


3
Inoltre, assicurati di non avere la proprietà 'action' impostata nel modulo: form (action = "/ login", lng-submit = "login ()") Poiché ciò aggiornerà la pagina anche se hai impostato ng-submit .
jenso

Invio di un modulo e prevenzione dell'azione predefinita Poiché il ruolo dei moduli nelle applicazioni angolari lato client è diverso rispetto alle classiche app di andata e ritorno, è auspicabile che il browser non traduca l'invio del modulo in un ricaricamento a pagina intera che invia i dati al server . Invece, è necessario attivare una logica javascript per gestire l'invio del modulo in modo specifico per l'applicazione. Per questo motivo, Angular impedisce l'azione predefinita (invio modulo al server) a meno che l'elemento <form> non abbia un attributo azione specificato. - docs.angularjs.org/api/ng.directive:form
Jignesh Gohel

Ho un modulo con ng-submit = {expression} e un pulsante con type = "submit". Funziona bene, tranne su BB10. Se uso la tastiera BB10 Invia, la pagina verrà aggiornata. Se uso il pulsante che ho dichiarato nel mio modulo, funziona perfettamente.
Michael,

Questo non funziona per me. Ho seguito esattamente le indicazioni. La pagina continua a
postare

18

Uso la direttiva per prevenire comportamenti predefiniti:

module.directive('preventDefault', function() {
    return function(scope, element, attrs) {
        angular.element(element).bind('click', function(event) {
            event.preventDefault();
            event.stopPropagation();
        });
    }
});

E poi, in HTML:

<button class="secondaryButton" prevent-default>Secondary action</button>

Questa direttiva può essere utilizzata anche con <a>tutti gli altri tag


+1 Grazie! Ciò è utile quando non si ha accesso al <form>tag e quindi non è possibile utilizzare la ng-submitdirettiva.
jackvsworld,

grazie per questo, ma devo anche cancellare ng-click in una direttiva
boi_echos

Ciò impedisce anche al modulo di attivare il callback di ng-submit, giusto?
Jhourlad Estrella,

5

È possibile mantenere <button type="submit">, ma è necessario rimuovere l'attributo action=""di <form>.


2

Mi chiedo perché nessuno abbia proposto la soluzione forse più semplice:

non usare a <form>

A <whatever ng-form>fa IMHO un lavoro migliore e senza un modulo HTML, non c'è nulla che possa essere inviato dal browser stesso. Qual è esattamente il comportamento giusto quando si usa angolare.


come imporre il formvalid al clic quindi senza tag del modulo?
Rizwan Patel,

1
@RizwanPatel Immagino, non capisco, ma con ng-form=someForm, ottieni $scope.someForme ha un $validcampo. Quindi ottengo tutto ciò di cui ho bisogno <button ng-disabled="!someForm.$valid">.
maaartinus,


1

Questa risposta potrebbe non essere direttamente correlata alla domanda. È solo per il caso in cui si invia il modulo utilizzando gli script.

Secondo il codice ng-submit

 var handleFormSubmission = function(event) {
  scope.$apply(function() {
    controller.$commitViewValue();
    controller.$setSubmitted();
  });

  event.preventDefault();
};

formElement[0].addEventListener('submit', handleFormSubmission);

Aggiunge listener di eventi di invio nel modulo. Ma il gestore eventi submit non verrà chiamato quando submit viene avviato chiamando form.submit (). In questo caso, ng-submit non impedisce l'azione predefinita, è necessario chiamare preventDefault nel gestore ng-submit;

Per fornire una risposta ragionevolmente definitiva, l'articolo 5 dell'algoritmo di invio del modulo HTML afferma che un modulo invia un evento di invio solo se non è stato inviato chiamando il metodo di invio (il che significa che invia un evento di invio solo se inviato da un pulsante o altro implicito metodo, ad esempio premendo Invio mentre lo stato attivo è su un elemento di testo di tipo input).

Vedere il modulo inviato utilizzando submit () da un collegamento non può essere rilevato dal gestore onsubmit


0

Il primo pulsante invia il modulo e il secondo no

<body>
<form  ng-app="myApp" ng-controller="myCtrl" ng-submit="Sub()">
<div>
S:<input type="text" ng-model="v"><br>
<br>
<button>Submit</button>
//Dont Submit
<button type='button' ng-click="Dont()">Dont Submit</button>
</div>
</form>

<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.Sub=function()
{
alert('Inside Submit');
}

$scope.Dont=function()
{
$scope.v=0;
}
});
</script>

</body>

0

Basta aggiungere l' FormsModulenella importsgamma di app.module.tsfile e aggiungere import { FormsModule } from '@angular/forms';nella parte superiore di questo file ... questo funzionerà.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.