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";
};

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


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"


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
}

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


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


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


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.


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

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


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>

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.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.