Clicking a button within a form causes page refresh
Asked Answered
M

11

232

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";
};
Mclane answered 7/9, 2012 at 14:7 Comment(6)
See if this is your issue github.com/angular/angular.js/issues/1238 (Unfortunately, I don't know my way around github enough to be able to tell if this fix is in the 1.0.1 release or not).Mweru
I saw that one, but I'm not changing the location so I don't think it applies. Unless this other button is somehow causing it to submit, but it's not defined as a submit type, and when I take off the ng-click the button doesn't submit the form.Mclane
It would be great it you could provide a working demo of this problem. Perhaps starting with: Angular PlnkrIslamism
Dupe of #933153Aggy
Seem like duplicate. #16703715Basicity
More like the link you listed is the dup. Check the dates. This predates that link.Mclane
M
499

If you have a look at the W3C specification, it would seem like the obvious thing to try is to mark your button elements with type='button' when you don't want them to submit.

The thing to note in particular is where it says

A button element with no type attribute specified represents the same thing as a button element with its type attribute set to "submit"

Milwaukee answered 9/3, 2013 at 18:12 Comment(5)
I have the same problem as OP but my buttons have the type specified - and still click causes refresh. Any other places where I could look?Straitlaced
That suggests to me that your problem is in javascript. The problem my answer is addressing is more a matter between the dom and the browser. Some javascript handling your button click is likely causing the reload you see. Happy hunting ;)Milwaukee
This is exactly what I was looking for. It was very annoying on my page because it was supposed to only show the errors and not submit.Diversity
I have my buttons marked with type="button" and have the issue too. In my ng-click handler, I have $event.stopPropagation(). When I remove it, it doesnt reload. I need it though. Any ideas why it causes a page reload?!Putput
@freshfelicio: try to also add $event.preventDefault(), that helped in my case. But I have no explaination why :-\Lennielenno
K
75

You can try to prevent default handler:

html:

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

js:

$scope.saveUser = function (event) {
  event.preventDefault();
  // your code
}
Karankaras answered 10/9, 2012 at 16:2 Comment(2)
Nice! It really fetched to my scenario!Alasdair
This worked for we, when using AngularJS inside of a SharePoint form. I did have to add "event.stopPropagation();" as well though.Relly
C
19

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

Cothurnus answered 7/9, 2012 at 20:8 Comment(4)
Also, make sure you dont have 'action' property set on the form: form(action="/login", lng-submit="login()") Since this will make the page refresh even if you have ng-submit set.Annitaanniversary
Submitting a form and preventing default action Since the role of forms in client-side Angular applications is different than in classical roundtrip apps, it is desirable for the browser not to translate the form submission into a full page reload that sends the data to the server. Instead some javascript logic should be triggered to handle the form submission in application specific way. For this reason, Angular prevents the default action (form submission to the server) unless the <form> element has an action attribute specified. - docs.angularjs.org/api/ng.directive:formGingrich
I have a form with ng-submit={expression} and a button with type="submit". Works like just fine except on BB10. If I use BB10 keyboard's Submit then the page will refresh. If I use the button which I've declared in my form it work fine.Sokul
This isnt working for me. I followed the directions exactly. The page still posts backAlyosha
B
18

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

Broncobuster answered 5/2, 2014 at 12:50 Comment(3)
+1 Thanks! This is helpful when you don't have access to the <form> tag and hence cannot use the ng-submit directive.Jenifferjenilee
yow thanks for this one, but I need to also cancel ng-click in a directiveStearn
This also prevents the form from triggering the ng-submit callback, right?Pigment
I
5

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

Imputable answered 7/2, 2016 at 6:25 Comment(0)
S
3

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.

Sabbath answered 13/7, 2020 at 15:9 Comment(0)
E
1

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.

Executor answered 23/3, 2016 at 0:3 Comment(2)
how to enforce the formvalid on click then without form tag ?Premonition
@RizwanPatel I guess, I don't understand, but with ng-form=someForm, you get $scope.someForm and it has a $valid field. So I get all I need with <button ng-disabled="!someForm.$valid">.Executor
T
1

Add action to your form.

<form action="#">

Thaumaturge answered 24/5, 2017 at 19:15 Comment(0)
I
1

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

 var handleFormSubmission = function(event) {
  scope.$apply(function() {
    controller.$commitViewValue();
    controller.$setSubmitted();
  });

  event.preventDefault();
};

formElement[0].addEventListener('submit', handleFormSubmission);

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

Inly answered 9/12, 2017 at 12:4 Comment(0)
V
0

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>
Votaw answered 2/7, 2015 at 9:13 Comment(0)
O
0

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.

Ornas answered 12/4, 2020 at 8:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.