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

¿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
  }
};

¿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;
        });
        ...

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>


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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.