Могу ли я получить доступ к форме в контроллере?

152

В настоящее время я использую следующее.

$scope.$$childHead.customerForm[firstName], так что:

<form name="customerForm">
  <input type="text" name="firstName" 
         ng-model="data.customer.firstName" 
         tabindex="1"  
         ng-disabled="!data.editable" 
         validationcustomer />
</form>

Но это работает только в Chrome. Теперь я попробовал следующее:

$scope.editCustomerForm[firstName], так что:

<form name="customerForm" ng-model="editCustomerForm">
  <input type="text" name="firstName" 
         ng-model="data.customer.firstName" tabindex="1"  
         ng-disabled="!data.editable" 
         validationcustomer />
</form>

Который не работает. Обратите внимание, что моя форма находится на вкладке Foundation. Как я могу получить доступ firstName?

РЕДАКТИРОВАТЬ : Похоже, что formне добавляется к, scopeкогда он находится во вкладке Foundation.

У кого-нибудь есть решение для этого?

Винсент
источник

Ответы:

210

Хотя в других комментариях упоминалось, что я немного расшифровал это для тех, кто использует синтаксис «Контроллер как»:

<div ng-controller="MyController as ctrl">

<form name="ctrl.myForm">
    ...inputs
    Dirty? {{ctrl.myForm.$dirty}}

    <button ng-click="ctrl.saveChanges()">Save</button>
</form>

</div>

Затем вы можете получить доступ к FormController в вашем коде, например:

function MyController () {
    var vm = this;
    vm.saveChanges = saveChanges;

    function saveChanges() {

       if(vm.myForm.$valid) { 
            // Save to db or whatever.
            vm.myForm.$setPristine();
       }
}
slopapa
источник
Насколько я вижу, шаблон не может вызвать метод "saveChanges", так как он не доступен для шаблона
Spock
2
Метод «saveChanges» представлен в строке 3 javascript или я неправильно понял?
Слопапа
3
это хорошо, так как это означает, что вы можете избежать введения целой области $, что, на мой взгляд,
чище
2
Как вы тестируете это в жасмине? В моей спецификации vm.myForm не определена
bahrieinn
1
Это должно быть отмечено в официальных документах для 1.5.X, это способ сделать компоненты и es6. Спасибо, сэр
MatanCo
91

Вы можете прикрепить форму к некоторому объекту, который определен в родительском контроллере. Тогда вы сможете добраться до своей формы даже из дочерней области.

Родительский контроллер

$scope.forms = {};

Какой-то шаблон в дочерней области

<form name="forms.form1">
</form>

Проблема в том, что форму не нужно определять в тот момент, когда выполняется код в контроллере. Таким образом, вы должны сделать что-то вроде этого

$scope.$watch('forms.form1', function(form) {
  if(form) {
    // your code...
  }
});
ondrs
источник
10
Я бы предложил использовать var watcher = $scope.$watcherи внутри оператора if вы бы извините watcher (), чтобы открепить часы. Это делает его
однократным
91

Если вы хотите передать форму контроллеру для целей проверки, вы можете просто передать ее в качестве аргумента методу, обрабатывающему отправку. Используйте имя формы, поэтому для исходного вопроса это будет что-то вроде:

<button ng-click="submit(customerForm)">Save</button>
Энтони Шалл
источник
13
Для того, чтобы прояснить для читателей будущих, если сказать , ваша форма называется / определяется аналогично этому <form name="myform"></form>, или даже <div ng-form name="myform"></div>, то ваше событие щелчка будет выглядеть следующим образом : ng-click="submit(myform)". Затем вы можете получить доступ к объекту формы Angular в функции щелчка, например: $scope.submit = function (form) { if (form.$valid) {и т. Д.
Matty J
Я нахожу здесь проблему - скажем, есть выпадающий список в форме. Использование вышеуказанного метода дает мне только значение представления, а не точное значение, которое мне нужно. Или я что-то не так делаю, добавлю скрипку.
swateek
82

Немного опоздал на ответ, но пришел со следующим вариантом. Это работает для меня, но не уверен, что это правильный путь или нет.

На мой взгляд, я делаю это:

<form name="formName">
    <div ng-init="setForm(formName);"></div>
</form>

И в контроллере:

$scope.setForm = function (form) {
    $scope.myForm = form;
}

Теперь после этого я получил мою форму в моей переменной контроллера, которая $scope.myForm

Атул Чаудхари
источник
1
Единственное, что я хотел бы добавить к этому, это убедиться, что это в нижней части формы.
кому - л
Положение <div ng-init = "setForm (formName);"> </ div> не имеет значения. Просто будьте осторожны, что это в форме.
Вакас
1
хорошо, но я бы предпочел более простое решение: ng-init = "$ parent.myForm = formName" Без необходимости менять контроллер Примечание: он работает только с прямым контроллером, в отличие от решения выше
mastilver
Попробовав другие методы, я остановился на этом, потому что он позволяет nameатрибуту быть именно таким, каким я хочу его видеть. Проблема с другими решениями фиктивных объектов заключается в том, что если этот компонент используется в другом компоненте с ng-формой, то другая ng-форма использует это имя форм буквально. Так что у него будет поле со строковым литералом (НЕ вложенные свойства) с именем "dummy.myForm", я счел это недопустимым.
Василий
Я много раз пытался и не смог использовать синтаксис controllerAs (я работаю с $ mdDialog). В конце концов согласился на это, и он проделал большую работу. Заметьте только, что любые инициализации контроллера должны выполняться по тайм-ауту $, так как форма недоступна при первом
запуске
22

Чтобы иметь возможность доступа к форме в вашем контроллере, вы должны добавить ее в фиктивный объект области видимости.

Что-то вроде $scope.dummy = {}

Для вашей ситуации это будет означать что-то вроде:

<form name="dummy.customerForm">

В вашем контроллере вы сможете получить доступ к форме:

$scope.dummy.customerForm

и вы сможете делать такие вещи, как

$scope.dummy.customerForm.$setPristine()

WIKI LINK

Иметь '.' в ваших моделях будет обеспечено, что наследование прототипа находится в игре. Итак, используйте, <input type="text" ng-model="someObj.prop1">а не<input type="text" ng-model="prop1">

Если вы действительно хотите / должны использовать примитив, есть два обходных пути:

1. Используйте $ parent.parentScopeProperty в дочерней области. Это предотвратит создание дочерней областью своего собственного свойства. 2. Определите функцию в родительской области и вызовите ее из дочернего элемента, передав примитивное значение родительскому элементу (это не всегда возможно)

Карстен
источник
Где эффективная область для определения привязки формы?
Гас Кроуфорд
Стоит упомянуть, что dummy.customerFormон будет неопределенным до тех пор, пока не будут выполнены условия ng-if, если на элемент формы будет ng-if
наложено
22

Этот ответ немного запоздал, но я наткнулся на решение, которое делает все намного проще.

На самом деле вы можете назначить имя формы непосредственно вашему контроллеру, если вы используете синтаксис controllerAs, а затем ссылаться на него из вашей переменной «this». Вот как я это сделал в своем коде:

Я настроил контроллер через ui-router (но вы можете сделать это так, как хотите, даже в HTML-коде, например <div ng-controller="someController as myCtrl">). Вот как это может выглядеть в конфигурации ui-router:

views: {
            "": {
                templateUrl: "someTemplate.html",
                controller: "someController",
                controllerAs: "myCtrl"
            }
       }

а затем в HTML вы просто задаете имя формы как «controllerAs». «name», например:

<ng-form name="myCtrl.someForm">
    <!-- example form code here -->
    <input name="firstName" ng-model="myCtrl.user.firstName" required>
</ng-form>

теперь внутри вашего контроллера вы можете очень просто сделать это:

angular
.module("something")
.controller("someController",
    [
       "$scope",
        function ($scope) {
            var vm = this;
            if(vm.someForm.$valid){
              // do something
            }
    }]);
FrankieAvocado
источник
2
Хотя это в основном та же самая техника, что предлагают несколько других ответов, это лучший вариант и должен быть принятым ответом, тем более что все теперь используют контроллер как.
точка с запятой
6

Да, вы можете получить доступ к форме в контроллере (как указано в документации ).

За исключением случаев, когда ваша форма не определена в области контроллера и определена в дочерней области.

В основном, некоторые угловые директивы, такие как ng-if, ng-repeatили ng-include, создают изолированную дочернюю область. Как и любые пользовательские директивы с определенным scope: {}свойством. Возможно, ваши фундаментальные компоненты тоже на вашем пути.

У меня была такая же проблема при введении простой ng-ifвокруг <form>тега.

Смотрите их для получения дополнительной информации:

Примечание: предлагаю переписать свой вопрос. Ответ на ваш вопрос - да, но ваша проблема немного отличается:

Могу ли я получить доступ к форме в дочерней области с контроллера?

На что ответ будет просто: нет .

Андре Торгал
источник
... если вы не настроите свои формы и контроллер, как описано в ответе @ondrs (используя $scope.forms = {}and name="forms.form1")
marapet
Пожалуйста, смотрите ответ сразу над вашим KhalilRavanna. Вы можете получить доступ к форме из $ scope.formName. Он приводит рабочий пример
micahblu
3

добавить ng-model="$ctrl.formName"атрибут к вашей форме, а затем в контроллере вы можете получить доступ к форме как объект внутри вашего контроллера с помощьюthis.formName

Дурим Келменди
источник
0

Определенно вы не можете получить доступ к форме в области видимости. это не создано. DOM из HTML-шаблона загружается немного медленно, как конструктор контроллера. решение состоит в том, чтобы наблюдать, пока не загрузится DOM и не будет определена вся область действия!

в контроллере:

$timeout(function(){
    console.log('customerForm:', $scope.customerForm);
    // everything else what you need
});
Виктор Орлетчи
источник