Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Validate only visible controls in AngularJS

I'm new to AngularJS and perhaps I'm going about this the wrong way, but I'm having problems validating a form.

I have one form containing multiple DIVs. Each DIV represent a page in the form flow. I've got a single Next-button to take the user to the next page (DIV).

A page is shown based on a "currentpage" field in the $scope, e.g.

<form> 
    <div ng-show="currentpage == 1">
        <input type="text" required />
    </div>
    <div ng-show="currentpage == 2">
        <input type="text" required />
    </div>
    <button ng-disabled="??" ng-click="next()" />
</form>

I want a click on the Next-button to trigger form validation on the visible DIV controls only, and not the hidden ones. Disabling the Next button based on the visible controls' validation status is perfect. But how? I would very much like to avoid using JQuery in my controller.

Thanks!

like image 800
Jeppebm Avatar asked Jan 22 '13 16:01

Jeppebm


People also ask

What is $setValidity in AngularJS?

The $setValidity() function is a built-in AngularJS function that is used to assign a key/value combination that can be used to check the validity of a specific model value. The key in this case is “unique” and the value is either true or false.

What is $dirty in AngularJS?

$dirty means the user has changed the input value, $invalid means the address itself is invalid. Therefore the error is only shown if the user has actively changed the input value to either an empty or invalid value.


3 Answers

One could also set value of ng-required to a value that holds true for conditional submission/display. So validation passes when not visible.

Then on submission, the unwanted fields could be deleted from the $scope form object. To make it cleaner and easier to maintain, one could have the array holding the alternate set of required/non required attributes for a given condition.

This way one could do with exactly one form.

like image 189
skipy Avatar answered Oct 08 '22 04:10

skipy


 <!DOCTYPE html>
 <html ng-app="myapp">
 <body>
  <form name="myForm" data-ng-controller="formController" novalidate> 
    <div ng-show="currentpage==1">
       Page1<input type="text" ng-model="page1" ng-required="currentpage==1"/>
     </div>
    <div ng-show="currentpage=='2'">
        Page2<input type="text" ng-model="page2" ng-required="currentpage==2"/>
    </div>
  <input ng-disabled="myForm.$invalid" type="submit" value="NEXT" ng-click="next()"/>
</form>
</body>
</html>

Try this.

Pay attention to:

ng-required="currentpage==1" and ng-required="currentpage==2"

ng-required works same as ng-show. So when currentpage==1 is true, the field in the 1st div has ng-required="true", whereas the field in the second div has ng-required="false".

Similarly, on clicking next, when currentpage==2, the field in the second div becomes required, since ng-required="true", whereas for the field in the 1st div, ng-required="false".

like image 23
nekshan Avatar answered Oct 08 '22 03:10

nekshan


Seems to me that if you can have one of them null or empty upon submission, it's not really "required" is it?

You should probably have each of those in a separate form. Because it sounds like you've got some sort of conditional submit based off of what the current page is, which is going to get hairy to maintain.

Here is an example of form validation for each of your two forms. In this example, each form still submits to the same method if you really want it to go that way, but I'd recommend just having them submit to their own method, rather than have to shoehorn everything into a switch statement. In some cases I might even give each of the forms their own controller.

<form> 
    <div ng-show="currentpage == 1">
        <form name="page1Form" ng-submit="next(currentPage)">
           <input type="text" name="item1" ng-model="item1" required />
           <span ng-show="page1Form.item1.$dirty && page1Form.item1.$error.required">required</span>
           <button type="submit" ng-disabled="page1Form.$invalid">Submit</button>
        </form>
    </div>
    <div ng-show="currentpage == 2">
        <form name="page2Form" ng-submit="next(currentPage)">
           <input type="text" name="item2" ng-model="item2" required />
           <span ng-show="page2Form.item2.$dirty && page2Form.item2.$error.required">required</span>
           <button type="submit" ng-disabled="page2Form.$invalid">Submit</button>
        </form>
    </div>
</form>
like image 24
Ben Lesh Avatar answered Oct 08 '22 04:10

Ben Lesh