Upon form submit the Tornado server does some checks and sends a response back to the client, which should appear in that current page as an alert.
Instead a blank html page is rendered with the Json response, but not as an alert on the current page where the form was submitted.
On submit the form is sent via post to /dh (DataHandler)
This is the Jquery:
$.post("/dh",function(data,status){
alert("Data: " + data + "\nStatus: " + status);
},"json");
The Tornado code:
class DataHandler(BaseHandler):
def post(self):
# Checks are done with form data received
dupInfo={
'tel' : duptel,
'name' : dupName
}
self.write(json.dumps(dupInfo, default=json_util.default))
self.finish()
So how can you return this json to the current page?
After the "alert" statement, add return false;. This disables the browser's default handling of the POST event. The browser's default behavior is to navigate to the new URL, and you want to prevent that.
Give your form an id and stop the default redirect after submission:
$("#yourForm").submit(function (event) {
event.preventDefault();
jQuery.ajax({
url: "/dh",
data: {
// whatever data you are passing to handler
},
dataType: "json",
type: "POST"
}).done(function (data, textStatus, jqXHR) {
// call was successful
// access response data
alert(data['tel'])
alert(data['name'])
}).fail(function (jqXHR, textStatus, errorThrown) {
// call error
// access response data
var data = jqXHR.responseJSON;
alert(data['tel'])
alert(data['name'])
});
});
Based on your handler, you should end up in the done callback rather than the fail one.
Related
I have this JavaScript that executes when the commit button for a form is clicked. It is supposed to submit the form body and a file:
$("#submitButton").off("click").on("click", function(evt) {
evt.preventDefault();
var url = "/portal/ProjectAuthority/Boq" + "?projectId=" + "0831260e-7018-dd49-9a84-daaf442bc1ec";
debugger;
var data = new FormData();
//Form data
var formData = $('#BoqReviewForm').serializeArray();
$.each(formData, function (key, input) {
data.append(input.name, input.value);
});
//File data
var fileData = $('input[name="boqFile"]')[0].files;
for (var i = 0; i < fileData.length; i++) {
data.append("boqFile", fileData[i]);
}
$("#boqDataWrapper").empty();
$.post({
url: url,
data: data,
processData: false,
contentType: false,
success: function (resp) {
setTimeout(function() {
getBoqReviewData(resp.importId);
},
100);
},
error: function(xmlHttpRequest, textStatus, errorThrown) {
alert(errorThrown);
}
});
return false;
});
The url is:
http://localhost/portal/ProjectAuthority/Boq?projectId=0831260e-7018-dd49-9a84-daaf442bc1ec
and the action method signature is:
public ActionResult Boq(Guid projectId, BoqUploadViewModel model, HttpPostedFileBase boqFile)
When I click the submit button, the jQuery Ajax error function is invoked before my breakpoint at the beginning of the action method, so the action method itself is not returning Bad Request, whatever tries to invoke the action method is.
Is there any obvious reason for the Bad Request error?
It turns out the viewmodel property for boqFile has a homemade data annotation attribute that is supposed to validate file extensions, e.g. to only xlsx, and that attribute was constantly failing, causing a bad request because the ajax call didn't return the model with errors.
I found this by skipping the ajax call and doing a straight postback, and then I got an error about the file extension, which was correct. I removed the faulty attribute, and the postback returned the valid json intended for the ajax call. Then I just went back to the ajax call and all is working.
I have a ajax section to submit data in laravel. I want if I submit success then don't reload the page and submit the error then reload the page. In the code below, when the error reloads the page correctly, I am having a problem in the success case, the page must not be reloaded, but the result is reloaded. I have added the line e.preventDefault () then true in the success case but wrong in the error case
$(document).ready(function() {
$('form').submit(function(e){
//e.preventDefault();
var form_data = $(this).serialize();
$.ajax({
url:'{{ route('contracts.store') }}',
method: "POST",
data: form_data,
dataType: "json",
success: function(data) {
$("#mgsContract").text("Add successfully");
$("#hideForm").css("visibility", "visible");
$("#hideForm").css("height", "auto");
$("#result-contract-id").val(data.contract_obj);
},
error: function(data) {
$("#mgsContract").text("Something wrong");
}
})
});
});
Add back that e.preventDefault() to prevent the form submission, and in the error case, call location.reload(). (Or if you want to submit the form conventionally in the error case, use e.target.submit(); instead. Since that's calling submit on the DOM element [not a jQuery wrapper], it won't call your submit handler again. [This is one of the differences between programmatically calling submit on a DOM element vs. calling it on a jQuery object.])
when you use ajax, laravel automatically responds in JSON for validation errors. therefore to access the validation errors you can use this.responseJSON.errors in error section of your ajax. there is no need to reload the page to access validation errors.
however in any case if you need to reload or go to specific location you can use window.location
window.location.href = "an address"; // going to specific location
window.location.reload(); //reloading the page
an ajax example is the following, in which a loop for showing all errors inside the form is specified.
$("#form_id").submit(function (e) {
e.preventDefault(); // avoid to execute the actual submit of the form.
var form = $(this);
var url = form.attr('action');
$.ajax({
method: "POST",
url: url,
data: form.serialize(), // serializes the form's elements.
success: function (data) {
// code in the case of success
},
error: function (err) {
if (err.status == 422) { // when status code is 422, it's a validation issue
// code in the case of error
console.log(err.responseJSON);
// you can loop through the errors object and show it to the user
console.warn(err.responseJSON.errors);
// display errors on each form field
$.each(err.responseJSON.errors, function (i, error) {
var el = $(document).find('[name="' + i + '"]');
el.removeClass('is-valid');
el.addClass('is-invalid');
var parent = el.parents('.form-group');
parent.append("<small class='error-message text-right text-danger d-block pr-5 ' role='alert'>" + error + "</small >");
});
}
},
});
});
I have a jquery ajax form to add/edit/delete username list in mysql db.
When I retrieve data with special chars from DB I'd like to populate the modal edit form with entity decoded chars...so for example ù wouldn't show as ù
Here you are the code I'm using:
$("body").on("click",".edit-user",function(){
var id = $(this).parent("td").prev("td").prev("td").prev("td").prev("td").text();
$('#form')[0].reset(); // reset form on modals
//Ajax Load data from ajax
$.ajax({
url : url + '/ajax_edit/' + id,
// type: "POST",
type: "GET",
dataType: "JSON",
success: function(data)
{
$('[name="username"]').val(data.username); // Populate edit modal form with retrieved username data
$('#con-close-modal').modal('show'); // show bootstrap modal when complete loaded
$('.modal-title').text('Edit Contributor'); // Set title to Bootstrap modal title
},
error: function (jqXHR, textStatus, errorThrown)
{
alert('Error get data from ajax');
}
});
});
Solved using echo html_entity_decode(json_encode($data)); in server side PHP script.
I am using Code Igniter and I have the following Javascript function in my View. I have tried to echo values such as "error" from my handler function in the controller, but the "success" code is always ran in this function below instead.
Do I use echo or return to respond to the AJAX post? What value do I return for success and failure?
<script>
function removeDatacenter(id)
{
var cfm = confirm("Do you wish to delete this datacenter?");
if (cfm==true)
{
$.ajax({
type: "POST",
url: "<?=base_url()?>datacenters/remove_handler.php",
data: { id: id },
success: function(result)
{
document.location.href = document.URL + "?result=success";
},
error: function(result)
{
document.location.href = document.URL + "?result=failed";
}}
);
}
};
</script>
The success-method runs if the ajax-request was successfully sent to your script. It does not say anything about what the request returned.
If you simply do echo "error"; in your PHP-script, you can check the value in the success-method like this:
success: function(response) {
if (response == "error") {
document.location.href = document.URL + "?result=failed";
}
else {
document.location.href = document.URL + "?result=success";
}
}
Edit: People tend to use json_encode in the PHP-code and decode the json-string to an object in the javascript-code. That way you can send more structured data from your script.
Any text you echo will be seen, by AJAX, as a success. Even if it's the word "error". In order for you to trigger the Javascript error handler, you need to trigger some sort of actual HTTP error. If you're just trying to trigger an error for testing purposes, you could throw an exception in your controller. Or point the AJAX request to a URL that doesn't exist on your server (then you'd get a 404 error).
By the way, the error callback you have in your Javascript is slightly off on the API. It might not matter depending on what you do in the error handler, but here's the full call:
error: function(xmlHttpRequest, textStatus, errorThrown) {
//handle error here
}
I am calling jQuery Ajax function, everything works fine.. except, it is not receving any response and appending it in.
When form is submitted.. beforeSend event is called and loading image successfully runs, and also there is an alert box with message 'Deleted', but the request and response from page is not appended.... in network tab of chrome, i can see message of selected post deleted... but its not appending in page.
$(document).ready(function() {
$("#post").submit(function() {
var post = $('#post').val();
var token = $('#token').val();
var str = 'token='+ token + '&post='+ post;
$.ajax({
type: "POST",
cache: false,
url: "http://localhost/delete.php",
data: str,
beforeSend: function(){
$("#post").html('<img src="http://localhost/loader.gif" align="absmiddle"> Deleting...');
},
success: function(msg) {
alert('Deleted');
$("#post").ajaxComplete(function(event, request, settings) {
$("#post").html(msg);
});
}
});
return false;
});
});
You're attaching a new event listener to #post after the AJAX query succeeds. Basically what you're saying is, "after this query succeeds, wait for another query to succeed and then change the HTML." Since the query has already succeeded, you need to remove ajaxComplete and simply use:
success: function() {
alert('Deleted');
$("#post").html(msg);
}