Clicking a button within a form causes page refresh - javascript

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:
If I remove the ng-click, the button doesn’t cause a page refresh.
If I comment out the code in the function, it doesn’t cause a page refresh.
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";
};

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"

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

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

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

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.

Add action to your form.
<form action="#">

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

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.

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>

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.

Related

Why is my button function not being called? [duplicate]

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:
If I remove the ng-click, the button doesn’t cause a page refresh.
If I comment out the code in the function, it doesn’t cause a page refresh.
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";
};
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"
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).
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
You can keep <button type="submit">, but must remove the attribute action="" of <form>.
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.
Add action to your form.
<form action="#">
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
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.
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>
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.

I cant get my JSON from api with fetch in html [duplicate]

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:
If I remove the ng-click, the button doesn’t cause a page refresh.
If I comment out the code in the function, it doesn’t cause a page refresh.
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";
};
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"
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).
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
You can keep <button type="submit">, but must remove the attribute action="" of <form>.
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.
Add action to your form.
<form action="#">
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
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.
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>
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.

Contact form with AJAX call still redirecting after submit [duplicate]

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:
If I remove the ng-click, the button doesn’t cause a page refresh.
If I comment out the code in the function, it doesn’t cause a page refresh.
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";
};
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"
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).
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
You can keep <button type="submit">, but must remove the attribute action="" of <form>.
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.
Add action to your form.
<form action="#">
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
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.
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>
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.

Delay form submit (AngularJS)

How can I prevent submitting a form in Angular until I receive a callback?
I have something along these lines:
<form method="post" action="http://example.com/external" ng-submit="submit()">
<input type="hidden" name="foo" value="{{bar}}" />
<input type="submit" />
</form>
Before submitting the form, I need to get the {{bar}} value from a local API call (using $http), and place it in the scope before allowing the actual form to submit (not POSTed using $http). How can this be done?
The form directive in Angular will wrap it in a formController and intercept it. You can still run your asynchronous code but you will need to reference the DOM form to submit it. I have an example fiddle with the solution - basically it sets up a button to submit the form, asynchronously sets the hidden field, then posts it.
Here is the relevant code:
MyController = function ($scope, MyService) {
$scope.boo = "";
$scope.submit = function () {
MyService.getAsync().then(function(result) {
$scope.boo = result;
document.myForm.action = "http://example.com/";
document.myForm.submit();
});
};
};
If you run a fiddle you will see the hidden field is populated:
http://jsfiddle.net/jeremylikness/T6B2X/
The "ugly" part of the code is the direct reference to:
document.myForm
If you wanted to clean this up, you could write your own directive that allows you to place an attribute on the form and interacts with a service to manipulate it. I.e. MyFormService and then I could do MyFormService.setAction(url) and MyFormService.submit() - that would be more cleaner and reusable but time wouldn't permit me to set that up for you.
As docs for ng-submit state:
Additionally it prevents the default action (which for form means
sending the request to the server and reloading the current page) but
only if the form does not contain an action attribute.
So remove that action attribute and handle it directly yourself in the submit() handler on the scope.
Make yours http call and in then success handler submit the form manually.
Can you not just use the submit button's onClick event to call a function that returns false if the submit is not allowed?
i.e. onClick='return CheckIfFooPopulated();'
Then in that function return false is foo as not yet been set or true if it OK to submit.
The problem is that ng-submit doesn't work with an action attribute, as stated in the docs.
Then, you can do whatever you want inside of submit() in your controller. However, I would use ng-model for the form input fields because it gives you better control over the model.
You would use this $scope.formModel to bind the input fields to the scope.
You could implement submit like that:
$scope.submit = function() {
$http.get("URL").success(function(data) {
$http.post("URL2", { model: $scope.formModel, bar: data.bar }).success(function() {
$location.path("/new-route");
});
});
}
There many possibilityes, but a less risky is to use ng-switch.
ng-switch do not load DOM if not needed.
<span ng-switch on="barNotEmpty">
<span ng-switch-when="true">
<form method="post" action="http://example.com/external" ng-submit="submit()">
<input type="hidden" name="foo" value="{{bar}}" />
</form>
</span>
<span ng-switch-default>
<form>
<input type="hidden" name="foo" value="{{bar}}" />
</form>
</span>

Form Not Validating when Using Anchor to Submit

I'm trying to submit a form using an anchor tag. However, the validation function doesn't seem to get triggered. I've since replaced the anchor with a submit button and it now works. Still, I'm curious why the previous anchor link didn't work.
The code is
function validate() {
/* validation code here */
return status;
}
<form id="myForm" action="/response_page.php" onsubmit="return validate();" method="POST">
<!-- form elements here -->
Submit
</form>
With this code, clicking the link goes straight to *response_page.php*. But when replaced with a submit button
<input type="submit" value="submit" />
WITHOUT changing the validate function and form tag, the validate function is called correctly. What's wrong with the anchor?
Thanks
This is expected behavior.
From the MDN on the submit function :
The form's onsubmit event handler (for example, onsubmit="return
false;") will not be triggered when invoking this method from
Gecko-based applications. In general, it is not guaranteed to be
invoked by HTML user agents.
If you want to validate your code in your link, just call the validate function explicitely :
<a id=subbut href="#" class="submit_button">Submit</a>
...
document.getElementById('subbut').addEventListener('click', function(){
if (validate()) document.getElementById('myForm').submit();
});

Categories