Angularjs verhindern das Senden von Formularen, wenn die Eingabevalidierung fehlschlägt

155

Ich schreibe ein einfaches Anmeldeformular mit anglejs mit einer clientseitigen Eingabevalidierung, um zu überprüfen, ob der Benutzername und das Kennwort nicht leer und länger als drei Zeichen sind. Siehe den folgenden Code:

<form name="loginform" novalidate ng-submit="login.submit()" class="css-form">
    <fieldset>

        <div class="control-group input-prepend">
            <span class="add-on"><i class="icon-user"></i></span>
            <input type="text" ng-model="login.username" name="username" required ng-minlength="3" placeholder="username" />
        </div>

        <div class="control-group input-prepend">
            <span class="add-on"><i class="icon-lock"></i></span>
            <input type="password" ng-model="login.password" name="password" required ng-minlength="3" placeholder="" />
        </div>

        <div class="control-group">
            <input class="btn" type="submit" value="Log in">
        </div>

    </fieldset>
</form>

Und der Controller:

var controller = function($scope) {

    $scope.login = {
        submit: function() {

            Console.info($scope.login.username + ' ' + $scope.login.password);
        }
    }

};

Das Problem ist, dass die login.submitFunktion auch dann aufgerufen wird, wenn die Eingabe ungültig ist. Ist es möglich, dieses Verhalten zu verhindern?

Als Randnotiz kann ich erwähnen, dass ich auch Bootstrap und Requirejs verwende.

Runar Halse
quelle
können wir es ohne Formular-Tag verwenden und trotzdem würde form.valid auf ng-click funktionieren!
Rizwan Patel

Antworten:

329

Du kannst tun:

<form name="loginform" novalidate ng-submit="loginform.$valid && login.submit()">

Keine Notwendigkeit für Controller-Überprüfungen.

Cyberwombat
quelle
8
Dies sollte die akzeptierte Antwort sein. Keine Notwendigkeit, irgendetwas in der Steuerung zu überprüfen
Howie
10
Ich bin nicht einverstanden mit "keine Notwendigkeit für Controller-Überprüfungen". Was ist, wenn wir zusätzliche Validierungsprüfungen in der Submit-Funktion durchführen?
SlaterCodes
6
Führen Sie die zusätzliche Validierung in der Direktive durch. Aktualisieren Sie die Validierung mit $ setValidity.
TMB
@ b1tsh1ft Es ist vorzuziehen, dass der aktuelle Status der Validierung immer bekannt ist, anstatt beim Senden herausgefunden zu werden. Das ist irgendwie der springende Punkt bei der Validierung von Angular. Sie können keinen visuellen Hinweis auf einen ungültigen Status erhalten, wenn der Bereich nichts davon weiß.
Kevin Beal
1
Ich habe diesen Ansatz ausprobiert, aber es scheint, dass er beide bewertet (dh den Booleschen &&Wert nicht kurzschließt, nachdem ich versucht habe, den Wert als Teil des Submit zu übergeben, und bestätigt habe, dass der Wert selbst "falsch" ist
Archimedes Trajano
67

Ändern Sie die Schaltfläche "Senden" in:

<button type="submit" ng-disabled="loginform.$invalid">Login</button>
Bijan
quelle
1
Gute Antwort. Du rockst!
Harsha.Vaswani
24
Sie können das Formular weiterhin senden, wenn Sie die Eingabetaste drücken, während ein Eingabefeld den Fokus hat!
Fabsenet
2
@ Red: Siehe Kommentar oben.
Andrei Rînea
Das Deaktivieren der Schaltfläche ist normalerweise der beste Weg, um dies zu beheben. Es ist jedoch nicht das, wonach das OP gefragt hat.
Downhand
1
Die Kombination dieser Technik, um dem Benutzer visuelles Feedback zu geben, mit der Antwort von @Yashua, um das Senden von Formularen zu verhindern, ist perfekt. Vielen Dank!
Karls
43

Die vorgeschlagene Antwort von TheHippo funktionierte also nicht für mich, sondern ich schickte das Formular als Parameter an die Funktion wie folgt:

<form name="loginform" novalidate ng-submit="login.submit(loginForm)" class="css-form">

Dadurch wird das Formular in der Controller-Methode verfügbar:

$scope.login = {
    submit : function(form) {
        if(form.$valid)....
    }
Runar Halse
quelle
Ich hatte das gleiche Problem. Die Verwendung Ihrer Methode hat jedoch funktioniert.
Panda4Man
Dies ist etwas besser als die akzeptierte Antwort, da die Prüfung des Formulars $ in JS und nicht in HTML erfolgt.
Cellepo
Ich glaube jedoch nicht, dass Sie loginForm übergeben müssen, um die Funktion zu senden: Ich denke, $ scope.loginform sollte im JS verfügbar sein (zumindest für mich), damit Sie form. $ Valid durch $ scope.loginform ersetzen können $ gültig.
Cellepo
13

Ihre Formulare werden automatisch als Objekt in $ scope eingefügt. Es kann über zugegriffen werden$scope[formName]

Unten finden Sie ein Beispiel, das mit Ihrem ursprünglichen Setup funktioniert und ohne das Formular selbst als Parameter in ng-submit übergeben zu müssen.

var controller = function($scope) {

    $scope.login = {
        submit: function() {
            if($scope.loginform.$invalid) return false;

        }
    }

};

Arbeitsbeispiel: http://plnkr.co/edit/BEWnrP?p=preview

davidmdem
quelle
4
Wie würden Sie auf das Formular zugreifen, wenn Sie die Notation "Als Controller" anstelle von $ scope verwenden?
Masimplo
@masimakopoulos: Sie können einfach if(this.loginform.$invalid).. verwenden, aber dann müssen Sie im HTML dem Formular den Namen geben <form name="ctrl.loginform" ... Und das setzt voraus, dass Sie <div ng-controller="controller as ctrl"..in Ihrer Controller-as-Syntax verwenden. Vielen Dank @JoshCaroll
Bart
13

HTML:

<div class="control-group">
    <input class="btn" type="submit" value="Log in" ng-click="login.onSubmit($event)">
</div>

In Ihrem Controller:

$scope.login = {
    onSubmit: function(event) {
        if (dataIsntValid) {
            displayErrors();
            event.preventDefault();
        }
        else {
            submitData();
        }
    }
}
TheHippo
quelle
Ist es wirklich notwendig, die Prüfung innerhalb der onsubmit-Methode durchzuführen? Dies bedeutet, dass Sie überprüfen müssen, ob die Eingabe alle Kriterien sowohl im Markup (über Winkel) als auch im js-Code erfüllt. Meiner Meinung nach sollte Angular das Onsubmit nicht aufrufen, wenn die Eingabe ungültig ist. siehe benlesh.com/2012/11/angular-js-form-validation.html mit der Aussage "ng- submit kann nicht aufgerufen werden, bis das gesamte Formular $ valid ist"
Runar Halse
Sie können die Schaltfläche auch deaktivieren, um die Übermittlung nicht zuzulassen, wenn das Formular gültig ist. Sie können auch das Formular ng-submit verwenden. Wenn Angular die Formularvalidierung nicht übernimmt, event.preventDefault()ist dies der richtige Weg, um die Formularübermittlung zu stoppen.
TheHippo
@ RunarHalse Es ist wirklich notwendig, die Prüfung durchzuführen. Ich stimme Ihnen zu, dass es nicht so sein sollte. Der Grund dafür, dass die onsubmit-Methode in dem von Ihnen verknüpften Beispiel nicht aufgerufen wird, liegt darin, dass in diesem Beispiel kein Novalidate festgelegt wurde. Der Browser verhindert, dass die Ereignisse ausgelöst werden, nicht Angular. Hier ist sein Beispiel mit nobalidate auf: plnkr.co/edit/R0C8XA?p=preview . Beachten Sie, dass das Formular gesendet wird.
Davidmdem
perfektionieren genau das, was ich suchte, senden Sie eine Art und Weise zu Blockform mit Winkel
Setebos
3

Obwohl dies keine direkte Lösung für die OP-Frage ist ng-app, können Sie dies explizit mithilfe der ngNonBindableDirektive tun , wenn sich Ihr Formular in einem Kontext befindet, Angular es jedoch vollständig ignorieren soll :

<form ng-non-bindable>
  ...
</form>
Ian Clark
quelle
2

Nur um die obigen Antworten zu ergänzen,

Ich hatte 2 normale Tasten wie unten gezeigt. (Kein Typ = "Submit" irgendwo)

<button ng-click="clearAll();" class="btn btn-default">Clear Form</button>
<button ng-disabled="form.$invalid" ng-click="submit();"class="btn btn-primary pull-right">Submit</button>

Egal wie viel ich versucht habe, die Eingabetaste zu drücken, sobald das Formular gültig war , wurde die Schaltfläche "Formular löschen" aufgerufen, wodurch das gesamte Formular gelöscht wurde.

Um dieses Problem zu umgehen,

Ich musste einen Dummy-Submit-Button hinzufügen, der deaktiviert und ausgeblendet war. Und dieser Dummy-Button musste über allen anderen Buttons liegen, wie unten gezeigt .

<button type="submit" ng-hide="true" ng-disabled="true">Dummy</button>

<button ng-click="clearAll();" class="btn btn-default">Clear Form</button>

<button ng-disabled="form.$invalid" ng-click="submit();"class="btn btn-primary pull-right">Submit</button>

Nun, meine Absicht war es nie, bei Enter einzureichen, also funktioniert der oben angegebene Hack einfach einwandfrei.

vighnu
quelle
Sie können die Übermittlung bei gedrückter Eingabetaste beenden, indem Sie das Attribut on ng-submit aus Ihrem Formular entfernen
Kieran
1

Ich weiß, dass dies ein alter Thread ist, aber ich dachte, ich würde auch einen Beitrag leisten. Meine Lösung ähnelt dem Beitrag, der bereits als Antwort markiert wurde. Einige Inline-JavaScript-Überprüfungen reichen aus.

ng-click="form.$invalid ? alert('Please correct the form') : saveTask(task)"
Dave Russell
quelle
1
Sie können das Formular weiterhin senden, wenn Sie die Eingabetaste drücken, während ein Eingabefeld den Fokus hat!
Jewgenij Afanasjew
0

Ich weiß, dass es spät ist und beantwortet wurde, aber ich möchte die netten Sachen teilen, die ich gemacht habe. Ich habe eine ng-validate-Direktive erstellt, die das Onsubmit des Formulars verknüpft. Wenn das $ eval false ist, wird dann die Vorbeugung ausgeführt.

app.directive('ngValidate', function() {
  return function(scope, element, attrs) {
    if (!element.is('form'))
        throw new Error("ng-validate must be set on a form elment!");

    element.bind("submit", function(event) {
        if (!scope.$eval(attrs.ngValidate, {'$event': event}))
            event.preventDefault();
        if (!scope.$$phase)
            scope.$digest();            
    });
  };
});

In Ihrem HTML:

<form name="offering" method="post" action="offer" ng-validate="<boolean expression">
Ran Cohen
quelle