I have a use case of sending form submission data to different server, before submitting the form to its action target.
So I need to delay form submission until I receive response given from AJAX request.
My limitation is that I can't use jQuery functions as I am developing my own library set for the product, which must be lite enough.
Now, I could have done something like unbind("submit") event on the form using jQuery, which could be called as callback in the AJAX function. But again, I've limited options.
My current form tracking code goes as:
form.onsubmit = function() {
event.preventDefault();
var url = "/lead/track/trackId/" + trackId;
var data = {};
for (var prop in fields) {
data[prop] = document.getElementsByName(prop)[0].value;
}
data['planId'] = planId;
data['visitorId'] = visitor_id;
var http_request = new XMLHttpRequest();
http_request.onreadystatechange = function(){
if (http_request.readyState == 4 )
{
setTimeout(function() {document.forms[0].submit();}, 0);
}
}
event.preventDefault() completely removes the submit action. If I remove this line, form goes to submission without waiting for AJAX response.
document.forms[0].submit() also doesn't helps. Its not receiving a form object, and displays "object is not a function". It could because this code is loaded asynchronously from a remote file.
Have already seen multiple jQuery alternatives. So, I need a specifically need a native Javascript based solution.
Thanks
Related
I am making a post request to google app script with the code below
var url ="MY WEBAPP EXEC"
function submitForm() {
var postRequest = {}
postRequest.name = $("#inputName").val();
postRequest.email = $("#inputEmail1").val();
postRequest.message = $("#inputMessage").val();
alert(JSON.stringify(postRequest)); // this alert
$.post(url, postRequest, function(data,status){
alert('success')
});
}
I am very confused why the post is working with the alert but doesn't work without it. Thank you.
===
OK I guess my question was not clear enough sorry.
I have a form accessing GAS remotely. I assumed the url implied that I was accessing GAS remotely. At the moment I am working on my localhost and on my JS above it works if the alert statement is present and does not do anything if alert is not there.
I was watching the execution list on GSuite Developer Hub to see if the request failed or completed. I observed if the alert statement is in the script the execution status is completed but if the alert statement is not there nothing happens. I assume that my post script is not working if alert is not there. Any idea why?
You haven't shown exactly how that function is called, but it's likely to be because, if this is truly a "form submit" action, the result of submitting a form is to "load a new page" (which can be the same page you're on, and is so by default with no action attribute in the form tag
Since you want to perform AJAX on form submit, you need to "prevent" the "default" form submit action - this can be achieved as shown in the second and third lines below
var url ="MY WEBAPP EXEC"
function submitForm(e) { // if this function is called using an event handler, it gets an event as the first and only argument
e.preventDefault(); // prevent the "default" form submit action
var postRequest = {}
postRequest.name = $("#inputName").val();
postRequest.email = $("#inputEmail1").val();
postRequest.message = $("#inputMessage").val();
alert(JSON.stringify(postRequest)); // this alert
$.post(url, postRequest, function(data,status){
alert('success')
});
}
How does one generally go about handling validation errors when using Ajax to process POST requests of Django forms?
I'm a server-side dev dabbling in a bit of pure JS to learn the ropes. I finished writing AJAX methods to handle the POST request of a Django form, but am now unsure regarding how to render validation errors.
For instance, here's a simple Django form:
class TextForm(forms.Form):
reply = forms.CharField(widget=forms.Textarea(attrs={'cols':30,'class': 'cxl','autocomplete': 'off','autofocus': 'autofocus'}))
def __init__(self,*args,**kwargs):
super(TextForm, self).__init__(*args,**kwargs)
self.fields['reply'].widget.attrs['id'] = 'text_field'
def clean(self):
data = self.cleaned_data
reply = data["reply"].strip()
if not reply:
raise forms.ValidationError('Write something')
elif len(reply) > 1500:
raise forms.ValidationError("Can't exceed 1500 chars")
return reply
And here's how the Ajax request works:
function overwrite_default_submit(e) {
// block the default behavior
e.preventDefault();
// create and populate the form with data
var form_data = new FormData();
form_data.append("reply", text_field.value);
// send the form via AJAX
var xhr = new XMLHttpRequest();
xhr.open('POST', e.target.action);
xhr.setRequestHeader("X-CSRFToken", get_cookie('csrftoken'));
xhr.send(form_data);
}
What's the best pattern to catch and display validation errors under such circumstances? Moreover, what if a file upload field was involved? Would love to see an illustrative example of how the experts do it.
Note: I prefer pure JS at this point since that's what I'm starting with. JQuery's on my radar, but I'll look at it in the future.
In the Django view, at the point where form.is_valid() fails, one can further place a check of the sort if request.is_ajax(). In this block, an HTTPResponse (or JSONResponse) of the following structure can be returned:
payload = {}
payload['success'] = False
payload['message'] = ERR_MSG['generic']
return HttpResponse(json.dumps(payload),content_type='application/json',)
This, in turn, can be caught in the AJAX side of things like so:
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200)
{
var resp = JSON.parse(this.responseText);
if (!resp.success) {
console.log(resp.message);
} else {
console.log("success at last");
}
}
};
Once the payload has reached the realm of JS, one can then proceed to render it accordingly.
I'll add more sophistication to this answer when/if I discover more (and when warranted). Over and out.
I need a script that will store html form data locally on the device until the user is online and then submit the form via the html action. Is this possible? I'm a javascript novice so I'd love any help available.
I think this is doable. Here's how I would do it, though it may not be ideal.
Set your form up so that the submit action is handled by javascript. It should attempt to submit the form with something like an XMLHttpRequest or jQuery's ajax() function.
Set up callbacks for the submission request. On success, indicate this to the user or navigate to some new page, however you want to show the request was successful. On failure (any failure or use the result's status code to confirm that the user is unable to connect) you have two options.
One option is to do a setTimeout of some reasonable length and attempt your submit action again. If the user closes the page or navigates away, though, this will never complete.
Another option is to put the form data into an array of some sort and put it into the localStorage object. Then if they reload the page, you can see if that data exists. If it does, it can repopulate the form and prompt the user to attempt a new submission. If the submission is successful, empty the local storage.
The way I'd do it would be a combination of both. Here's some psuedocode.
//run this once document is ready
//our submitForm action
var submitForm = function() {
var url = "my_form_action.php";
var params = "foo=bar"; //set params to your form values here
localStorage.myFormData = params;
http.open("POST", url, true);
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.setRequestHeader("Content-length", params.length);
http.setRequestHeader("Connection", "close");
//Call a function when the state changes.
http.onreadystatechange = function() {
if(http.readyState == 4) {
if(http.status == 200) {
//call was completed successfully
//clear out our local storage
localStorage.myFormData = null;
//do whatever here! (tell the user it was successful, change pages, whatever)
//doStuff();
} else {
//call was unsuccessful (user is offline)
//attempt again in 10 seconds
window.setTimeout(submitForm, 10000);
}
}
}
http.send(params)
}
//on document ready, check if we have pending form data to send
//if we do, fill in our form and attempt to submit it
if(localStorage.myFormData) {
//my data exists
//fill the form back out using stuff like
//document.getElementById('FirstName').value = localStorage.myFormData.match(/(.+?)=(.+?)(?:&|$)/g)[1][1];
//you'll need to figure out how best to repopulate your form when the page loads, but do it here
//once form is repopulated, either submit it using the form.submit function or call our submitForm() function directly
submitForm();
}
I hope this makes sense. There's a lot of work involved in getting the above setup working, but it should work!
I am using jQuery (latest) and have a entirely ajax through post login form. The form is monitored by this code:
$("form").live("submit", function(event) {
event.preventDefault();
var input = {};
input.url = $(this).attr('action');
input.data = $(this).serializeArray();
var output = Site.getResponse(input);
if(output.success) {
params = {};
params.title = 'Dashboard';
params.url = '/user/dashboard';
Page.instance().load(params);
}
});
So, essentially the browser should still recognize the post because it happens from the form's submit, I just use jQuery to stop that submit so I can process it. Is there a way to "trick" modern browsers into saving the password for my site without iframes, please.
IMHO the best way to handle login is to add this line to the end of the login script
header("Location: " . $_SERVER['HTTP_REFERER']);
or some constant url, depending on what you want. This way the page doesn't change and the form submits, therefore the browser remember's the password.
I have two forms on a page (one is being grabbed by AJAX). I need them both to be posted, so I serialize the second one and send it in a post using jQuery before submitting the first one. However, only the first form appears to be getting posted. The odd thing is though, if I put an alert after the serialized post it works as expected. What exactly is my problem here?
$("#submit").livequery('click', function() {
var form = $("#second_form");
var action = form.attr("action");
var serialized_form = form.serialize();
$.post(action, serialized_form);
//alert('test');
$("#first_form").submit();
return false;
});
Is there any better way to post two forms and then redirect to a new page on a button press? I tried posting both of them using the method above and then using window.location to change pages but I had a similar problem.
Much thanks!
You might try submitting "first_form" in a callback from the post of "second_form". I believe that the submit of "first_form" is unloading the page which causes the second post to be aborted. Doing the post of "first_form" in the callback from "second_form" will ensure that the initial post is complete before the second post begins.
$("#submit").livequery('click', function() {
var form = $("#second_form");
var action = form.attr("action");
var serialized_form = form.serialize();
$.post(action, serialized_form, submit_first);
});
function submit_first(val) {
$("#first_form").submit();
}