web-dev-qa-db-ja.com

AngularJSモーダルダイアログフォームオブジェクトはコントローラーで未定義です

以下のようなフォームでモーダルダイアログを開くページがあります。しかし、フォームアクションを処理するコントローラーをヒットすると、フォームオブジェクトは未定義になり、Angular newbieが多すぎて...

これは、モーダルダイアログを開くための関数を保持する親ページコントローラーです。

_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;
          }
          }
        }
      );
    };
_

次のようなページで:

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

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

_    <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>
_

招待を処理するコントローラーはどこかにあります:

_  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...

    };
  }]);
_

それでは、コントローラにフォームスコープを取得する正しい方法は何でしょうか?

_$modal_をsendInvitationControllerに挿入し、sendInvitation関数を追加する必要があるかもしれません。しかし、私がそうするとき、アクションは決してコントローラーに入りません。または、コントローラーを参照する代わりに、送信アクションを処理する関数を_$modal.open({ ..._に追加する必要がありますか?ただし、sendInvitationControllerを独自のファイルとスコープに入れたいと思っています。

助けてくれてありがとう!

[〜#〜] edit [〜#〜]

回避策を構築するのに役立ち、誰かが質問に答えるのに役立つかもしれないいくつかのことを見つけました:

  1. _$scope.invitation_オブジェクトはsendInvitationControllerで未定義ではありませんが、正しいデータを保持しますが、_$scope.invitationForm_オブジェクトは未定義のままです。
  2. send-invitation.html内で_$scope.invitationForm.$invalid_にアクセスし、そこで検証を行うことができます:<button type="button" ng-click="sendInvitation()" ng-disabled="invitationForm.$invalid">Invite</button>

質問は次のとおりです:invitationFormオブジェクトの_$scope_へのバインドは、フォームモデルが正しくバインドされているのに、送信に失敗するのはなぜですか?

52
Pete

私は同じ問題を抱えていましたが、モーダルコントローラーのスコープでフォームオブジェクトを定義することで解決できました。コードを機能させるには、たとえば$scope.form = {};をコントローラーの先頭に追加し、フォームタグを<form name="form.invitation">。その後$scope.form.invitation.$invalidを入力する必要があります。

78
Robin

2014年11月更新:angle-ui-bootstrapから開始0.12.0トランスクルージョンスコープは、コントローラーのスコープとマージされます。何もする必要はありません。

.12.0より前

invitationFormを親コントローラースコープに直接配置するには、トランスクルードスコープを次のようにバイパスする必要があります。

<form name="$parent.invitationForm">

上記は、親コントローラーにフォームオブジェクトを自動的に作成します。初期化前のもの、長いオブジェクトパス、またはイベントによる受け渡しは必要ありません。モーダルが開いたら、$scope.invitationFormでアクセスするだけです。

39
gertas

「なぜ?」の質問に対する答え「スコープ」です。 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>

(これは非常に単純化されたバージョンであり、shouldはすべてのコアコンポーネントを保持します。)では、スコープの作成場所と挿入されるものを見てみましょう。それら。

<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>要素で作成された新しい子スコープがあり、thatinvitationFormオブジェクトが実際に追加されていることがわかります。そのため、sendInvitationControllerにオブジェクトは表示されませんが、ng-disabledのボタンには表示されます。 <modal-dialog>要素の外部(たとえば、sendInvitationController)でフォーム構造にアクセスできるようにしたい場合は、関数呼び出しでそれを渡す必要があります。

<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>

コントローラーが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のスコープをルートとするオブジェクトを作成し、Angularのスコープトラバーサルメカニズムに依存してフォームをそのオブジェクトに直接アタッチし、<modal-dialog>の外側のスコープでformオブジェクトを見つけて、それにオブジェクトを形成します。 sendInvitationController$scope.form = {}を指定しなかった場合、Angularは<modal-dialog>のスコープでformの新しいオブジェクトを作成し、それでもsendInvitationControllerでアクセスできなかったことに注意してください。 。

うまくいけば、これはあなたや他の人がAngularスコーピングについて学ぶのに役立つでしょう。

19
squid314

私はこのように働くようになりました:

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

フォーム名、$parentはありません。 AngularUI Bootstrapバージョン0.12.1を使用しています。

this により、この解決策が実現しました。

2
Jason Swett
$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,

            })
0
Jijo Paulose