Angularjs prevent form submission when input validation fails

AngularjsValidation

Angularjs Problem Overview


I'm writing a simple login form using angularjs with some client side input validation to check that the user name and password is not empty and longer than three characters. See the below code:

<form name="loginform" novalidate ng-submit="login.submit()" class="css-form">
    <fieldset>
			
        <div class="control-group input-prepend">
            <span class="add-on"><i class="icon-user"></i></span>
            <input type="text" ng-model="login.username" name="username" required ng-minlength="3" placeholder="username" />
        </div>
				
        <div class="control-group input-prepend">
            <span class="add-on"><i class="icon-lock"></i></span>
            <input type="password" ng-model="login.password" name="password" required ng-minlength="3" placeholder="" />
        </div>
				
        <div class="control-group">
            <input class="btn" type="submit" value="Log in">
        </div>
				
    </fieldset>
</form>

And the controller:

var controller = function($scope) {
	
    $scope.login = {
        submit: function() {
				
            Console.info($scope.login.username + ' ' + $scope.login.password);
        }
    }

};

The problem is that the login.submit function will be called even if the input is not valid. Is it possible to prevent this behaviour?

As a side note I can mention that I use bootstrap and requirejs as well.

Angularjs Solutions


Solution 1 - Angularjs

You can do:

<form name="loginform" novalidate ng-submit="loginform.$valid && login.submit()">

No need for controller checks.

Solution 2 - Angularjs

Change the submit button to:

<button type="submit" ng-disabled="loginform.$invalid">Login</button>

Solution 3 - Angularjs

So the suggested answer from TheHippo did not work for me, instead I ended up sending the form as a parameter to the function like so:

<form name="loginform" novalidate ng-submit="login.submit(loginForm)" class="css-form">

This makes the form available in the controller method:

$scope.login = {
    submit : function(form) {
        if(form.$valid)....
    }

Solution 4 - Angularjs

HTML:

<div class="control-group">
    <input class="btn" type="submit" value="Log in" ng-click="login.onSubmit($event)">
</div>

In your controller:

$scope.login = {
    onSubmit: function(event) {
    	if (dataIsntValid) {
    		displayErrors();
    		event.preventDefault();
    	}
    	else {
    		submitData();
    	}
    }
}

Solution 5 - Angularjs

Your forms are automatically put into $scope as an object. It can be accessed via $scope[formName]

Below is an example that will work with your original setup and without having to pass the form itself as a parameter in ng-submit.

var controller = function($scope) {

    $scope.login = {
        submit: function() {
            if($scope.loginform.$invalid) return false;

        }
    }

};

Working example: http://plnkr.co/edit/BEWnrP?p=preview

Solution 6 - Angularjs

Although not a direct solution for the OPs question, if your form is within an ng-app context, but you want Angular to ignore it altogether, you can do this explicitly using the ngNonBindable directive:

<form ng-non-bindable>
  ...
</form>

Solution 7 - Angularjs

Just to add to the answers above,

I was having a 2 regular buttons as shown below. (No type="submit"anywhere)

<button ng-click="clearAll();" class="btn btn-default">Clear Form</button>
<button ng-disabled="form.$invalid" ng-click="submit();"class="btn btn-primary pull-right">Submit</button>

No matter how much i tried, pressing enter once the form was valid, the "Clear Form" button was called, clearing the entire form.

As a workaround,

I had to add a dummy submit button which was disabled and hidden. And This dummy button had to be on top of all the other buttons as shown below.

<button type="submit" ng-hide="true" ng-disabled="true">Dummy</button>

<button ng-click="clearAll();" class="btn btn-default">Clear Form</button>

<button ng-disabled="form.$invalid" ng-click="submit();"class="btn btn-primary pull-right">Submit</button>

Well, my intention was never to submit on Enter, so the above given hack just works fine.

Solution 8 - Angularjs

I know this is an old thread but I thought I'd also make a contribution. My solution being similar to the post already marked as an answer. Some inline JavaScript checks does the trick.

ng-click="form.$invalid ? alert('Please correct the form') : saveTask(task)"

Solution 9 - Angularjs

I know it's late and was answered, but I'd like to share the neat stuff I made. I created an ng-validate directive that hooks the onsubmit of the form, then it issues prevent-default if the $eval is false:

app.directive('ngValidate', function() {
  return function(scope, element, attrs) {
	if (!element.is('form'))
		throw new Error("ng-validate must be set on a form elment!");

    element.bind("submit", function(event) {
		if (!scope.$eval(attrs.ngValidate, {'$event': event}))
			event.preventDefault();
    	if (!scope.$$phase)
    		scope.$digest();            
    });
  };
});

In your html:

<form name="offering" method="post" action="offer" ng-validate="<boolean expression">

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRunar HalseView Question on Stackoverflow
Solution 1 - AngularjscyberwombatView Answer on Stackoverflow
Solution 2 - AngularjsBijanView Answer on Stackoverflow
Solution 3 - AngularjsRunar HalseView Answer on Stackoverflow
Solution 4 - AngularjsTheHippoView Answer on Stackoverflow
Solution 5 - AngularjsdavidmdemView Answer on Stackoverflow
Solution 6 - AngularjsIan ClarkView Answer on Stackoverflow
Solution 7 - AngularjsvighnuView Answer on Stackoverflow
Solution 8 - AngularjsDave RussellView Answer on Stackoverflow
Solution 9 - AngularjsRan CohenView Answer on Stackoverflow