web-dev-qa-db-ja.com

AngularJSはグローバルngModelOptionsを設定します

NgModelの更新(およびその後の検証)のデフォルトの動作は、change;です。これをonblurに変更したいと思います。 docs これを行う方法をケースバイケースで説明するのは次のとおりです。<ANY ng-model-options="{ updateOn: 'blur' }"></ANY>。私はソースコードを調べましたが、どういうわけかngModelOptionsng-model-optionsも見つかりません(にもかかわらず)両方とも、ソースコードからスクレイピングされたドキュメントで発生します)。

26
jacob

Jon/Johnによって作成されたngModelデコレータは、舞台裏での優れたソリューションを提供しますが、宣言的に、ngModelOptionsは個々の入力フィールドレベルで宣言する必要はありませんが、宣言できることにも注意する必要があります。モジュールレベルで宣言されます。

<body ng-app = "myApp" ng-model-options="{ updateOn: 'blur' }">

上記を実行すると、myAppモジュールのすべての入力フィールドがng-model-optionsを継承します。これらは、必要に応じて特定の入力フィールドでオーバーライドできます(検索フィルターなど)。

このプランカーは次のことを示しています: http://plnkr.co/edit/2L1arGgHJwK82xVucJ4p?p=preview

25
Angad

@Angadが言及しているように、any要素にng-model-optionsを設定でき、それはそのすべての子孫に適用されます 。ただし、これに伴う問題は、このように設定すると、ラジオとチェックボックスが期待どおりに機能しなくなることです。

<body ng-app="myApp" ng-model-options="{ updateOn: 'blur' }">

これは、changeclickupdateOnに追加することで回避できます。

<body ng-app="myApp" ng-model-options="{ updateOn: 'change click blur' }">

入力後、一定の遅延後に更新する場合は、次を使用できます。

<body ng-app="myApp" ng-model-options="{ updateOn: 'keyup change click blur', debounce: { keyup: 500, click: 0, change: 0, blur: 0 } }">

Firefox、Chome、Internet Explorer(10、11)、Safariでこれらの手法をテストしました。他のイベントを使用する場合は、これらをクロスブラウザでテストしてください。たとえば、IEを除くすべてのブラウザで、クリックした直後にラジオがchangeを起動します。

23
Mark Lagendijk

これは本当に良い質問なので、もっと詳しく書いています これに関するブログ記事 。これを行うために私が思いついた唯一の実際の一般的な方法は、実際にngModelOptionsを使用するのはこのディレクティブであるため、ngModelディレクティブを装飾することです。

ngModel ディレクティブのangular sourceを見ると、プロパティ$ optionsを使用して、ngModelControllerでngModelOptionsを効果的に設定するためのリンク前関数があります。 $ optionsはngModelOptionsDirectiveで作成されることに注意してください。これは、実質的にng-model-options属性の$ evalです。

NgModelデクターで行う必要があるのは、このpre link関数の後に、この$ optionsプロパティが未定義の場合にデフォルト値を追加することです。ここでは、開発者がプロ​​ジェクトでngModelOptionsを明示的に設定している場合、魔法のように変更したくないと想定しています。したがって、$ optionsプロパティが未定義の場合にのみ、デフォルトを設定します。

コードは次のとおりです。

(function (angular) {
'use strict';

angular.module('myAppOverridesModule').config(['$provide',
    function ($provide) {
        $provide.decorator('ngModelDirective', [
            '$delegate',
            function ($delegate) {
                var directive = $delegate[0],
                    link = directive.link,
                    shouldSetBlurUpdateEvent = function (nodeName, inputType) {
                        // The blur event is only really applicable to input controls so
                        // we want to stick with the default events for selects, checkboxes & radio buttons
                        return nodeName.toLowerCase() === 'textarea' ||
                               (nodeName.toLowerCase() === 'input' && 
                               inputType.toLowerCase() !== 'checkbox' && 
                               inputType.toLowerCase() !== 'radio');
                    };

                directive.compile = function () {
                    return function (scope, element, attrs, ctrls) {
                        var ngModelCtrl = ctrls[0];
                        link.pre.apply(this, arguments);

                        // if ngModelOptions is specified leave it unmodified as developer is explicitly setting it.
                        if (ngModelCtrl.$options === undefined && shouldSetBlurUpdateEvent(element[0].nodeName, element[0].type)) {
                            console.log('set');
                            ngModelCtrl.$options = {
                                updateOn: 'blur',
                                updateOnDefault: false
                            };
                        }

                        link.post.apply(this, arguments);
                    };
                };

                return $delegate;
            }
        ]);
    }
]);
}(angular));

更新:blurイベントは最適な更新イベントではないため、選択、チェックボックス、ラジオボタンを無視するようにコードを更新しました。

12
Jon

ジョン・サムウェルの答えを修正したのは、彼をもう働かせることができなかったからです。

これは、ngModelDirectiveのコンパイル関数への参照を格納し、元の関数と追加のオーバーライドコードを呼び出して、pre/postLink関数を返すことでオーバーライドします。

楽しい!

app.config(function($provide) {

    $provide.decorator('ngModelDirective', function($delegate) {
        var directive = $delegate[0],
            link = directive.link,
            shouldSetBlurUpdateEvent = function (nodeName, inputType) {
              // The blur event is only really applicable to input controls so
              // we want to stick with the default events for selects, checkboxes & radio buttons
              return nodeName.toLowerCase() === 'textarea' ||
                    (nodeName.toLowerCase() === 'input' && 
                     inputType.toLowerCase() !== 'checkbox' && 
                     inputType.toLowerCase() !== 'radio');
                };

        // save a reference to the original compile function
        var compileFn = directive.compile;

        directive.compile = function () {   

            var link = compileFn.apply(this, arguments);

            return {
                pre: function ngModelPostLink(scope, element, attr, ctrls) {

                    if(!ctrls[2]) {
                        ctrls[2] = {};
                    }

                    var ngModelOptions = ctrls[2];

                    if (ngModelOptions.$options === undefined && shouldSetBlurUpdateEvent(element[0].nodeName, element[0].type)) {
                        ngModelOptions.$options = {
                            updateOn: 'blur',
                            updateOnDefault: false
                        };
                    }

                    link.pre.apply(this, arguments);
                },
                post: link.post
            };
        };

        return $delegate;
    });

});
5
John Strickler

使用する代わりに

ng-model-options="{ updateOn: 'blur' }

あなたが使うことができます

ng-model-options="{ debounce : { default : 500 } }"

コンテナdivなどのdomの親要素に適用します。上記のdebounce設定は、Angularが、500ミリ秒のアクティビティがない場合にのみ検証ルールを評価するように指示します。

この方法でdebounceを使用すると、blurを使用するよりも優れています。これは、ぼかしをフォーム全体に適用すると、ラジオとチェックボックスに問題が発生するためです。

デバウンスオプションは整数値であり、モデルの更新で整数ミリ秒の遅延が発生します。これにより、$digestサイクルが発生する頻度が減り、jsアプリケーションが消費するリソースが少なくなるだけでなく、検証ルールが適用される前にユーザーが入力できるようになります。

YearOfMoo.com このようにぼかしとデバウンスを一緒に使用することをお勧めします

ng-model-options="{ debounce : { default : 500, blur : 0 } }"

これで、モデル値と検証は、ユーザーがフィールドから離れた直後に適用されます。これにより、blurイベントの待機時間が0ミリ秒に設定されます。ぼかしはデフォルト値を上書きします。

2
steampowered