AngularJS sprawdza, czy formularz jest poprawny w kontrolerze

86

Muszę sprawdzić, czy formularz jest ważny w kontrolerze.

Widok:

<form novalidate=""
      name="createBusinessForm"
      ng-submit="setBusinessInformation()"
      class="css-form">
 <!-- fields -->
</form>

W moim kontrolerze:

.controller(
    'BusinessCtrl',
    function ($scope, $http, $location, Business, BusinessService, 
              UserService, Photo)
    {

        if ($scope.createBusinessForm.$valid) {
            $scope.informationStatus = true;
        }

        ...

Otrzymuję ten błąd:

TypeError: Cannot read property '$valid' of undefined
Rober
źródło
Czy owinąłeś to wokół funkcji setBusinessInformation w kontrolerze?
matsko
3
kod jest zbyt pofragmentowany, aby przeanalizować, co może być nie tak ... stwórz proste demo w jsfiddle.net lub plunker, który powiela problem. Czy formularz jest objęty zakresem BusinessCtrl? nie mogę powiedzieć, nie widząc więcej
charlietfl
@matsko: Nie. Muszę wykonać ten kod podczas inicjalizacji kontrolera.
Rober
@charlietfl: Niewiele więcej. Usuwam kod, aby uprościć przykład. Tak, formularz powinien mieścić się w zakresie BusinessCtrl (kontroler jest ustawiony na trasach w app.js. Dodaję swoje rozwiązanie w odpowiedzi poniżej. Ale nie wiem, dlaczego tak nie działa.
Rober

Odpowiedzi:

109

Spróbuj tego

z uwagi:

<form name="formName" ng-submit="submitForm(formName)">
 <!-- fields -->
</form>

w kontrolerze:

$scope.submitForm = function(form){
  if(form.$valid) {
   // Code here if valid
  }
};

lub

z uwagi:

<form name="formName" ng-submit="submitForm(formName.$valid)">
  <!-- fields -->
</form>

w kontrolerze:

$scope.submitForm = function(formValid){
  if(formValid) {
    // Code here if valid
  }
};
Damsoriański
źródło
A jeśli chcę sprawdzić poprawność wielu przycisków w formularzu?
Fahad Mullaji
to zadziałało dla mnie, ale dlaczego $scope.formName.$validskutkuje undefined?
ps0604
Jeśli użyjesz ng-if, to $ scope.formName. $ Valid nie zadziała, a jeśli użyjesz ng-show, to $ scope.formName. $ Valid będzie działać.
Vaibhav Shaha
2
To powinna być najlepsza odpowiedź, prosta. Ale czy mógłbyś obsłużyć nieprawidłowy formularz? Jak możesz pokazać użytkownikowi, które dane wejściowe są nieprawidłowe?
Nicolas Leucci
1
@ ps0604 formName.$validmożna uzyskać dostęp tylko w szablonie, jeśli chcesz uzyskać dostęp w kontrolerze, musisz utworzyć obiekt do tego podobnego $scope.forms.formNamei w szablonie: <form name="forms.formName"> sprawdź ten komentarz
Damsorian
29

Zaktualizowałem kontroler do:

.controller('BusinessCtrl',
    function ($scope, $http, $location, Business, BusinessService, UserService, Photo) {
        $scope.$watch('createBusinessForm.$valid', function(newVal) {
            //$scope.valid = newVal;
            $scope.informationStatus = true;
        });
        ...
Rober
źródło
Pamiętaj też, że - jeśli formularz jest modalny, pamiętaj, aby zadeklarować nazwę formularza w notacji kropkowej, np .: "data.theform" i uzyskać do niego dostęp w kontrolerze jako $ scope.data.theform
Jasper
2
To nie działa dla mnie. Pokaż, w jaki sposób dostałeś „createBusinessForm” do zakresu $ scope kontrolera.
cyrf
$ zakres sprawy minęły, teraz używamy vmpodejścia. czy możesz utworzyć plunker dla tej samej odpowiedzi, używając kontrolera jako podejścia składniowego. Nie jestem w stanie tego zrobić. Będzie pomocny także dla innych, którzy szukają odpowiedzi w dzisiejszym kontekście. Dzięki
ankitd
14

Oto inne rozwiązanie

Ustaw ukrytą zmienną zakresu w swoim html, a następnie możesz jej użyć ze swojego kontrolera:

<span style="display:none" >{{ formValid = myForm.$valid}}</span>

Oto pełny przykład działania:

angular.module('App', [])
.controller('myController', function($scope) {
  $scope.userType = 'guest';
  $scope.formValid = false;
  console.info('Ctrl init, no form.');
  
  $scope.$watch('myForm', function() {
    console.info('myForm watch');
    console.log($scope.formValid);
  });
  
  $scope.isFormValid = function() {
    //test the new scope variable
    console.log('form valid?: ', $scope.formValid);
  };
});
<!doctype html>
<html ng-app="App">
<head>
 <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular.min.js"></script>
</head>
<body>

<form name="myForm" ng-controller="myController">
  userType: <input name="input" ng-model="userType" required>
  <span class="error" ng-show="myForm.input.$error.required">Required!</span><br>
  <tt>userType = {{userType}}</tt><br>
  <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>
  <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>
  <tt>myForm.$valid = {{myForm.$valid}}</tt><br>
  <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>
  
  
  /*-- Hidden Variable formValid to use in your controller --*/
  <span style="display:none" >{{ formValid = myForm.$valid}}</span>
  
  
  <br/>
  <button ng-click="isFormValid()">Check Valid</button>
 </form>
</body>
</html>

Enkode
źródło
4

BusinessCtrlZostaje zainicjowany przed createBusinessForm„s FormController. Nawet jeśli masz ngControllerna formularzu, nie będzie działać tak, jak chciałeś. Nic na to nie ngControllerDirectiveporadzisz (możesz stworzyć swój i spróbować oszukać priorytet). Tak działa angularjs.

Zobacz na przykład ten plik plnkr: http://plnkr.co/edit/WYyu3raWQHkJ7XQzpDtY?p=preview

Oliver
źródło