52

以下のようなフォームでモーダル ダイアログを開くページがあります。ただし、フォーム アクションを処理する必要があるコントローラーをヒットすると、フォーム オブジェクトが定義されておらず、Angular 初心者の私にはその理由がわかりません...

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

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を独自のファイルとスコープに入れたいと思っています。

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

編集

回避策を構築するのに役立ち、誰かが質問自体に答えるのに役立つ可能性があるいくつかのことを見つけました。

  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送信時に失敗するのはなぜですか?

4

5 に答える 5

39

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

0.12.0 より前:

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

<form name="$parent.invitationForm">

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

于 2014-05-29T21:24:41.483 に答える
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>ここでは、要素で作成された新しい子スコープあり、そこにinvitationFormオブジェクトが実際に追加されていることがわかります。そのため、 のオブジェクトは表示されませ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 のスコープ トラバーサル メカニズムを利用formして、スコープ外のオブジェクトを検索し<modal-dialog>、フォーム オブジェクトをそれ。$scope.form = {}で指定しなかった場合、Angular はのスコープで のsendInvitationController新しいオブジェクトを作成し、でそれにアクセスすることはできなかったことに注意してください。form<modal-dialog>sendInvitationController

願わくば、これがあなたや他の人々が Angular スコープについて学ぶのに役立つことを願っています。

于 2014-02-04T17:50:01.100 に答える
2

私はこのように動作するようになりました:

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

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

私はこれによってこの解決策にひっくり返されまし

于 2015-05-02T14:53:09.347 に答える
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,

            })
于 2016-01-08T11:08:12.287 に答える