88

I need to check if a form is valid in a controller.

View:

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

In my controller:

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

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

        ...

I'm getting this error:

TypeError: Cannot read property '$valid' of undefined
4
  • Did you wrap it around the setBusinessInformation function within the controller? Commented Nov 18, 2013 at 17:39
  • 3
    code too fragmented to analyze what could be wrong...create a simple demo in jsfiddle.net or plunker that replicates problem. Is form within scope of BusinessCtrl? can't tell without seeing more Commented Nov 18, 2013 at 17:45
  • @matsko: No. I need to execute this code on controller initialization. Commented Nov 18, 2013 at 18:53
  • @charlietfl: There is not much more. I remove some code in order to simplify the example. Yes, the form should be in the scope of BusinessCtrl (the controller is set on routes in app.js. I add my solution in an answer below. But, I don´t know why is not working this way. Commented Nov 18, 2013 at 18:55

5 Answers 5

111

Try this

in view:

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

in controller:

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

or

in view:

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

in controller:

$scope.submitForm = function(formValid){
  if(formValid) {
    // Code here if valid
  }
};
Sign up to request clarification or add additional context in comments.

8 Comments

What if I want to validate multiple buttons in a form?
this worked for me, but why $scope.formName.$valid results in undefined?
If you use ng-if then $scope.formName.$valid will not work and if you use ng-show then $scope.formName.$valid will work.
This should be the best answer, simple. But could you handle the form invalid ? How could you show to user what inputs are invalid ?
@ps0604 the formName.$valid can be accessed only in the template, if you want to access in the controller you need to create an object for that like $scope.forms.formName and in the template: <form name="forms.formName"> check this comment
|
29

I have updated the controller to:

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

3 Comments

Also remember that - If the form is a Modal then remember to declare form name as dot notation eg: "data.theform" and access it in your controller as $scope.data.theform
This does not work for me. Please show how you get 'createBusinessForm' into the controller's $scope.
$scope things has gone, now a days we are using vm approach. can you create a plunker for same answer by using controller as syntax approach. I am not able to do it. It will be helpful for other as well who are looking for answer with today's context. Thanks
14

Here is another solution

Set a hidden scope variable in your html then you can use it from your controller:

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

Here is the full working example:

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>

Comments

4

The BusinessCtrl is initialised before the createBusinessForm's FormController. Even if you have the ngController on the form won't work the way you wanted. You can't help this (you can create your ngControllerDirective, and try to trick the priority.) this is how angularjs works.

See this plnkr for example: http://plnkr.co/edit/WYyu3raWQHkJ7XQzpDtY?p=preview

Comments

0

I like to disable the save/submit button if the form is invalid:

<form name="ruleForm">
    <md-input-container>
        <label>Priority</span>
        <input name="description" ng-model="vm.record.description" required>
    </md-input-container>
    <md-button ng-click="vm.save()" ng-disabled="ruleForm.$invalid" class="md-primary md-raised">Save</md-button>
</form>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.