2

ctrl.$setValidityディレクティブの 1 つで使用して、フォームを無効にします。ただし、別の条件でこの要素を DOM から削除できるメソッドが別の場所にあります。フォームを無効にし$setValidityて問題のある要素を削除すると、フォームは無効のままになりますが、新しい Inputfield セットに基づいて有効性を再計算する必要があります。

単に , を探しているわけではないことに注意してくださいctrl.$setValidity true(フォームの他の入力フィールドが有効である場合と無効である場合があります)。フォームを再計算するだけです。

以下は、ディレクティブ コードです。

 app.directive('dir', function() {
   return {
      restrict: 'C',
      require: "ngModel",
      link: function(scope, element, attrs, ctrl) {
      someValue = scope.someValue;
      someField = element.find(".some-class");

      monitorField = function(newValue, oldValue){
        console.log("whee");
        scope.someFunction(newValue);
        if(newValue =="Invalidate NOW!"){
        ctrl.$setValidity('someClass', false);      
        } else if (oldValue == "Invalidate NOW!"){
           angular.element(document.querySelector('.some-class')).remove();
        } else {
          ctrl.$setValidity('someClass', true); 
       }
    }  
    scope.$watch("someValue", monitorField, true);
   }
 }
});

以下で動作します:

   <FORM class="dir" ng-model="someValue">
     <INPUT type="text" class="some-class" ng-model="someValue"/>
     <INPUT type="text" class="some-other-class"/>
   </FORM>

(はい、やや不自然な例です)。

問題はここで再現されます: http://jsfiddle.net/kTuAY/

私の実際のコードでは、オブジェクトの配列に基づいて入力フィールドにデータを入力します。これは Service を介して入力され、array.splice を介して要素を削除します。jsfiddle に示されている例は、単純にするためにあるだけです。

このフィドルには、別の興味深い失敗の状態が見られます。

http://jsfiddle.net/JACAv/

具体的には、入力の 1 つが他のフィールドとの値の衝突がないことに依存しているため、無効化された後、他のフィールドの値が変更された場合、有効性は不正確なままになります。

仕事に行く間、一時的に機能しないフィドル:

http://jsfiddle.net/yQpHL/

ありがとう!

4

3 に答える 3

2

モデルの一部にリンクされている DOM 要素を削除するには、可能であれば、モデルが指している $scoped オブジェクトの一部を削除する必要があります。基本的な ngRepeat について考えてみてください。配列から項目を削除すると、DOM から要素が削除されます。フォームも同じように機能するはずです。これにより、それが発生するのを防ぐことができます。すべての検証情報は、 $scope 内のモデルに含まれています... $scope.myForm.model.$error.requiredたとえば。モデルが指している $scope プロパティまたは配列項目 (たとえば、$scope.fooまたはを削除する$scope.items.splice(2,1)と、Angular は (おそらく次の $digest 中に) モデルとその検証情報を削除することを認識します。

コントローラーまたはディレクティブでアイテムを削除するかどうかは問題ではありませんが、$scope から削除する必要があります。その後、UI と検証を更新するためにダイジェストを実行する必要があります。

私が言おうとしていたことにつまずいたような気がするので、それが役に立てば幸いです...

于 2013-01-18T22:27:59.190 に答える
0

私がこれを解決した方法は次のとおりです。

  1. 終わっている配列に別のウォッチ式を置きng-repeatedます。
  2. そのウォッチ式内で、関連するディレクティブに一致する入力フィールドに現在存在するすべての値のハッシュを作成します。
  3. これらのフィールドの値を で強制的にリセットし、内部フィールドを.val()呼び出し$compileて内部ウォッチ式を再トリガーします
  4. ctrl.$setValidityコントローラーに入力フィールドの値を追加する関数内 (内部ディレクティブから直前に呼び出される関数:
    • 値の入力回数が 1 回であることを確認します。
    • ハッシュの値を含むように ng-repeat されている配列をリセットします

いいもの:

  • 要素が削除されると、外側のウォッチ (配列全体のウォッチ) がトリガーされ、ハッシュが再計算され、各フィールドの値がリセットされ、再検証されます。
  • 衝突が検出されると、正しくバブリングし、衝突するすべてのフィールドが無効としてマークされ、衝突が除去されると、すべてのフィールドが再検証されます
悪い人:
  • 配列が変更されるたびにすべてのフィールドで $compile を呼び出すのは計算効率が悪い
  • 内側のウォッチ式は、値が変更されたときに 1 回トリガーされ、外側のウォッチ式が compile を呼び出したときに 1 回トリガーされるため、実質的に$digest's の数は 2 倍になります。

コードをサニタイズしたらすぐにコード例をまとめます。

于 2013-01-25T09:38:52.567 に答える
0

問題はディレクティブにあるとは思いません。「その他」のコードにあります。

DOM 要素の削除が「ネイティブ」イベント (つまり、ドラッグ アンド ドロップ イベント、ajax イベントなど) に応答して行われた場合、Angular フレームワークはそれ自体で再計算を実行することを認識しません。更新が完了した後のこのコードでは、適切なスコープで $scope.$apply() を呼び出す必要があります。

ああ、あなたのフィドルが見えます...わかりました。DOM 要素を削除する代わりに、ng-show 属性で装飾し、angular に残りの処理を任せてみませんか?

于 2013-01-18T22:09:00.237 に答える