2013-10-11 36 views
50

次のようなフォームでモーダルダイアログを開くページがあります。しかし、フォームアクションを処理するコントローラをヒットすると、フォームオブジェクトは定義されていません。理由はわかりません。AngularJSモーダルダイアログフォームオブジェクトがコントローラで定義されていません

これは親ページコントローラがモーダルダイアログ:このようなページの

app.controller('organisationStructureController', ['$scope', ..., '$modal', function ($scope, ..., $modal) { 

    $scope.openInvitationDialog = function (targetOrganisationId) { 
     $modal.open({ 
      templateUrl: 'send-invitation.html', 
      controller: 'sendInvitationController', 
      resolve: {$targetOrganisationId: function() { 
      return targetOrganisationId; 
      } 
      } 
     } 
    ); 
    }; 

<div class="modal-dialog"> 
     <div class="modal-content"> 
      <div class="modal-header"> 
       <!-- ... --> 
      </div> 
      <div class="modal-body"> 
       <form name="invitationForm"> 

        <div class="form-group"> 
         <label for="email" style="color:white;">Email</label> 
         <input type="email" class="form-control" autocomplete="off" placeholder="New member email" id="email" name="email" ng-model="invitation.email" required="true"/> 
         <span class="error animated fadeIn" ng-show="invitationForm.email.$dirty && invitationForm.email.$error.required">Please enter an email address!</span> 
         <span class="error animated fadeIn" ng-show="invitationForm.email.$error.email">Invalid email</span> 
        </div> 

        <!-- ... --> 

        <div class="modal-footer"> 
         <button type="button" class="btn btn-default" ng-click="cancel()">Cancel</button> 
         <button type="submit" class="btn btn-primary" ng-click="sendInvitation()">Invite</button> 
        </div> 
       </form> 
      </div> 
     </div> 
    </div> 

// inside a loop over organisations 
<a ng-click="openInvitationDialog({{organisation.id}})">Invite new member</a> 

招待ダイアログHTMLは次のようになります

招待を処理するコントローラはどこか別の場所である:

app.controller('sendInvitationController', ['$targetOrganisationId', '$scope', ..., 
    function ($targetOrganisationId, $scope, ...) { 

    $scope.invitation = { 
     // ... 
     targetOrganisation: { 
     id: $targetOrganisationId 
     } 
    }; 

    $scope.sendInvitation = function() { 

     // $scope.invitationForm is undefined 
     if ($scope.invitationForm.$invalid) { 
     return false; 
     } 

     // send the invitation... 

    }; 
    }]); 

だから、コントローラにフォームの範囲を取得するための正しい方法は何ですか?

多分sendInvitationController$modalを注入してsendInvitation機能を追加する必要がありますか?しかし、私がそうすると、アクションは決してコントローラに入りません。または、コントローラーを参照する代わりに、サブミットアクションを処理する関数を$modal.open({ ...に追加する必要がありますか?私はsendInvitationControllerを独自のファイルとスコープに入れたいと思っていますが、

ありがとうございました!

  1. $scope.invitationオブジェクトがsendInvitationControllerで未定義のではなく、正しいデータを保持している:私たちは、私たちは、回避策を構築し、誰かが質問自体に答えるかもしれない助けたいくつかのことが発見

    EDIT

    $scope.invitationFormは未定義のままです。我々は$scope.invitationForm.$invalidにアクセスし、すぐそこに検証を行うことができ、送信-invitation.html内部

  2. <button type="button" ng-click="sendInvitation()" ng-disabled="invitationForm.$invalid">Invite</button>

そこで質問です:なぜ$scopeから​​オブジェクトの結合は、フォームながら、提出に失敗しませんモデルは矛盾しません。

+1

私は同様の問題がありました。問題は、このようにモーダルを作成するときに$ modalが2つのスコープを作成することです.1つはモーダルウィンドウ用、もう1つはあなたのものです。あなたのng形式の式にドットを入れてみてください。$ scope.data = {}そしてng-form = "data.invitationForm" – 4vanger

+0

なぜ '$ dialog'を' backdropClick:false、 'と組み合わせて使用​​しないのですか? –

+0

あなたの答えをありがとう。 @ 4avanger:2つの異なるスコープがある場合、ドット表記を追加するとなぜ助けになるのですか?私はそれを試みたが、データがinvitationFormの代わりに未定義になった。 @マキシム:私たちは$モーダルを使用しています。 $ダイアログが何であるかわからない、多分同じですか?'backdropCLick:false'とは​​何ですか? – Pete

答えて

77

私は同じ問題を抱えていましたが、モーダルコントローラの範囲でフォームオブジェクトを定義することで解決できました。あなたのコードを動作させるには、コントローラの先頭に例えば$scope.form = {};を入れて、フォームタグを<form name="form.invitation">に変更してください。その後、$scope.form.invitation.$invalidを記入してください。

+3

! – Shawn

+0

これも私のために働いた。私はこれがモーダルでのスコープの問題であることを認識していますが、これをよりエレガントにする/角度のような方法がありますか? –

+2

@ErikOlson '$ parent'スコープはそれには理想的です。私の答えを確認してください – gertas

19

「なぜ?」という質問に対する答え。 「スコープ」です。 tl; drあなたはコントローラからスコープのフォームオブジェクトを隠したモーダルダイアログで新しいスコープを作成しました。

私たちはあなたのコードを簡素化した場合、我々はおおよそ以下のようになります。

<div ng-ctrl="organizeCtrl"> 
    <modal-dialog> 
    <form name="invitationForm"> 
     <input type="email" ng-model="invitation.email" placeholder="Enter email..." /> 
     <input type="submit" ng-click="sendInvitation()" text="Invite!" /> 
     <input type="button" ng-click="cancel()" text="Cancel :(" /> 
    </form> 
    </modal-dialog> 
</div> 

(これははまだコアコンポーネントのすべてを持っている必要があり非常に単純化したバージョンです。)ここで、スコープが作成される場所とそこに注入される内容を見てみましょう。ここで

<div ng-ctrl="sendInvitationController"> 
<!-- scope created above with "invitation" and "sendInvitation" from sendInvitationController --> 
    <modal-dialog> 
    <!-- scope created above for the modal dialog transclude --> 
    <form name="invitationForm"> 
    <!-- add "invitationForm" to the modal dialog's scope --> 
     <input type="email" ng-model="invitation.email" placeholder="Enter email..." /> 
     <input type="submit" ng-click="sendInvitation()" text="Invite!" /> 
     <input type="button" ng-click="cancel()" text="Cancel :(" /> 
    </form> 
    </modal-dialog> 
</div> 

、あなたは​​オブジェクトが実際に加算されるがある<modal-dialog>要素とで作成された新しい子余地があることがわかります。そのため、sendInvitationControllerのオブジェクトは表示されませんが、ng-disabledのボタンで確認できます。パラメータとして招待フォームを受け入れる

<div ng-ctrl="organizeCtrl"> 
    <modal-dialog> 
    <form name="invitationForm"> 
     <input type="email" ng-model="invitation.email" placeholder="Enter email..." /> 
     <input type="submit" ng-click="sendInvitation(invitationForm)" text="Invite!" /> 
     <input type="button" ng-click="cancel()" text="Cancel :(" /> 
    </form> 
    </modal-dialog> 
</div> 

コントローラ付:あなたがアクセスできるようにしたい場合は、フォームを使用すると、関数呼び出しでそれを渡す必要があります(sendInvitationController中など)<modal-dialog>要素の外を構築しますsendInvitation関数に:

app.controller('sendInvitationController', ['$targetOrganisationId', '$scope', ..., 
    function ($targetOrganisationId, $scope, ...) { 
    $scope.invitation = { 
    targetOrganisation: { 
     id: $targetOrganisationId 
    } 
    }; 
    $scope.sendInvitation = function (form) { 
    if (form.$invalid) { 
     return false; 
    } 
    // send the invitation... 
    }; 
}]); 

@Robinを見つけるために角度の範囲トラバーサル機構に依存する、具体的sendInvitationControllerの範囲に根ざしたオブジェクトを作成し、そのオブジェクトに直接フォームを添付し、他の解決策を同定しましたform<modal-dialog>以外のスコープでフォームオブジェクトを添付してください。 sendInvitationController$scope.form = {}を指定しなかった場合、Angularは<modal-dialog>のスコープに新しいオブジェクトformを作成しており、まだsendInvitationControllerにアクセスできなかったことに注意してください。

これは、あなたや他の人々が角の範囲を学ぶのに役立ちます。

+2

優れた説明!ありがとう! – HaukurHaf

+0

本当に素晴らしい説明!わかりやすい:) – somnathchakrabarti

+0

この説明は、送信ボタンのクリックに基づいて、親スコープ内でDOMを変更する必要がある場合に便利です。 – somnathchakrabarti

39

アップデート11月2014:angle-ui-bootstrapから開始0.12.0トランジションスコープがコントローラのスコープにマージされます。何もする必要はありません。

0.12.0前:

があなたの親コントローラの範囲内で直接​​を置くために、あなたは、このようトランスクルード範囲をバイパスする必要があります。

<form name="$parent.invitationForm"> 
以上がautomaticalyあなたの親コントローラにフォームオブジェクトを作成します

。事前初期化処理、長いオブジェクトパス、またはイベント渡しの必要はありません。モーダルを開くと$scope.invitationFormでアクセスしてください。

+2

この時点で唯一の解決策はあります(角度1.3)upvote! – Offirmo

+1

私はあなたにキスしてうれしいです!あなたはこの超簡単なソリューションで私の一日を作ったばかりです! – hewstone

+0

もう一度!本当にありがとう! – hewstone

2

私は私はこのように動作するようになった:

$modal.open({ 
    templateUrl: 'send-invitation.html', 
    controller: 'sendInvitationController', 
    scope: $scope // <-- I added this 
} 

no形式名、なし$parent。 AngularUI Bootstrapバージョン0.12.1を使用しています。

私はthisでこの解決策を説明しました。

0
$mdDialog.show({ 
       locals: {alert:"display meassage"}, 
       controller: DialogController, 
       templateUrl: 'views/dialog.html', 
       parent: angular.element(document.body), 
       clickOutsideToClose:true, 
       backdrop: true, 
       keyboard: true, 
       backdropClick: true, 

      }) 
関連する問題