Durch Klicken auf eine Schaltfläche in einem Formular wird die Seite aktualisiert

217

Ich habe ein Formular in Angular, das zwei Schaltflächen-Tags enthält. Eine Schaltfläche sendet das Formular weiter ng-click. Die andere Schaltfläche dient ausschließlich zur Navigation ng-click. Wenn Sie jedoch auf diese zweite Schaltfläche klicken, führt AngularJS eine Seitenaktualisierung durch, die eine 404 auslöst. Ich habe einen Haltepunkt in der Funktion gelöscht und er löst meine Funktion aus. Wenn ich eine der folgenden Aktionen ausführe, wird sie gestoppt:

  1. Wenn ich das entferne ng-click, bewirkt die Schaltfläche keine Seitenaktualisierung.
  2. Wenn ich den Code in der Funktion auskommentiere, wird keine Seitenaktualisierung durchgeführt.
  3. Wenn ich das Schaltflächen-Tag in ein Anker-Tag ( <a>) mit ändere href="", wird keine Aktualisierung durchgeführt.

Letzteres scheint die einfachste Problemumgehung zu sein, aber warum führt AngularJS nach meiner Funktion überhaupt Code aus, der das Neuladen der Seite bewirkt? Scheint wie ein Fehler.

Hier ist das Formular:

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

Hier ist die Controller-Methode:

$scope.showChangePassword = function() {
  $scope.selectedLink = "changePassword";
};
Chubbsondubs
quelle
Überprüfen Sie, ob dies Ihr Problem ist. Github.com/angular/angular.js/issues/1238 (Leider kenne ich mich mit Github nicht gut genug aus, um feststellen zu können, ob dieses Update in der Version 1.0.1 enthalten ist oder nicht.) .
Mark Rajcok
Ich habe das gesehen, aber ich ändere den Ort nicht, also denke ich nicht, dass es zutrifft. Es sei denn, diese andere Schaltfläche veranlasst sie irgendwie zum Senden, aber sie ist nicht als Übermittlungstyp definiert, und wenn ich den ng-Klick entferne, sendet die Schaltfläche das Formular nicht.
Chubbsondubs
Es wäre großartig, wenn Sie eine funktionierende Demo dieses Problems bereitstellen könnten. Vielleicht beginnend mit: Angular Plnkr
Pete BD
Scheint wie ein Duplikat. stackoverflow.com/questions/16703215/…
Vaibs

Antworten:

471

Wenn Sie sich die W3C-Spezifikation ansehen , ist es naheliegend, Ihre Schaltflächenelemente mit zu markieren, type='button'wenn Sie nicht möchten, dass sie gesendet werden.

Besonders zu beachten ist, wo es heißt

Ein Schaltflächenelement, für das kein Typattribut angegeben ist, entspricht einem Schaltflächenelement, dessen Typattribut auf "Senden" festgelegt ist.

LOAS
quelle
4
Ich habe das gleiche Problem wie OP, aber meine Schaltflächen haben den angegebenen Typ - und das Klicken bewirkt immer noch eine Aktualisierung. Gibt es noch andere Orte, an denen ich suchen könnte?
Mateo Velenik
Das deutet darauf hin, dass Ihr Problem in Javascript liegt. Das Problem, das meine Antwort anspricht, ist eher eine Frage zwischen dem Dom und dem Browser. Einige Javascript, die Ihren Schaltflächenklick verarbeiten, verursachen wahrscheinlich das Neuladen, das Sie sehen.
Viel
Genau das habe ich gesucht. Es war sehr nervig auf meiner Seite, weil es nur die Fehler anzeigen und nicht einreichen sollte.
reaper_unique
Ich habe meine Schaltflächen mit type = "button" markiert und habe auch das Problem. In meinem ng-click-Handler habe ich $ event.stopPropagation (). Wenn ich es entferne, wird es nicht neu geladen. Ich brauche es aber. Irgendwelche Ideen, warum es ein erneutes Laden der Seite verursacht?!
Felixfbecker
@freshfelicio: versuche auch hinzuzufügen $event.preventDefault(), das hat in meinem Fall geholfen. Aber ich habe keine Erklärung warum: - \
Tim Büthe
72

Sie können versuchen, den Standardhandler zu verhindern:

html:

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

js:

$scope.saveUser = function (event) {
  event.preventDefault();
  // your code
}
Antage
quelle
Nett! Es kam wirklich zu meinem Szenario!
Richard
2
Dies funktionierte für uns, wenn AngularJS in einem SharePoint-Formular verwendet wurde. Ich musste "event.stopPropagation ()" hinzufügen. aber auch.
Nick DeMayo
19

Sie sollten das Attribut ng-submit={expression}in Ihrem <form>Tag deklarieren .

Aus den ngSubmit-Dokumenten http://docs.angularjs.org/api/ng.directive:ngSubmit

Aktiviert das Binden von Winkelausdrücken an Onsubmit-Ereignisse.

Außerdem wird die Standardaktion verhindert (was für das Formular bedeutet, dass die Anforderung an den Server gesendet und die aktuelle Seite neu geladen wird).

Shane Stillwell
quelle
3
Stellen Sie außerdem sicher, dass für das Formular keine Aktionseigenschaft festgelegt ist: form (action = "/ login", lng-submit = "login ()"). Dadurch wird die Seite auch dann aktualisiert, wenn ng-submit festgelegt wurde .
Jenso
Senden eines Formulars und Verhindern von Standardaktionen Da sich die Rolle von Formularen in clientseitigen Angular-Anwendungen von der in klassischen Roundtrip-Apps unterscheidet, ist es wünschenswert, dass der Browser die Formularübermittlung nicht in ein erneutes Laden aller Seiten übersetzt, das die Daten an den Server sendet . Stattdessen sollte eine Javascript-Logik ausgelöst werden, um die Formularübermittlung anwendungsspezifisch zu behandeln. Aus diesem Grund verhindert Angular die Standardaktion (Formularübermittlung an den Server), es sei denn, für das <form> -Element ist ein Aktionsattribut angegeben. - docs.angularjs.org/api/ng.directive:form
Jignesh Gohel
Ich habe ein Formular mit ng-submit = {expression} und eine Schaltfläche mit type = "submit". Funktioniert wie gut, außer auf BB10. Wenn ich das Senden der BB10-Tastatur verwende, wird die Seite aktualisiert. Wenn ich die Schaltfläche verwende, die ich in meinem Formular deklariert habe, funktioniert sie einwandfrei.
Michael
Das funktioniert bei mir nicht. Ich habe die Anweisungen genau befolgt. Die Seite postet immer noch zurück
meffect
18

Ich benutze Direktive, um Standardverhalten zu verhindern:

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

Und dann in HTML:

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

Diese Anweisung kann auch mit <a>und allen anderen Tags verwendet werden

Pleerock
quelle
+1 Danke! Dies ist hilfreich, wenn Sie keinen Zugriff auf das <form>Tag haben und daher die ng-submitDirektive nicht verwenden können .
Jackvsworld
yow danke für dieses, aber ich muss auch ng-click in einer Direktive
abbrechen
Dies verhindert auch, dass das Formular den Rückruf ng-submit auslöst, oder?
Jhourlad Estrella
5

Sie können behalten <button type="submit">, müssen aber das Attribut action=""von entfernen <form>.

Anderson Ferreira
quelle
2

Ich frage mich, warum niemand die möglicherweise einfachste Lösung vorgeschlagen hat:

benutze kein a <form>

A <whatever ng-form>macht meiner Meinung nach einen besseren Job und ohne ein HTML-Formular kann der Browser selbst nichts einreichen. Welches ist genau das richtige Verhalten bei der Verwendung von Winkel.

Maaartinus
quelle
Wie erzwinge ich die Formulargültigkeit beim Klicken dann ohne Formular-Tag?
Rizwan Patel
1
@ RizwanPatel Ich denke, ich verstehe nicht, aber mit ng-form=someForm, bekommen Sie $scope.someFormund es hat ein $validFeld. So bekomme ich alles was ich brauche <button ng-disabled="!someForm.$valid">.
Maaartinus
1

Fügen Sie Ihrem Formular eine Aktion hinzu.

<form action="#">

Swapnil Patwa
quelle
1

Diese Antwort steht möglicherweise nicht in direktem Zusammenhang mit der Frage. Dies gilt nur für den Fall, dass Sie das Formular mithilfe von Skripten senden.

Laut ng-submit Code

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

  event.preventDefault();
};

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

Dem Formular wird der Listener für Übermittlungsereignisse hinzugefügt. Der Submit-Ereignishandler wird jedoch nicht aufgerufen, wenn Submit durch Aufrufen von form.submit () initiiert wird. In diesem Fall verhindert ng-submit die Standardaktion nicht. Sie müssen PreventDefault selbst im ng-submit-Handler aufrufen.

Um eine einigermaßen endgültige Antwort zu geben, gibt der HTML-Formularübermittlungsalgorithmus Punkt 5 an, dass ein Formular ein Übermittlungsereignis nur dann auslöst, wenn es nicht durch Aufrufen der Übermittlungsmethode übermittelt wurde (was bedeutet, dass es ein Übermittlungsereignis nur auslöst, wenn es über eine Schaltfläche oder ein anderes implizites Element übermittelt wird Methode, z. B. Drücken der Eingabetaste, während der Fokus auf einem eingegebenen Textelement liegt).

Siehe Formular, das mit submit () von einem Link gesendet wurde, kann vom onsubmit-Handler nicht abgefangen werden

user1577263
quelle
0

Der erste Button sendet das Formular und der zweite nicht

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

Fügen Sie einfach das FormsModulein das importsArray der app.module.tsDatei ein und fügen Sie es import { FormsModule } from '@angular/forms';oben in diese Datei ein ... das wird funktionieren.

Sahil Sharma
quelle