2

シンプルな HTML5 ユーザー登録フォームがあります。inputに追加されたカスタム関数を使用して、同じユーザー名を持つユーザーが存在しないことを確認するために、ユーザー名の値が検証され$asyncValidatorsます。

次の状況を考慮してください。

  1. ユーザーがユーザー名 (「Me」など) の入力を開始します。
  2. 少し遅れて、Angular バリデーターが実行され、ユーザー名が使用可能かどうかを尋ねる非同期要求がサーバーに送信されます。
  3. ユーザーはさらに文字を入力し始めます (たとえば、'Me123')。
  4. 少し遅れて、Angular はサーバーに別のリクエストを送信して、ユーザー名の検証を再度試みます。

ユーザー名の有効性に関して 2 つの応答を受け取った場合、Angular は何をしますか? これを優雅に処理する方法はありますか?

私がやりたいことは、ユーザーがユーザー名の値を変更するとすぐに、最初の検証試行の結果をキャンセルするか、Angular に無視するように指示することです。


編集 11/12/2015:

シロッコの答えは、私の質問を明確にするのに役立ちました。ここには 2 つの部分があります。

  1. 実際の HTTP リクエストを中止する
  2. Angular 検証プロセスに、返された promise$asyncValidators.usernameAvailableが解決または拒否されるのを待つのをやめるように指示します。

timeoutサービスのオプションを使用して、最初のことができました$http。私の質問は次のとおりです。2番目のことを行う必要があるか、望ましいか、または可能ですか? もしそうなら、どのように?

keyupこれは、ディレクティブの要素に追加されたイベント ハンドラーで発生する可能性があると考えていlinkます。下記参照:

index.html

<input 
  ng-model="user.username" 
  ng-model-options="{ debounce: 250 }" 
  check-availability />

checkAvailability.directive.js

function affectsText(keyCode) {
  // some code to determine if keyCode could change value of a text input
}

angular
  .module('app')
  .directive('checkAvailability', ['$q', 'users', function($q, users) {
    return {
      restrict: 'AC',
      require: 'ngModel',
      link: function (scope, element, attrs, ctrl) {
        element.on('keyup', function(e) {
          if (!affectsText(e.keyCode)) {
            return;
          }

          // cancel previous $asyncValidators.usernameAvailable process??

          // users service cancels operation by rejecting a promise previously assigned to to $http's timeout option
          users.cancelIsAvailableCheck();
        });

        ctrl.$asyncValidators.usernameAvailable = function(modelValue) {
          if (ctrl.$isEmpty(modelValue)) {
            return $q.when();
          }

          var deferred = $q.defer();

          users.isAvailable(modelValue).then(function(available) {
            if (available) {
              deferred.resolve();
            } else {
              deferred.reject();
            }
          });

          return deferred.promise;
        }
      }
    };
  }]);
4

1 に答える 1

1

最も簡単な方法は、次のようなユーザー入力を無効にすることです。

<input 
  name="username"
  ng-model="user.username" 
  ng-model-options="{ updateOn: 'blur' }"
  ng-disabled="myForm.$pending"
  check-availability />

したがって、ユーザーがユーザー名フィールドからタブで移動すると、検証がトリガーされ、フィールドが無効になります (送信ボタンを無効にすることもできます)。

それが許容できる UX でない場合は、代わりにここで説明されている方法を使用できます: http://www.bennadel.com/blog/2616-aborting-ajax-requests-using-http-and-angularjs.htm

基本的$httpに、Promise をそのtimeoutプロパティに設定できます。そのプロパティを次にresolve指定すると、http 呼び出しは中止されます。バリデータ内で最適なアプローチを見つけるには、試行錯誤が必要になる場合があります。

于 2015-11-12T06:27:18.237 に答える