Объект формы 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,
})