4

このjsFiddleでテストできます:こちら (新しいjsFiddleで確認することをお勧めします。この投稿の編集部分を参照してください)

AngularJS にバグがあるか、少なくとも期待どおりの結果ではないと思います。フォームをデタッチしてから再追加すると、DOM に再追加するクラスng-invalidスイッチになります。ng-validこれにより、データが有効でない場合でもフォームの送信ボタンが有効になります。もちろん、有効ステータスが切り替わらないことを期待していました。

これは角度のあるバグだと思いますが、おそらくjqueryのバグです。jquery を使用して追加をチェックし、フォームが有効かどうかを確認してからフォーム クラスを強制することもできますが、有効なフォームが無効のステータスを取得するので機能していないようです。デタッチする前にステータスフォームを保存するためにある種のデータを使用しないと、他の回避策がわからないので、それは非常に奇妙です。

では、すでにこの問題に遭遇した人はいますか? このバグを取り除く方法 (可能であれば AngularJS ディレクティブを使用) はありますか?

PS: DOM をできるだけきれいに保つために、単一ページの Web アプリケーションでフォーム (およびその他の要素) を切り離す必要があります。

編集

私の問題をさらに説明する新しいjsFiddleを実行し、内部サイトナビゲーションのコンテンツを切り離しました: http://jsfiddle.net/EWVwa/

アップデート

この一時的な解決策にたどり着きました(CaioToOnのおかげです)

http://plnkr.co/edit/KIgMz2

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  $scope.name = 'World';
});


app.directive('customValidation', function() {
  return {
    require: ['ngModel', '^?form'],
    link: function(scope, element, attr, ctrls) {
      console.log(ctrls);
      var ngModelCtrl = ctrls[0],
          formCtrl = ctrls[1];


      ngModelCtrl.$parsers.push(function(viewValue) {
        if (viewValue === 'test') {
          ngModelCtrl.$setValidity('name', true);
          formCtrl.$setValidity('name', true);
          return viewValue;
        } else {
          ngModelCtrl.$setValidity('name', false);
          formCtrl.$setValidity('name', false);
          return undefined;
        }
      });


      // custom event
      element.bind('$append', function() {
        formCtrl && formCtrl.$addControl(ngModelCtrl);
        /*** TEST for to keep form's validation status ***/
        formCtrl.$setValidity('name', ngModelCtrl.$valid);
        //ngModelCtrl.$setValidity('name', ngModelCtrl.$valid);
        console.log(formCtrl.$valid);
      });
      //binding on element, not scope. 
      element.bind('$destroy', function() {
        console.log("gone haven");        
      });
    }
  };
});

これには、複数の入力の検証に関するより多くのテストが必要です。すべてのテストが完了したら、必ず回答を更新します。

4

1 に答える 1

3

この問題は、要素が DOM から削除されると、フォーム コントロールからinputディレクティブ自体が削除されるために発生します。ngModelフォームコントローラーと再度リンクしないため、入力はフォームによって考慮されなくなります。

基本的に、2 つの 3 つのオプションがあります。

  • 要素の可視性を削除する代わりに変更する
  • (以下のものが望ましい)元のフォームに再追加する「再リンク」機能を公開する
  • すべてのコントロールでカスタム イベントをトリガーして、自分自身を再リンクできるようにする

要素の可視性を変更すると、DOMTree に不要な DOM 要素が含まれることになります。とにかく $compile 要素への参照を保持しているため、これはそれほど悪くはありません。したがって、$digestサイクルと「DOM」の変更にまだ参加します。

(しばらく考えた後、新しいソリューションはこれよりもわずかに優れているため、再リンク機能を公開しないでください)再リンク機能を公開することは (機能的ではありますが) 非常に奇妙であり、これはソリューションの中で最も信頼できるものではありません。これを実現する 1 つの方法は、フォーム コントローラー ( require: ['ngModel', '^?form']) を要求し、要素のデータに再リンク関数をバインドすることです。

element.data('relink', function(){
  formCtrl && formCtrl.$addControl(ngModelCtrl);
});

要素を画面に再度追加するときは、すべてのコントロールの relink 関数を呼び出す必要があります。

$('.controls').data('relink')();

ここで例を参照してください。

信頼性は高くありませんが、あなたの場合にはうまくいくかもしれません。

カスタム イベントのトリガーは前とほぼ同じですが、再リンクする必要があるすべての要素にカスタム イベントをディスパッチします。これはかなり整理されていますが、フォームやその他のリンクも壊れている可能性があるため、信頼性は高くありません (これで十分です)。基本的に、ディレクティブでカスタム イベントをリッスンします。

element.bind('$append', function(){
  formCtrl && formCtrl.$addControl(ngModelCtrl);
});

フォームに変更したら、すべてのコントロールでカスタム イベントをトリガーします。

$('.control').triggerHandler('$append');

これが優れている理由は、ディレクティブがコンポーネントをいつ再リンクするかを決定し、イベントが一種の「一般的」であるためです。これが動作中の plunkerです。

最後の努力として、すべての要素の子でカスタム イベントを再帰的にオーバーライドしてトリガーすることができますjQuery.fn.append(これは、要素を削除するときにAngular が行うことです)。これは最も整理された方法ですが、すべての通話のパフォーマンスに影響を与えappendます。

于 2013-04-20T18:15:42.317 に答える