Un clic sur un bouton d'un formulaire entraîne l'actualisation de la page

217

J'ai un formulaire en angulaire qui contient deux balises de boutons. Un bouton soumet le formulaire ng-click. L'autre bouton est uniquement destiné à la navigation ng-click. Cependant, lorsque ce deuxième bouton est cliqué, AngularJS provoque une actualisation de page qui déclenche un 404. J'ai supprimé un point d'arrêt dans la fonction et il déclenche ma fonction. Si je fais l'une des actions suivantes, cela s'arrête:

  1. Si je supprime le ng-click, le bouton ne provoque pas une actualisation de la page.
  2. Si je commente le code dans la fonction, cela ne provoque pas un rafraîchissement de la page.
  3. Si je change la balise de bouton en balise d'ancrage ( <a>) avec href="", cela ne provoque pas de rafraîchissement.

Ce dernier semble être la solution de contournement la plus simple, mais pourquoi AngularJS exécute-t-il même du code après ma fonction qui provoque le rechargement de la page? On dirait un bug.

Voici le formulaire:

<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>

Voici la méthode du contrôleur:

$scope.showChangePassword = function() {
  $scope.selectedLink = "changePassword";
};
chubbsondubs
la source
Voyez si c'est votre problème github.com/angular/angular.js/issues/1238 (Malheureusement, je ne connais pas assez le github pour savoir si ce correctif est dans la version 1.0.1 ou non) .
Mark Rajcok
J'ai vu celui-là, mais je ne change pas l'emplacement, donc je ne pense pas que cela s'applique. Sauf si cet autre bouton le fait en quelque sorte le soumettre, mais il n'est pas défini comme un type de soumission, et quand je retire le ng-click, le bouton ne soumet pas le formulaire.
chubbsondubs
Ce serait formidable si vous pouviez fournir une démonstration de ce problème. Peut-être à partir de: Angular Plnkr
Pete BD
On dirait un doublon. stackoverflow.com/questions/16703215/…
Vaibs

Réponses:

471

Si vous jetez un œil à la spécification W3C , il semblerait que la chose la plus évidente à essayer est de marquer vos éléments de bouton type='button'lorsque vous ne voulez pas qu'ils soient soumis.

La chose à noter en particulier est l'endroit où il est dit

Un élément de bouton sans attribut de type spécifié représente la même chose qu'un élément de bouton avec son attribut de type défini sur "soumettre"

LOAS
la source
4
J'ai le même problème que OP mais mes boutons ont le type spécifié - et toujours cliquer provoque une actualisation. D'autres endroits où je pourrais regarder?
Mateo Velenik
Cela me suggère que votre problème est en javascript. Le problème que je réponds est plus une question entre le dom et le navigateur. Certains javascript qui gèrent le clic de votre bouton provoquent probablement le rechargement que vous voyez. Bonne chasse;)
LOAS
Ceci est exactement ce que je cherchais. C'était très ennuyeux sur ma page car il était censé montrer uniquement les erreurs et ne pas soumettre.
reaper_unique
J'ai mes boutons marqués avec type = "bouton" et j'ai aussi le problème. Dans mon gestionnaire ng-click, j'ai $ event.stopPropagation (). Lorsque je le supprime, il ne se recharge pas. J'en ai besoin cependant. Des idées pourquoi cela provoque un rechargement de page?!
felixfbecker
@freshfelicio: essayez également d'ajouter $event.preventDefault(), cela a aidé dans mon cas. Mais je n'ai aucune explication pourquoi: - \
Tim Büthe
72

Vous pouvez essayer d'empêcher le gestionnaire par défaut:

html:

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

js:

$scope.saveUser = function (event) {
  event.preventDefault();
  // your code
}
antage
la source
Agréable! Cela correspondait vraiment à mon scénario!
Richard
2
Cela a fonctionné pour nous, lors de l'utilisation d'AngularJS dans un formulaire SharePoint. J'ai dû ajouter "event.stopPropagation ();" mais aussi.
Nick DeMayo
19

Vous devez déclarer l'attribut ng-submit={expression}dans votre <form>balise.

À partir des documents ngSubmit http://docs.angularjs.org/api/ng.directive:ngSubmit

Permet de lier des expressions angulaires aux événements onsubmit.

De plus, il empêche l'action par défaut (ce qui signifie pour le formulaire l'envoi de la demande au serveur et le rechargement de la page actuelle).

Shane Stillwell
la source
3
Assurez-vous également que la propriété 'action' n'est pas définie sur le formulaire: form (action = "/ login", lng-submit = "login ()"), car cela actualisera la page même si vous avez défini ng-submit .
jenso
Soumettre un formulaire et empêcher l'action par défaut Étant donné que le rôle des formulaires dans les applications angulaires côté client est différent de celui des applications aller-retour classiques, il est souhaitable que le navigateur ne traduise pas la soumission du formulaire en une recharge de page complète qui envoie les données au serveur. . Au lieu de cela, une logique javascript doit être déclenchée pour gérer la soumission du formulaire de manière spécifique à l'application. Pour cette raison, Angular empêche l'action par défaut (soumission de formulaire au serveur) à moins que l'élément <form> n'ait un attribut d'action spécifié. - docs.angularjs.org/api/ng.directive:form
Jignesh Gohel
J'ai un formulaire avec ng-submit = {expression} et un bouton avec type = "submit". Fonctionne très bien sauf sur BB10. Si j'utilise la commande Envoyer du clavier BB10, la page sera actualisée. Si j'utilise le bouton que j'ai déclaré dans mon formulaire, cela fonctionnera bien.
Michael
Cela ne fonctionne pas pour moi. J'ai suivi les instructions exactement. La page revient toujours
meffect
18

J'utilise la directive pour empêcher le comportement par défaut:

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

Et puis, en html:

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

Cette directive peut également être utilisée avec <a>et toutes les autres balises

pleerock
la source
+1 Merci! Cela est utile lorsque vous n'avez pas accès à la <form>balise et que vous ne pouvez donc pas utiliser la ng-submitdirective.
jackvsworld
yow merci pour celui-ci, mais je dois également annuler ng-click dans une directive
boi_echos
Cela empêche également le formulaire de déclencher le rappel ng-submit, non?
Jhourlad Estrella
5

Vous pouvez conserver <button type="submit">, mais vous devez supprimer l'attribut action=""de <form>.

Anderson Ferreira
la source
2

Je me demande pourquoi personne n'a proposé la solution peut-être la plus simple:

n'utilisez pas de <form>

A <whatever ng-form>mon humble avis fait un meilleur travail et sans formulaire HTML, il n'y a rien à soumettre par le navigateur lui-même. Quel est exactement le bon comportement lors de l'utilisation angulaire.

maaartinus
la source
comment appliquer le formulaire valide en un clic puis sans balise de formulaire?
Rizwan Patel
1
@RizwanPatel Je suppose, je ne comprends pas, mais avec ng-form=someForm, vous obtenez $scope.someFormet il a un $validchamp. Je reçois donc tout ce dont j'ai besoin <button ng-disabled="!someForm.$valid">.
maaartinus
1

Ajoutez une action à votre formulaire.

<form action="#">

Swapnil Patwa
la source
1

Cette réponse peut ne pas être directement liée à la question. C'est juste pour le cas où vous soumettez le formulaire à l'aide de scripts.

Selon le code ng-submit

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

  event.preventDefault();
};

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

Il ajoute soumettre écouteur d'événements sur le formulaire. Mais le gestionnaire d'événements submit ne serait pas appelé lorsque submit est lancé en appelant form.submit (). Dans ce cas, ng-submit n'empêchera pas l'action par défaut, vous devez appeler vous-même preventDefault dans le gestionnaire ng-submit;

Pour fournir une réponse raisonnablement définitive, l'élément 5 de l'algorithme de soumission de formulaire HTML indique qu'un formulaire ne distribue un événement de soumission que s'il n'a pas été soumis en appelant la méthode de soumission (ce qui signifie qu'il ne distribue un événement de soumission que s'il est soumis par un bouton ou un autre moyen implicite). , par exemple en appuyant sur Entrée pendant que le focus est sur un élément de texte de type d'entrée).

Voir le formulaire soumis à l'aide de submit () à partir d'un lien ne peut pas être détecté par le gestionnaire onsubmit

user1577263
la source
0

Le premier bouton soumet le formulaire et le second ne le fait pas

<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>
Amay Kulkarni
la source
0

Ajoutez simplement le FormsModuledans le importstableau de app.module.tsfichiers, et ajoutez import { FormsModule } from '@angular/forms';en haut de ce fichier ... cela fonctionnera.

Sahil Sharma
la source