Rowanto Luo


Just another blog. or log.


Why your cancel button submit the html form

One of the mistake which I see often during development on the frontend side is the cancel button, which actually submits the form when clicked. Saw it once, wait a while, saw it again, wait a while, saw it again, and the loop continues. Some people doesn't even realize.

So what's the problem? Let's take a look at a normal html form in AngularJS.
HTML Code

<div ng-app="MyApp">
    <div ng-controller="MyController">
    <form ng-submit="submitTheForm()">
        <div class="form-group">
            <label for="name">Name</label>
            <input type="text" class="form-control" ng-model="someone.name" id="name" placeholder="Enter name"></input>
        </div>
        <button class="btn btn-default" ng-click="cancel()">Cancel</button>
        <button type="submit" class="btn btn-default">Submit</button>
    </form>
    </div>
</div>

JavaScript Code

angular.module('MyApp', [])
.controller('MyController', function($scope) {
    $scope.submitTheForm = function () {
        var name = $scope.someone.name || 'No Name';
        alert("Submitted the form of " + name + "!");
    }
    $scope.cancel = function () {
        $scope.someone = {};
    }
});

So what's wrong with the form? It's this part here:

<button class="btn btn-default" ng-click="cancel()">Cancel</button>

If you actually copy pasted the file into a real AngularJS application, filled in the name field, then click the cancel button. You will notice that the cancel button function is being run. The name field will be reset to null. Everything is fine, except that you will also get the alert which says you've also submitted the form! If you're not surprised, then congratulations! If you are, don't worry, it's just small stuff.

The problem is, default type of button is actually "submit". So, if you don't specify the type of your buttons, then all your buttons will submit the form if you use the form tag!

So either of these three variations will fix the problem:

Specifying the button type:

<div ng-app="MyApp">
    <div ng-controller="MyController">
    <form ng-submit="submitTheForm()">
        <div class="form-group">
            <label for="name">Name</label>
            <input type="text" class="form-control" ng-model="someone.name" id="name" placeholder="Enter name"></input>
        </div>
        <button type="button" class="btn btn-default" ng-click="cancel()">Cancel</button>
        <button type="submit" class="btn btn-default">Submit</button>
    </form>
    </div>
</div>

Not using the form tag:

<div ng-app="MyApp">
    <div ng-controller="MyController">
    <div class="form-group">
        <label for="name">Name</label>
        <input type="text" class="form-control" ng-model="someone.name" id="name" placeholder="Enter name"></input>
    </div>
    <button class="btn btn-default" ng-click="cancel()">Cancel</button>
    <button class="btn btn-default" ng-click="submitTheForm()">Submit</button>
    </div>
</div>

Of course the preferred way should be to specify the button type to be a "button" explicitly to prevent your buttons sending the form. The second solution will also work, but in AngularJS context, your AngularJS form validations will not work anymore because it needs the form tag.

You can also change the cancel button to use an "a" tag instead of a "button" tag, but well, let's just do it the button-way. :)

I made a JSFiddle link if you want to play around and see it in action: http://jsfiddle.net/hu57nnbo/7

Sometimes I see that people actually don't realize this because their submit function does some check and prevents an invalid form submission from happening. But it's still not right. The best practice is to always put the button type when you're using forms!