[angularjs] Angularjs prevent form submission when input validation fails

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.

This question is related to angularjs validation

The answer is


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


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

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();
        }
    }
}

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">

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.


Change the submit button to:

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

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)"

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>