[javascript] Clicking a button within a form causes page refresh

I have a form in Angular that has two buttons tags in it. One button submits the form on ng-click. The other button is purely for navigation using ng-click. However, when this second button is clicked, AngularJS is causing a page refresh which triggers a 404. I’ve dropped a breakpoint in the function and it is triggering my function. If I do any of the following, it stops:

  1. If I remove the ng-click, the button doesn’t cause a page refresh.
  2. If I comment out the code in the function, it doesn’t cause a page refresh.
  3. If I change the button tag to an anchor tag (<a>) with href="", then it doesn’t cause a refresh.

The latter seems like the simplest workaround, but why is AngularJS even running any code after my function that causes the page to reload? Seems like a bug.

Here is the form:

<form class="form-horizontal" name="myProfile" ng-switch-when="profile">
  <fieldset>
    <div class="control-group">
      <label class="control-label" for="passwordButton">Password</label>
      <div class="controls">
        <button id="passwordButton" class="secondaryButton" ng-click="showChangePassword()">Change</button>
      </div>
    </div>

    <div class="buttonBar">
      <button id="saveProfileButton" class="primaryButton" ng-click="saveUser()">Save</button>
    </div>
  </fieldset>
</form>

Here is the controller method:

$scope.showChangePassword = function() {
  $scope.selectedLink = "changePassword";
};

This question is related to javascript angularjs

The answer is


You can keep <button type="submit">, but must remove the attribute action="" of <form>.


You can try to prevent default handler:

html:

<button ng-click="saveUser($event)">

js:

$scope.saveUser = function (event) {
  event.preventDefault();
  // your code
}

You should declare the attribute ng-submit={expression} in your <form> tag.

From the ngSubmit docs http://docs.angularjs.org/api/ng.directive:ngSubmit

Enables binding angular expressions to onsubmit events.

Additionally it prevents the default action (which for form means sending the request to the server and reloading the current page).


Add action to your form.

<form action="#">


Just add the FormsModule in the imports array of app.module.ts file, and add import { FormsModule } from '@angular/forms'; at the top of this file...this will work.


First Button submits the form and second does not

<body>
<form  ng-app="myApp" ng-controller="myCtrl" ng-submit="Sub()">
<div>
S:<input type="text" ng-model="v"><br>
<br>
<button>Submit</button>
//Dont Submit
<button type='button' ng-click="Dont()">Dont Submit</button>
</div>
</form>

<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.Sub=function()
{
alert('Inside Submit');
}

$scope.Dont=function()
{
$scope.v=0;
}
});
</script>

</body>

I also had the same problem, but gladelly I fixed this by changing the type like from type="submit" to type="button" and it worked.


This answer may not be directly related to the question. It's just for the case when you submit the form using scripts.

According to ng-submit code

_x000D_
_x000D_
 var handleFormSubmission = function(event) {_x000D_
  scope.$apply(function() {_x000D_
    controller.$commitViewValue();_x000D_
    controller.$setSubmitted();_x000D_
  });_x000D_
_x000D_
  event.preventDefault();_x000D_
};_x000D_
_x000D_
formElement[0].addEventListener('submit', handleFormSubmission);
_x000D_
_x000D_
_x000D_

It adds submit event listener on the form. But submit event handler wouldn't be called when submit is initiated by calling form.submit(). In this case, ng-submit will not prevent the default action, you have to call preventDefault yourself in ng-submit handler;

To provide a reasonably definitive answer, the HTML Form Submission Algorithm item 5 states that a form only dispatches a submit event if it was not submitted by calling the submit method (which means it only dispatches a submit event if submitted by a button or other implicit method, e.g. pressing enter while focus is on an input type text element).

See Form submitted using submit() from a link cannot be caught by onsubmit handler


I wonder why nobody proposed the possibly simplest solution:

don't use a <form>

A <whatever ng-form> does IMHO a better job and without an HTML form, there's nothing to be submitted by the browser itself. Which is exactly the right behavior when using angular.


I use directive to prevent default behaviour:

module.directive('preventDefault', function() {
    return function(scope, element, attrs) {
        angular.element(element).bind('click', function(event) {
            event.preventDefault();
            event.stopPropagation();
        });
    }
});

And then, in html:

<button class="secondaryButton" prevent-default>Secondary action</button>

This directive can also be used with <a> and all other tags