4

背景:私はフォームがダーティーな場合は停止ナビゲーションを作成しようとしています。私はSOに関するいくつかの質問/例を見てきましたが、やや機能的ですが、正しくはないものをまとめました。このディレクティブをWebアプリケーション全体の複数のフォームの属性として使用しようとしています。同一のディレクティブを使用する同じページ上の複数のフォームと、要素ディレクティブ内の1つのフォーム

問題:私は2つの<form>要素(「Form1の」および「Form2の」)<tab>要素内にネストされて含まれているページがあります。 Form2は、カスタム要素ディレクティブの内部にさらにネストされます。

フォームが汚れていて、別のページに移動しようとすると(UIルーターの変更)、私たちのプロンプトサービスから期待されるカスタムプロンプトが表示されます。しかし、私がページをリロードしようとすると、form2が汚れているときにのみ、ブラウザでプロンプトが表示されます。 form1が汚れている場合は、プロンプトは表示されません。

form1が汚れていて、リロードなどのウィンドウイベントが発生したときにブラウザのプロンプトを生成する方法を教えてもらえますか?


RELEVANT HTML

<!-- "main" view --> 
<tabset> 
    <tab heading="Heading1"> 
     <form name="FORM1" class="form-horizontal" form-dirty> 
      <!-- FORM STUFF --> 
     </form> 
    </tab> 
    <tab heading="Heading2"> 
     <this-contains-form2 data="objOnScope"></this-contains-form2> 
    </tab> 
</tabset> 

<!-- "thisContainsForm2" template --> 
<form name="FORM2" class="form-horizontal" form-dirty> 
    <!-- FORM STUFF --> 
</form> 

RELEVANT JAVASCRIPT

// "form-dirty" directive 
angular.module('webapp.shared').directive('formDirty', ['$state', 'DlgPromptService', function($state, DlgPromptService) {  
    return { 
     scope: {theForm: '=name'}, 
     restrict: 'A', 
     link: function (scope, element, attrs) { 

      scope.$watch('theForm', function() { 

       // if there's a UI router change  
       scope.$on('$stateChangeStart', function (event, toState, toParams){ 

        // WHEN FORM1 DIRTY: PROMPT AND CONSOLE-LOG BOTH FORMS 
        // WHEN FORM2 DIRTY: PROMPT AND CONSOLE-LOG BOTH FORMS 

        console.log(scope.theForm); 

        // if form was not modified 
        if (!scope.theForm.$dirty) { 
         return; 
        } 
        else { 
         // if form was modified then intervene 

         // halt the route change 
         event.preventDefault(); 

         // prompt user 
         DlgPromptService.confirm('Unsaved Changes', 
          'This form has unsaved changes.<br/>' 
          +'Are you sure you want to leave?') 
         .then(function() { 
          // we will proceed with the route change 
          scope.theForm.$setPristine(); 
          $state.go(toState.name, toParams); 
         }) 
        } 
       }) 

       // if there's a window change (reload, etc) 
       window.onbeforeunload = function (event) { 

        // WHEN FORM1 DIRTY: NO PROMPT, NO CONSOLE LOG 
        // WHEN FORM2 DIRTY: PROMPT AND CONSOLE-LOG FORM2 

        console.log(scope.theForm); 

        // if form was not modified    
        if (!scope.theForm.$dirty) { 
         return; 
        } 
        else { 
         // prompt 
         return "prompt"; 
        } 
       } 

       scope.$on('$destroy', function() { 
        window.onbeforeunload = undefined; 
       }) 
      }) 
     } 
    } 
}]) 

// "thisContainsForm2" directive 
angular.module('webapp.shared').directive('thisContainsForm2', function() { 

    var controller = function($scope, $http, $state, DlgPromptService) { 
     // CONTROLLER STUFF 
    } 

    return { 
     scope : {data: '='}, 
     templateUrl : 'shared/thisContainsForm2.html', 
     controller : controller 
    } 
}) 

答えて

0

あなたはUIブートストラップ]タブの実装を使用する場合は、すべてのタブが常にレンダリングされていることを認識する必要があり、しかしすべて活性なものがに設定されている:第二のタブは、第一タブwindow.onbeforeunload機能をオーバーライドするように、両方のフォームダーティディレクティブは、問題であると同時に、で活性である。この場合の「表示なし」

そのような複数のリスナーを登録するか、独自のソリューションを登録できるようにするには、jQuerysイベントメカニズムを使用してください。

2つのフォームを同じページに置くだけで問題が発生する可能性があります。アンロードする前に正しく行ってください

+0

ありがとうThomas、それは私の疑惑でもありました。それは複数のイベントリスナーについての良い提案ですが、私はそれについて検討します。 – Kevin

関連する問題