Angularjsは、入力検証が失敗したときにフォームの送信を防ぎます


155

ユーザー名とパスワードが空でなく、3文字を超えていないことを確認するために、クライアント側の入力検証を伴うAngularJSを使用した簡単なログインフォームを書いています。以下のコードを参照してください:

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

そしてコントローラー:

var controller = function($scope) {

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

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

};

問題はlogin.submit、入力が無効な場合でも関数が呼び出されることです。この動作を防ぐことは可能ですか?

補足として、私はブートストラップとrequirejsも使用していることを述べます。



formタグなしでそれを使用できますか?それでもform.validはng-clickで動作します!
Rizwan Patel

回答:


329

できるよ:

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

コントローラのチェックは必要ありません。


8
これは受け入れられる答えになるはずです。コントローラーで何もチェックする必要はありません
ハウィー

10
「コントローラのチェックは不要」には同意しません。送信機能で追加の検証チェックが発生するとどうなるでしょうか。
SlaterCodes 2014

6
ディレクティブで追加の検証を実行します。$ setValidityで検証を更新します。
TMB

@ b1tsh1ft提出時に把握するのではなく、検証の現在の状態を常に把握しておくことが望ましいでしょう。これが、angularの検証の要点です。スコープがそれを認識していない場合、無効な状態を視覚的に示すことはできません。
Kevin Beal 2015年

1
私はこのアプローチを試しましたが、両方を評価しているようです(つまり&&、送信の一部として値を渡してブール値を短絡させず、値自体が「false」であることを確認した後
Archimedes Trajano

67

送信ボタンを次のように変更します。

<button type="submit" ng-disabled="loginform.$invalid">Login</button>

1
すばらしい答えです。あなたはロック!
Harsha.Vaswani 2015年

24
入力フィールドにフォーカスがあるときにEnterキーを押すと、フォームを送信できます。
fabsenet、2015年

2
@赤:上記のコメントを参照してください。
AndreiRînea15年

通常、ボタンを無効にすることがこれを解決する最良の方法ですが、OPが要求するものではありません。
2016年

1
この手法と@Yashuaの回答を組み合わせてユーザーに視覚的なフィードバックを提供し、フォームの送信を防ぐのは完璧です。ありがとう!
tkarls

43

したがって、TheHippoからの提案された答えは私にとってはうまくいきませんでしたが、代わりに次のように関数へのパラメータとしてフォームを送信することになりました:

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

これにより、コントローラーメソッドでフォームを使用できるようになります。

$scope.login = {
    submit : function(form) {
        if(form.$valid)....
    }

同じ問題がありました。しかし、あなたの方法を使うことはうまくいきました。
Panda4Man 2014

form。$ validチェックはHTMLではなくJSで行われるため、これはAccepted Answerよりもわずかに優れています。
cellepo

ただし、関数を送信するためにloginFormを渡す必要はないと思います。$ scope.loginformはJSで利用できるはずです(少なくとも私にとってはそうでした)。form。$ validを$ scope.loginformに置き換えることができます。 。$有効。
cellepo

13

フォームは$ scopeにオブジェクトとして自動的に配置されます。経由でアクセスできます$scope[formName]

以下は、ng-submitのパラメーターとしてフォーム自体を渡すことなく、元の設定で機能する例です。

var controller = function($scope) {

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

        }
    }

};

作業例:http : //plnkr.co/edit/BEWnrP?p=preview


4
$ scopeの代わりに「As Controller」表記を使用する場合、フォームにどのようにアクセスしますか?
masimplo 2013

@masimakopoulos:if(this.loginform.$invalid)代わりに..を使用できますが、HTMLでフォームに名前を付ける必要があります<form name="ctrl.loginform" ..。そして、それ<div ng-controller="controller as ctrl"..はあなたがコントローラとしての構文で使用していることを前提としています。ありがとう@JoshCaroll
Bart

13

HTML:

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

コントローラで:

$scope.login = {
    onSubmit: function(event) {
        if (dataIsntValid) {
            displayErrors();
            event.preventDefault();
        }
        else {
            submitData();
        }
    }
}

onsubmitメソッド内でチェックを行う必要がありますか?これは、入力がマークアップ(angularを使用)とjsコードの両方ですべての基準を満たしていることを確認する必要があることを意味します。私の意見では、入力が無効な場合、angularはonsubmitを呼び出すべきではありません。benlesh.com/2012/11/angular-js-form-validation.htmlを参照して、「フォーム全体が$ validになるまでng-submitを呼び出すことはできません」
Runar Halse

フォームが有効な場合、ボタンを無効にして送信を許可しないこともできます。ng-submitの形式を使用することもできます。angularがフォームの検証を処理しない場合event.preventDefault()は、フォームの送信を停止する方法です。
TheHippo 2013

@RunarHalseチェックを行うことが本当に必要です。このようにしてはいけないということに同意します。リンクした例でonsubmitメソッドが呼び出されないのは、その例にはnovalidateが設定されていないためです。ブラウザは、Angularではなく、イベントの発生を防止しています。以下は、nobalidateを使用した彼の例です。フォームが送信されることに注意してください。
davidmdem 2013

まさに私が探していたもの、angularを使用してフォームの送信をブロックする方法
setebos

3

OPの質問に対する直接的な解決策ではありませんが、フォームがng-appコンテキスト内にあるが、Angularに完全に無視させたい場合は、ngNonBindableディレクティブを使用してこれを明示的に行うことができます。

<form ng-non-bindable>
  ...
</form>

2

上記の答えに追加するだけで、

以下に示すように、2つの通常のボタンがありました。(type = "submit"はどこにもありません)

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

どれだけ試しても、フォームが有効になったらEnterキーを押すと、[フォームのクリア]ボタンが呼び出され、フォーム全体がクリアされました。

回避策として、

無効になって非表示になっているダミーの送信ボタンを追加する必要がありました。また、このダミーボタンは、以下に示すように、他のすべてのボタンの上に配置する必要があります

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

まあ、私の意図はEnterでサブミットすることではなかったので、上記のハックはうまく機能しました。


フォームからon ng-submit属性を削除することでも、Enterキーを押すと送信を停止できます
Kieran

1

これは古いスレッドであることは知っていますが、私も貢献したいと思いました。私の解決策はすでに回答としてマークされた投稿に似ています。いくつかのインラインJavaScriptチェックでうまくいきます。

ng-click="form.$invalid ? alert('Please correct the form') : saveTask(task)"

1
入力フィールドにフォーカスがあるときにEnterキーを押すと、フォームを送信できます。
Yevgeniy Afanasyev 2015

0

遅くなって答えられたのはわかっていますが、私が作ったきちんとしたものを共有したいと思います。フォームのonsubmitをフックするng-validateディレクティブを作成し、$ evalがfalseの場合にprevent-defaultを発行します。

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();            
    });
  };
});

あなたのhtmlで:

<form name="offering" method="post" action="offer" ng-validate="<boolean expression">
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.