AngularJS vérifie si le formulaire est valide dans le contrôleur

86

Je dois vérifier si un formulaire est valide dans un contrôleur.

Vue:

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

Dans mon contrôleur:

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

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

        ...

J'obtiens cette erreur:

TypeError: Cannot read property '$valid' of undefined
Rober
la source
L'avez-vous intégré à la fonction setBusinessInformation dans le contrôleur?
matsko
3
code trop fragmenté pour analyser ce qui pourrait être faux ... créer une simple démo dans jsfiddle.net ou plunker qui reproduit le problème. La forme est-elle dans le champ d'application BusinessCtrl? ne peut pas dire sans en voir plus
charlietfl
@matsko: Non. Je dois exécuter ce code lors de l'initialisation du contrôleur.
Rober
@charlietfl: Il n'y a pas grand-chose de plus. Je supprime du code afin de simplifier l'exemple. Oui, le formulaire doit être dans le cadre de BusinessCtrl (le contrôleur est défini sur les routes dans app.js. J'ajoute ma solution dans une réponse ci-dessous. Mais, je ne sais pas pourquoi ne fonctionne pas de cette façon.
Rober

Réponses:

109

Essaye ça

en vue:

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

dans le contrôleur:

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

ou

en vue:

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

dans le contrôleur:

$scope.submitForm = function(formValid){
  if(formValid) {
    // Code here if valid
  }
};
Damsorian
la source
Que faire si je souhaite valider plusieurs boutons dans un formulaire?
Fahad Mullaji
cela a fonctionné pour moi, mais pourquoi les $scope.formName.$validrésultats sont indéfinis?
ps0604
Si vous utilisez ng-if alors $ scope.formName. $ Valid ne fonctionnera pas et si vous utilisez ng-show alors $ scope.formName. $ Valid fonctionnera.
Vaibhav Shaha
2
Cela devrait être la meilleure réponse, simple. Mais pourriez-vous gérer le formulaire invalide? Comment pouvez-vous montrer à l'utilisateur quelles entrées sont invalides?
Nicolas Leucci
1
@ ps0604 le formName.$validne peut être consulté que dans le modèle, si vous voulez accéder au contrôleur, vous devez créer un objet pour cela comme $scope.forms.formNameet dans le modèle: <form name="forms.formName"> vérifiez ce commentaire
Damsorian
29

J'ai mis à jour le contrôleur pour:

.controller('BusinessCtrl',
    function ($scope, $http, $location, Business, BusinessService, UserService, Photo) {
        $scope.$watch('createBusinessForm.$valid', function(newVal) {
            //$scope.valid = newVal;
            $scope.informationStatus = true;
        });
        ...
Rober
la source
Rappelez-vous également que - Si le formulaire est un modal, n'oubliez pas de déclarer le nom du formulaire sous forme de notation par points, par exemple: "data.theform" et accédez-y dans votre contrôleur en tant que $ scope.data.theform
Jasper
2
Cela ne fonctionne pas pour moi. Veuillez montrer comment vous obtenez 'createBusinessForm' dans la portée $ du contrôleur.
cyrf
$ scope les choses ont disparu, maintenant nous utilisons l' vmapproche. pouvez-vous créer un plunker pour la même réponse en utilisant le contrôleur comme approche syntaxique. Je ne peux pas le faire. Cela sera également utile pour d'autres qui recherchent une réponse dans le contexte actuel. Merci
ankitd
14

Voici une autre solution

Définissez une variable de portée cachée dans votre html, puis vous pouvez l'utiliser à partir de votre contrôleur:

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

Voici l'exemple de travail complet:

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
la source
4

Le BusinessCtrlest initialisé avant le createBusinessForm's FormController. Même si vous avez le ngControllersur le formulaire ne fonctionnera pas comme vous le souhaitez. Vous ne pouvez pas vous en empêcher (vous pouvez créer votre ngControllerDirective, et essayer de tromper la priorité.) C'est ainsi que fonctionne angularjs.

Voir ce plnkr par exemple: http://plnkr.co/edit/WYyu3raWQHkJ7XQzpDtY?p=preview

Oliver
la source