JS removes form data before PHP can send email - javascript

Ran into a small oddity here.
When I submit a form, I have a JS click event listener on the submit button - this is to remove the HTML values and add a thank you message (pretty simple stuff).
Oddly, however, it seems that the JS is acting before the PHP because all emails have blank values until I remove the JS that removes the HTML values.
The code is:
pretty simple HTML form (this has been cut down to show what the problem might be)
HTML:
<form method="post" action="contactForm.php" id="contact-form" target="hiddenForm">
<textarea class="form-control input-outline reqItem" rows="6" cols="50" name="message" form="contact-form" placeholder="Message" required></textarea>
<button type="submit" class="btn btn-outline rounded-0 d-block d-md-inline-block submit-button">Submit</button>
</form>
JS (has an event listener on the submit button for click):
if(document.querySelector('.submit-button')){
document.getElementById('contact-form').addEventListener('submit', function(e){
// Check that form is valid
if(document.querySelector('form').checkValidity()){
document.querySelectorAll('.checkbox').forEach(e => {
if(e.classList.contains('checked')){
e.classList.remove('checked')
}
})
// Change messagae to thank you
e.target.classList.add('submit-hide')
document.querySelector('.submit-thankyou').classList.add('submit-show')
// remove all field values <<<<< issue seems to be being caused here
document.querySelectorAll('.form-control').forEach(e => {
// this causes the form to lose all data
e.disabled = true;
})
}
})
}
The e.disabled = true;
Is going over each form input and making it disabled, I have also used e.value = "".
Both of these stop PHP action in the form of setting variables as the values of the inputs.
So the question is,
am I doing something wrong (maybe right.....?)
is there a way to allow the PHP to act first getting the values before removing them with the JS?
Feel free to ask any questions here.
Any insights are welcome.

The submit event as part of the browser's form submission algorithm, before the browser even looks at the form's fields, so any changes you make as part of that event will be submitted to the server and you'll have access to them from PHP.
In order to change the form without affecting the submission, you'll have to do that at some point after the browser's form submission finishes, but before the page navigates to the form's action:
document.getElementById('contact-form').addEventListener('submit', function(){
setTimeout(function() {
// Modify the form here.
}, 0);
});
Remember that setTimeout(func, msecs) means "run func whenever you have the chance, but no earlier than msec milliseconds". While the browser is running the form submission algorithm, no Javascript code (other than that for the synchronous events submit and formdata) can run, so the earliest chance for func to run will be after the form is submitted.

Related

Multiple forms with one button for 2 different functions [duplicate]

I have HTML two forms, one that submits data upon entry to a database using PHP, the other directs the user to a paypal payment page, my problem is that the user would have to submit both forms which of course I do not want them to have to do. Is there anyway to use one submit button for two forms?
(Javascript is welcome)
You should be able to do this with JavaScript:
<input type="button" value="Click Me!" onclick="submitForms()" />
If your forms have IDs:
submitForms = function(){
document.getElementById("form1").submit();
document.getElementById("form2").submit();
}
If your forms don't have IDs but have names:
submitForms = function(){
document.forms["form1"].submit();
document.forms["form2"].submit();
}
A form submission causes the page to navigate away to the action of the form. So, you cannot submit both forms in the traditional way. If you try to do so with JavaScript by calling form.submit() on each form in succession, each request will be aborted except for the last submission. So, you need to submit the first form asynchronously via JavaScript:
var f = document.forms.updateDB;
var postData = [];
for (var i = 0; i < f.elements.length; i++) {
postData.push(f.elements[i].name + "=" + f.elements[i].value);
}
var xhr = new XMLHttpRequest();
xhr.open("POST", "mypage.php", true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send(postData.join("&"));
document.forms.payPal.submit();
You can submit the first form using AJAX, otherwise the submission of one will prevent the other from being submitted.
In Chrome and IE9 (and I'm guessing all other browsers too) only the latter will generate a socket connect, the first one will be discarded. (The browser detects this as both requests are sent within one JavaScript "timeslice" in your code above, and discards all but the last request.)
If you instead have some event callback do the second submission (but before the reply is received), the socket of the first request will be cancelled. This is definitely nothing to recommend as the server in that case may well have handled your first request, but you will never know for sure.
I recommend you use/generate a single request which you can transact server-side.
The currently chosen best answer is too fuzzy to be reliable.
This feels to me like a fairly safe way to do it:
(Javascript: using jQuery to write it simpler)
$('#form1').submit(doubleSubmit);
function doubleSubmit(e1) {
e1.preventDefault();
e1.stopPropagation();
var post_form1 = $.post($(this).action, $(this).serialize());
post_form1.done(function(result) {
// would be nice to show some feedback about the first result here
$('#form2').submit();
});
};
Post the first form without changing page, wait for the process to complete. Then post the second form.
The second post will change the page, but you might want to have some similar code also for the second form, getting a second deferred object (post_form2?).
I didn't test the code, though.
If you have a regular submit button, you could add an onclick event to it that does the follow:
document.getElementById('otherForm').submit();
if you want to submit two forms with one button you need to do this:
1- use setTimeout()
2- allow show pop up
<script>
function myFunction() {
setTimeout(function(){ document.getElementById("form1").submit();}, 3000);
setTimeout(function(){ document.getElementById("form2").submit();}, 6000);
}
</script>
<form target="_blank" id="form1">
<input type="text">
<input type="submit">
</form>
<form target="_blank" id="form2">
<input type="text">
<input type="submit">
</form>
javascript doesn't submit two forms at the same time. we submit two forms with one button not at the same time but after secounds.
edit: when we use this code, browser doesn't allow pop up.
if you use this code for your software like me just set browser for show pop up but if you use it in designing site, browser is a barrier and code doesn't run.

Invisible re-captcha fully from javascript without form submission

I am trying to use an invisible re-captcha v2 on a form that is submitted through JS. Every example I see online shows a regular plain HTML submitted form with a specified action and method, but I am using preventDefault() on my form to submit it with ajax. It seems like such a simple thing but I've been searching for hours and can't find a single person online who has ever done this.
HMTL:
<form id="form-login">
<!-- ...form fields... -->
<div
class="g-recaptcha"
data-sitekey="<site_key>"
data-size="invisible"
></div>
<button class="uk-button uk-button-primary" type="submit">Submit</button>
</form>
JS:
$('#form-login').submit(function(event) {
event.preventDefault();
console.log(grecaptcha.getResponse()); // <-- always comes back empty
});
I can see that the captcha is initializing because I can see the icon in the bottom right.
I've seen grecaptcha.execute() but it doesn't seem to do anything for me.
There are no errors in the console.
Recently I had a problem like you, making captcha invisible created a lot of issues for me e.g. https://github.com/google/recaptcha/issues/269 which is still an opened issue on GitHub.
I solved it with dynamically genarated captcha on each time form is submitted. Here is a bit of code I used. (commented code is a call to backend to verify response with Google API).
https://gist.github.com/ANTOSzbk/75ed7003e914162550f61399122a3bd4
Then you just use my function like this:
$('#form-login').submit(async function(event) {
event.preventDefault();
const response = await captchaVerification();
if (response) { } // proper submit code execution
else { } // on invalid captcha response
});

How to setup event tracking on Google Analytics on form submission?

Im trying to track when a user hits the submit button on a contact form.
The page's URL doesn't change, its static.
I can't track a differnt URL after submission, the only option would be to track when a user hits the submit button.
Do I need to edit my analytics account?
Where do I add the additional javascript?
UA is installed correctly (analytics.js)
I'm new to GA and javascript so please break it down for me.
Thanks
I can't track a differnt URL after submission, the only option would be to track when a user hits the submit button.
That is a bit of a non sequitur. Even when the Url does not change there is probably some stuff happening - before you send it there is probably some form validation, and there is some action behind the scene to send there form, like e.g an ajax call.
You could attach event tracking to a submit handler:
<form onSubmit="ga('send','event','category','action','label')">
<input type="text" id="text" name="text">
<input type="submit">
</form>
However this would just tell you that somebody hit the submit button, not if they filled in the form correctly or if the form actually has been sent.
Now I enter speculation land, because I do not know how your form actually works - maybe you can show us an url or give more information.
But maybe you have a validation function that is called on the submit action of the form to see if the form is filled in correctly. In that case it would be advisable to do the tracking in the validation function (horribly simplified example, not production code):
<form onSubmit="validate()"><input type="text" id="text" name="text"><input type="submit"></form>
<script>
function validate() {
var test = document.querySelector('#text').value
if(test = "") {
ga('send','event','Form','Submit','Submitted, but not filled in');
return false;
}
ga('send','event','Form','Submit','Submitted with correct values');
return true;
}
</script>
That's a tad better, at least it tracks the difference between correct submissions and invalid submissions.
Even more speculation: If your form is sent without page reloads it uses probably an ajax call, and there is a huge probability that is uses jQuery (I say that because a) it really is probable and b) it's easier to construct an example in jQuery. The same can be achivied with other libraries or in native JS, but the example will produce an error if you do not use jQuery).
jQuery has a thing called "global ajax handlers". "Global" means they are not callbacks for a specific action, they hook into jQuerys ajax "mechanism" whenever a call to an ajax function is made. The following might work if you have only one aja event per page (else you need logic to distinguish the different ajax event e.g, by checking the url they are being send to), and allows you to track if the ajax call has returned successfully, like when your form data has been send to the server and the request return a 2xx status code:
$(document).ajaxSuccess(function() {
ga('send','event','Form','Submit','Yeah, form data sent to the server');
});
However this does not tell you if the data has been processed correctly. For that you need to make the server emit a success message and check the response:
$( document ).ajaxSuccess(function( event, xhr, settings ) {
if ( settings.url == "formprocessor.php" ) {
if(xhr.responseText.indexOf("success") > -1) {
ga('send','event','Form','Response Received','Form data processed ');
} else {
ga('send','event','Form','Response Received','Form data NOT processed ');
}
}
});
The global ajax event handler is attached to the document - you can put that anywhere on your page, it will do nothing unless an ajax event was called.
Again, this is not production code. Do not try to copy and paste.
This was certainly a bit much if you are new to this, but it should at least help you to improve the question and to see what kind of things are possible. If you can share an Url to your form I can possibly improve the answer.

PureCSS stop page reload on form submit but retain form validation

I'm trying to use PureCSS forms in my web app and I can't figure out how to retain the nifty form validation while stopping the page reload.
I know I can stop the page reload using onsubmit="return false;"
Then I can use AJAX to post the form data using onClick="PostSettings();", where PostSettings() is my javascript function containing the AJAX request. I also have to include event.preventDefault(); at the top of that function to stop the reload.
Unfortunately these steps which stop the reload also stop the nice in-built PureCSS validation.
Is there a way to retain that without triggering the page reload or will I need to make my own validation in the javascript?
FYI, here's the html:
<button type="submit" class="pure-button pure-input-1-2 pure-button-primary"
id="save-simulation-button" onClick="PostSettings();"
onsubmit="return false;">
<i class="fa fa-save"></i> Submit Simulation Parameters
</button>
Use 'return false' instead of event.preventDefault() inside the 'PostSettings()' method.
Thanks for your replies Lucas and Vignesh -- they didn't quite solve the problem, but they got me thinking and I developed a solution:
In the html I had to add a return here: onClick="return PostSettings();"
Then in the javascript I return true or false depending on whether or not the form passes validation, which I have to check:
function PostSettings() {
//event.preventDefault(); <<- commented out per Vigneshs suggestion
var name = $("#simulation-name").val(); // jquery to get form values
var description = $("#description").val();
// Code to validate form: name and description cannot be blank
if (name === "" || description === "") {
console.log("name or description fields cannot be blank");
return true; // <<- returning true allows PureCSS validation to continue
}
// Code passed validation so post the data...
// POST code omitted for brevity
return false; // <<- returning false stops the page reload
}
So in summary, returning true allows the PureCSS form validation to take place as per normal (and there's no page reload because the form hasn't passed validation). And when the form passes validation I return false to stop the page reload -- this also stops any other default events of the PureCSS form, but that's okay because I manually checked if it validated in the javascript.
Hope this helps others who want to accomplish this in the future!
You only need a onsubmit="return MyValidFunction();" in the Form tag and nothing else in the "submit" button
When the form is not ok PureCSS make the validation with his message, When All is ok call your "MyValidFunction()" function
function MyFunction() {
/// your Ajax Code here
return false;
}
<form class="pure-form" onsubmit="return PostSettings();">
<input id="form_url" type="url" class="pure-input-1-3">
<button type="submit" class="pure-button pure-input-1-1">OK</button>
</form>
I had the same issue. Adding onsubmit="event.stopPropagation()" in the form tag prevents the refresh when the form is valid, and retains validation flags when it's invalid.

Reading form value fails - Javascript

I`m trying to read the value from an input and fill it in one empty div.However , the value is being read but when I click the button submit , the value appears for like 0.2 seconds on the empty div , and then , disappears ... any suggestions why?
HTML :
<div id="vuvedenaSuma">
</div>
<form action="">
<input type="text" id="suma" required="required" placeholder="Въведи сума" name="Suma" />
<button id="submit">Submit!</button>
</form>
Javascript:
function valueRead(){
var vuvedenaSuma = document.getElementById('suma').value;
document.getElementById('vuvedenaSuma').innerHTML = vuvedenaSuma;
}
document.getElementById('submit').addEventListener('click',valueRead);
I want to make it withe eventListener , not onclick attribute on the button.
Your form is being submitted right after the execution of the function.
You can prevent the default event(form submission) to be called with event.preventDefault() like this:
function valueRead(e){
var vuvedenaSuma = document.getElementById('suma').value;
document.getElementById('vuvedenaSuma').innerHTML = vuvedenaSuma;
e.preventDefault();
}
https://jsfiddle.net/ez0qchyq/
Your event is firing, then the page is likely reloading because of the form firing. Try using
event.preventDefault()
and it will prevent the form from submitting.
Edit: Also, the comment below me is absolutely correct. Remember to pass the event into the function.
The default way that a form "submits" is to send a new page request to the server, using the given inputs as parameters. From there, a serverside language like PHP might save them. Often, this would churn out an "Operation successful!" page or similar.
In your case, your form's action is blank, meaning it will "submit" to the page it's on. Since your page is pretty basic, it will reload without any of the sent information appearing in it.
As John Kossa suggested, you could intercept this by adding an argument, let's say, "evt", to the parentheses of the valueRead function, and then calling evt.preventDefault().
When you click the button then you send the form and the page is automatically refreshed. To prevent this behavior try this solution
function valueRead(e){
e.preventDefault();
var vuvedenaSuma = document.getElementById('suma').value;
document.getElementById('vuvedenaSuma').innerHTML = vuvedenaSuma;
}
Also, you might want to use the event listener on submit:
document.getElementById('formName').addEventListener('submit', valueRead);

Categories