Как я могу установить форму, содержащуюся внутри ng-include, чтобы быть престижным?
У меня есть следующий код:
<div modal="modal.shouldBeOpen" close="close()" options="opts">
<div class="modal-body">
<form novalidate name="itemForm" style="margin-bottom: 0px;">
который содержится внутри включенного файла modal.html
<div data-ng-controller="AdminController">
<ng-include src="'/Content/app/admin/partials/grid-subject.html'"></ng-include >
<ng-include src="'/Content/app/admin/partials/modal.html'"></ng-include>
</div>
В моем контроллере AdminController я пытаюсь использовать следующий код для reset для формы:
$scope.itemForm.$setPristine();
Когда я это делаю, он говорит мне, что "itemForm" undefined.
Есть ли способ, которым я могу установить содержимое формы в нетронутую. Я предполагаю, что это проблема с областью, но я не уверен, как ее исправить. я
попробовал одно решение по удалению второго включить и вставить код непосредственно. Это решение работает.
Однако мы хотим иметь возможность повторно использовать код
поэтому я хотел бы иметь возможность сделать это с помощью include для modal.html
Обратите внимание, что причина, по которой мы хотели бы сделать это, состоит в том, что на нашем modal.html есть что-то вроде следующего:
<button
class="btn float-right"
data-ng-disabled="itemForm.$pristine"
data-ng-click="modalReset()"
data-ng-show="modal.resetButton">
Reset</button>
</form>
Итак, мы действительно находимся внутри элемента itemForm и хотим установить его в $netist от кнопки внутри.
Ответы
Ответ 1
Этот ответ нарушит все правила (т.е. обход DOM внутри контроллера), но здесь все равно...
.controller('AdminController', ['$scope','$element',
function($scope, $element) {
$scope.$on('$includeContentLoaded', function() {
var childFormController = $element.find('form').eq(0).controller('form');
console.log(childFormController);
childFormController.$setPristine();
});
}]);
Мы ожидаем загрузки содержимого, содержащего ng, а затем из $element
, где определен AdminController, мы ищем элементы form
, выбираем первый, а затем получаем его FormController.
Plunker
Если вы вызываете $setPristine()
только в результате взаимодействия с пользователем, вам не нужно искать событие $includedContentLoaded
– Я только должен был сделать это, потому что я не хотел создавать какой-либо компонент пользовательского интерфейса для запуска операции, и когда контроллер сначала запускается, форма еще не существует.
См. также AngularJS: Access formController формы, помещенной внутри transcluded директивы от родительского контроллера, которая касается аналогичной проблемы с попыткой доступа к дочернию из родителя.
Более чистое решение: определите директиву (используйте ее в элементе ng-include) и передайте ей функцию AdminController в качестве атрибута. В функции директивной ссылки вызовите этот метод и передайте FormController в качестве параметра. Тогда AdminController будет иметь ссылку на желаемый FormController. (Я не стал это кодировать, так как я не уверен, что вы хотите получить решение, в котором вы должны использовать директиву вместе с ng-include.)
Ответ 2
Ну, один из способов сделать это - трансляция события, например:
angular.module('myApp',[])
.controller('AdminCtrl',function($scope){
$scope.modalReset = function(){
$scope.$broadcast('modal-reset');
};
})
.controller('ModalCtrl', function($scope){
$scope.$on('modal-reset', function(){
$scope.itemForm.$setPristine();
});
});
Таким образом, вам не нужно проходить через dom.
Ответ 3
Не нарушайте правила:) Просто определите переменную (пустой объект) в контроллере и используйте ее при определении формы. Поскольку angular JS использует прототипы прототипов под капотом, когда форма попытается получить доступ к внутренней области (для начальной загрузки переменной), она сначала будет проходить через цепочку видимости и попытаться найти ту же переменную в родительской области.
<!—- The vars should live in the controller. I placed them here for the example. -—>
<div ng-controller="controllerName" ng-init="form={}; model={}" >
<div ng-include=" ‘path-to-the-template’ "></div>
</div>
<!—- Inside path-to-the-template -—>
<form name="form.createUser">
<input name="name" ng-model="model.name" />
<input name="email" ng-model="model.email" />
</form>
Ссылка для справки http://blog.152.org/2014/07/angular-form-element-not-attaching-to.html
Ответ 4
Если вы хотите достичь этого в результате некоторого взаимодействия с пользователем, на мой взгляд, гораздо более чистым и "angular" способом было бы использовать пользовательскую директиву, которая установит форму в нетронутую (т.е. когда пользователь хочет очистить форму, нажав esc или нажав кнопку или что-то еще).
app.directive("formCleaner",
function () {
return {
restrict: 'E',
require: '^form',
scope: {
callback: '&',
defaultText:'@'
},
template: '<button type="button" ng-click="setFormToPristine()" class="btn btn-warning" >{{defaultText}}</button>',
link: function (scope, element, attrs, formCtrl) {
scope.setFormToPristine = function () {
formCtrl.$setPristine();
scope.callback();
};
}
};
});
и просто подключите его к некоторой кнопке в вашей форме:
<form name="testForm">
<input type="text" ng-model="someModel" />
<hr/>
<input type="button" value="submit form" class="btn btn-primary" ng-disabled="testForm.$pristine"
ng-click=submitForm(testForm) />
<form-cleaner callback="resetFormCallback(testForm)" default-text="Clear Form"></form-cleaner>
</form>
И если вы хотите установить форму в исходное состояние непосредственно из контроллера (не в результате взаимодействия с пользователем), например, от ответа на запрос POST, тогда один из способов - назначить обратный вызов директиве который будет отвечать за очистку формы и последующий вызов этого обратного вызова от контроллера. На ваш взгляд:
<form-cleaner callback="resetFormCallback(testForm)" default-text="Clear Form"></form-cleaner>
и контроллер:
$scope.resetFormOnSubmitCallback=function(cb){
$log.warn("simulating $http POST call.....");
$timeout(function() {
cb();
$scope.someModel=null;
}, 3000)
}
и директива:
return {
restrict: 'E',
require: '^form',
scope: {
callback: '&',
defaultText:'@',
ngDisabled:'='
},
template: '<button type="button" ng-disabled="ngDisabled" ng-click="submitForm()" class="btn btn-primary" >{{defaultText}}</button>',
link: function (scope, element, attrs, formCtrl) {
var setFormToPristine=function(){
$log.log("setting form to prsitine....");
formCtrl.$setPristine();
};
scope.submitForm = function () {
scope.callback({
onFormSubmittedCallback:setFormToPristine
});
};
}
};
Смотрите plunk