AngularJS verifica se o formulário é válido no controlador


86

Preciso verificar se um formulário é válido em um controlador.

Visão:

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

No meu controlador:

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

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

        ...

Estou recebendo este erro:

TypeError: Cannot read property '$valid' of undefined

Você envolveu a função setBusinessInformation no controlador?
— matsko de

3
código muito fragmentado para analisar o que pode estar errado ... crie uma demonstração simples no jsfiddle.net ou plunker que replica o problema. O formulário está dentro do escopo de BusinessCtrl? não posso dizer sem ver mais
— charlietfl

@matsko: Não. Eu preciso executar este código na inicialização do controlador.
— Rober de

@charlietfl: Não há muito mais. Eu removo algum código para simplificar o exemplo. Sim, o formulário deve estar no escopo do BusinessCtrl (o controlador é definido em rotas no app.js. Eu adiciono minha solução na resposta abaixo. Mas, não sei por que não está funcionando dessa forma.
— Rober

Respostas:


109

Tente isto

em vista:

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

no controlador:

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

ou

em vista:

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

no controlador:

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

E se eu quiser validar vários botões em um formulário?
— Fahad Mullaji

isso funcionou para mim, mas por que $scope.formName.$validresulta em indefinido?
— ps0604

Se você usar ng-if então $ scope.formName. $ Valid não funcionará e se você usar ng-show então $ scope.formName. $ Valid funcionará.
— Vaibhav Shaha

2
Esta deve ser a melhor resposta, simples. Mas você poderia lidar com o formulário inválido? Como você poderia mostrar ao usuário quais entradas são inválidas?
— Nicolas Leucci

1
@ ps0604 o formName.$validpode ser acessado apenas no template, se você deseja acessar no controlador você precisa criar um objeto para esse gosto $scope.forms.formNamee no template: <form name="forms.formName"> verifique este comentário
— Damsorian 23/09/16

29

Eu atualizei o controlador para:

.controller('BusinessCtrl',
    function ($scope, $http, $location, Business, BusinessService, UserService, Photo) {
        $scope.$watch('createBusinessForm.$valid', function(newVal) {
            //$scope.valid = newVal;
            $scope.informationStatus = true;
        });
        ...

Lembre-se também disso - Se o formulário for Modal, lembre-se de declarar o nome do formulário como notação de ponto, por exemplo: "data.theform" e acesse-o em seu controlador como $ scope.data.theform
— Jasper

2
Isso não funciona para mim. Por favor, mostre como você coloca 'createBusinessForm' no escopo $ do controlador.
— cyrf

As coisas de $ scope se foram, agora que estamos usando a vmabordagem. você pode criar um plunker para a mesma resposta usando o controlador como abordagem de sintaxe. Eu não sou capaz de fazer isso. Será útil também para outros que estão procurando uma resposta no contexto de hoje. Obrigado
— ankitd de

14

Aqui está outra solução

Defina uma variável de escopo oculta em seu html, então você pode usá-la em seu controlador:

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

Aqui está o exemplo de trabalho 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

O BusinessCtrlé inicializado antes do createBusinessForm's FormController. Mesmo se você tiver o ngControllerno formulário, não funcionará da maneira que você queria. Você não pode evitar isso (você pode criar o seu ngControllerDirectivee tentar enganar a prioridade). É assim que o angularjs funciona.

Consulte este plnkr por exemplo: http://plnkr.co/edit/WYyu3raWQHkJ7XQzpDtY?p=preview

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.