AngularJs не может получить доступ к объекту формы в контроллере ($ scope)
Я использую bootstrap-ui более конкретно модальные окна. И у меня есть форма в модальном режиме, я хочу создать экземпляр объекта проверки формы. Поэтому я в основном делаю это:
<form name="form">
<div class="form-group">
<label for="answer_rows">Answer rows:</label>
<textarea name="answer_rows" ng-model="question.answer_rows"></textarea>
</div>
</form>
<pre>
{{form | json}}
</pre
Я вижу объект формы в html файле без проблем, однако, если я хочу получить доступ к объекту проверки формы от контроллера. Он просто выводит мне пустой объект. Вот пример контроллера:
.controller('EditQuestionCtrl', function ($scope, $modalInstance) {
$scope.question = {};
$scope.form = {};
$scope.update = function () {
console.log($scope.form); //empty object
console.log($scope.question); // can see form input
};
});
Каковы могут быть причины, по которым я не могу получить доступ к $scope.form
от контроллера?
Ответы
Ответ 1
Только для тех, кто не использует $scope
, а скорее this
, в своем контроллере вам придется добавить псевдоним контроллера, предшествующий имени формы. Например:
<div ng-controller="ClientsController as clients">
<form name="clients.something">
</form>
</div>
а затем на контроллере:
app.controller('ClientsController', function() {
// setting $setPristine()
this.something.$setPristine();
};
Надеюсь, что это также будет способствовать общему набору ответов.
Ответ 2
Обычный способ, если ng-controller является родителем элемента формы:
удалите эту строку:
$scope.form = {};
Если angular устанавливает форму в ваши контроллеры $scope
, вы перезаписываете ее пустым объектом.
Как заявлял ОП, это не так. Он использует $modal.open
, поэтому контроллер не является родителем формы. Я не знаю хорошего решения. Но эту проблему можно взломать:
<form name="form" ng-init="setFormScope(this)">
...
и в вашем контроллере:
$scope.setFormScope= function(scope){
this.formScope = scope;
}
а затем в вашей функции обновления:
$scope.update = function () {
console.log(this.formScope.form);
};
Ответ 3
Посмотрите на исходный код "модального" angular ui bootstrap, вы увидите, что директива имеет
transclude: true
Это означает, что модальное окно создаст новую дочернюю область, родительский элемент которой является областью контроллера $, как дочерний элемент области действия. Тогда "форма" может быть доступна только вновь созданной дочерней областью.
Одним из решений является определение var в области контроллера, например
$scope.forms = {};
Затем для имени формы мы используем что-то вроде forms.formName1
. Таким образом, мы могли бы получить доступ к нему из нашего контроллера, просто позвонив $scope.forms.formName1
.
Это работает, потому что механизм наследования в JS является прототипной цепочкой. Когда дочерний объект пытается создать forms.formName1
, он сначала пытается найти объект forms в своей области, который определенно не имеет его, поскольку он создается "на лету". Затем он попытается найти его от родителя (вплоть до цепи прототипа), и здесь, поскольку мы определили его в области контроллера, он использует этот объект "forms
", который мы создали, для определения переменной formName1
. В результате мы все еще можем использовать его в нашем контроллере, чтобы делать такие вещи, как:
if($scope.forms.formName1.$valid){
//if form is valid
}
Подробнее о трансклюзии, посмотрите на видео ниже Misco с 45 минут. (это, вероятно, самое точное объяснение того, что такое трансключенные области, которые я когда-либо обнаружил!!!)
www.youtube.com/watch?v=WqmeI5fZcho
Ответ 4
Нет необходимости в обмане ng-init, поскольку проблема заключается в том, что $scope.form
не задается при запуске кода контроллера. Удалите инициализацию form = {}
и получите доступ к форме, используя часы:
$scope.$watch('form', function(form) {
...
});
Ответ 5
Я использую документированный подход.
https://docs.angularjs.org/guide/forms
поэтому, пользователь имя формы, на "сохранить" клик, например, просто передайте formName в качестве параметра и hey presto form, доступный в методе save (где formScopeObject поддерживается на основе спецификаций ng-моделей, которые вы задали в своей форме ИЛИ если вы редактируете это будет объект хранения редактируемого элемента, то есть учетной записи пользователя)
<form name="formExample" novalidate>
<!-- some form stuff here -->
Name
<input type="text" name="aField" ng-model="aField" required="" />
<br /><br />
<input type="button" ng-click="Save(formExample,formScopeObject)" />
</form>
Ответ 6
Чтобы расширить ответ от пользователя1338062: решение, которое я использовал несколько раз, чтобы инициализировать что-то в моем контроллере, но должен был ждать, пока он действительно будет доступен для использования:
var myVarWatch = $scope.$watch("myVar", function(){
if(myVar){
//do whatever init you need to
myVarWatch(); //make sure you call this to remove the watch
}
});
Ответ 7
Для тех, кто использует Angular 1.5, мое решение было $смотреть форму на стадии postlink:
$postLink() {
this.$scope.$watch(() => this.$scope.form.$valid, () => {
});
}