AngularJS comprueba si el formulario es válido en el controlador

86

Necesito verificar si un formulario es válido en un controlador.

Ver:

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

En mi controlador:

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

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

        ...

Recibo este error:

TypeError: Cannot read property '$valid' of undefined
Rober
fuente
¿Lo envolvió en la función setBusinessInformation dentro del controlador?
matsko
3
código demasiado fragmentado para analizar qué podría estar mal ... cree una demostración simple en jsfiddle.net o plunker que replica el problema. ¿Está la forma dentro del alcance de BusinessCtrl? no puedo decir sin ver más
charlietfl
@matsko: No. Necesito ejecutar este código en la inicialización del controlador.
Rober
@charlietfl: No hay mucho más. Elimino algo de código para simplificar el ejemplo. Sí, el formulario debe estar en el alcance de BusinessCtrl (el controlador está configurado en rutas en app.js. Agrego mi solución en una respuesta a continuación. Pero, no sé por qué no funciona de esta manera.
Rober

Respuestas:

109

Prueba esto

en vista:

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

en controlador:

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

o

en vista:

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

en controlador:

$scope.submitForm = function(formValid){
  if(formValid) {
    // Code here if valid
  }
};
Damoriano
fuente
¿Qué sucede si quiero validar varios botones en un formulario?
Fahad Mullaji
esto funcionó para mí, pero ¿por qué $scope.formName.$validresulta indefinido?
ps0604
Si usa ng-if, $ scope.formName. $ Valid no funcionará y si usa ng-show, $ scope.formName. $ Valid funcionará.
Vaibhav Shaha
2
Esta debería ser la mejor respuesta, simple. ¿Pero podría manejar el formulario inválido? ¿Cómo podría mostrarle al usuario qué entradas no son válidas?
Nicolas Leucci
1
@ ps0604 formName.$validse puede acceder solo en la plantilla, si desea acceder en el controlador, debe crear un objeto para ese me gusta $scope.forms.formNamey en la plantilla: <form name="forms.formName"> verifique este comentario
Damsorian
29

He actualizado el controlador a:

.controller('BusinessCtrl',
    function ($scope, $http, $location, Business, BusinessService, UserService, Photo) {
        $scope.$watch('createBusinessForm.$valid', function(newVal) {
            //$scope.valid = newVal;
            $scope.informationStatus = true;
        });
        ...
Rober
fuente
También recuerde que: si el formulario es un modal, recuerde declarar el nombre del formulario como notación de puntos, por ejemplo: "data.theform" y acceda a él en su controlador como $ scope.data.theform
Jasper
2
Esto no funciona para mi. Muestre cómo obtiene 'createBusinessForm' en el $ scope del controlador.
cyrf
Las cosas de $ scope se han ido, ahora estamos usando un vmenfoque. ¿Puede crear un plunker para la misma respuesta utilizando el controlador como enfoque de sintaxis? No puedo hacerlo. También será útil para otros que estén buscando una respuesta con el contexto actual. Gracias
ankitd
14

Aquí hay otra solución

Establezca una variable de alcance oculta en su html y luego podrá usarla desde su controlador:

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

Aquí está el ejemplo de trabajo completo:

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
fuente
4

El BusinessCtrles inicializado antes de que los createBusinessForm's FormController. Incluso si tiene el ngControllerformulario en el formulario, no funcionará como deseaba. No puedes evitar esto (puedes crear el tuyo ngControllerDirectivee intentar engañar a la prioridad). Así es como funciona angularjs.

Vea este plnkr por ejemplo: http://plnkr.co/edit/WYyu3raWQHkJ7XQzpDtY?p=preview

Oliver
fuente