Объект формы AngularJS модального диалога undefined в контроллере

У нас есть страница, которая открывает модальный диалог с формой, как показано ниже. Однако, когда мы нажимаем на контроллер, который должен обрабатывать действие формы, объект формы undefined, и я слишком много новичок 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 в своем собственном файле и области.

Спасибо за любую помощь!

ИЗМЕНИТЬ

Мы обнаружили несколько вещей, которые помогли нам создать обходной путь и могли бы помочь кому-то ответить на сам вопрос:

  • Объект $scope.invitation не undefined в sendInvitationController, но содержит правильные данные, а $scope.invitationForm остается undefined.
  • внутри send-invite.html мы можем получить доступ к $scope.invitationForm.$invalid и выполнить проверку: <button type="button" ng-click="sendInvitation()" ng-disabled="invitationForm.$invalid">Invite</button>

Итак, возникает вопрос: почему привязка объекта invitationForm к $scope не выполняется при отправке, когда модель формы привязывается к исходному?

Ответ 1

У меня была такая же проблема, и я смог ее решить, определив объект формы в области контроллера модалов. Чтобы заставить работать ваш код, например, $scope.form = {}; в начале вашего контроллера и измените свой тег формы на <form name="form.invitation">. Затем $scope.form.invitation.$invalid должен быть заполнен.

Ответ 2

Обновление Nov 2014: начиная с angular -ui-bootstrap 0.12.0 область перехвата объединяется с областью контроллера. Нет необходимости ничего делать.

До 0.12.0:

Чтобы разместить invitationForm непосредственно в области вашего родительского контроллера, вам необходимо обойти запретную область действия следующим образом:

<form name="$parent.invitationForm">

Выше автоматическое создание объекта формы в вашем родительском контроллере. Нет необходимости в материалах предварительной инициализации, длинных объектных дорогах или передаче события. Просто войдите в него с помощью $scope.invitationForm после открытия модального мода.

Ответ 3

Ответ на вопрос "Почему?" является "областью определения". 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 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 = {} в sendInvitationController, Angular создал бы новый объект для form в области для <modal-dialog>, и вы все равно не смогли бы получить к нему доступ в sendInvitationController.

Надеюсь, это поможет вам или другим людям узнать о области Angular.

Ответ 4

Я получил свою работу следующим образом:

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

Нет имени формы, нет $parent. Я использую версию AnglerUI Bootstrap версии 0.12.1.

Я был перенаправлен на это решение this.

Ответ 5

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

            })