I have a script with two methods one that's submits a form with Ajax
function saveCustomer(){
$('#createCustomer').submit(function(ev) {
ev.preventDefault();
$('#submit').attr('disabled',true);
var $inputs = $('#createCustomer :input');
var values = {};
$inputs.each(function() {
values[this.name] = $(this).val();
});
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
})
$.ajax({
url: '/customer',
type : 'POST',
data : values,
success : function(data){
//check if controller validation send customer exist
if(data.confirmation){
$("#confirmation").show();
}
else{
$('#createCustomer :input').val('');
$("#customer").hide();
//assign values to success modal
$('#firstName').val(data.customer.firstName);
$('#lastName').val(data.customer.lastName);
$('#street').val(data.address.street);
$('#businessName').val(data.customer.businessName);
$('#submit').attr('disabled',false);
}
},
error : function(error){
$('#submit').attr('disabled',false);
}
});
});
}
And a function that adds another input to the form and calls the first function
$('#proceedWithSave').on('click', function(){
var input = $("<input>")
.attr("type", "hidden")
.attr("name", "proceed");
$('#createCustomer').append($(input));
saveCustomer();
});
Now the second function is called successfully because it adds the new input but the first function is not called because no ajax call is made.
Any ideas on what can be wrong here?
You want to submit the form, using Ajax, on click of $('#proceedWithSave')...
So just remove the $('#createCustomer').submit(function(ev) { line and its closing }); bracket.
function saveCustomer(){
//$('#createCustomer').submit(function(ev) {
//ev.preventDefault();
$('#submit').attr('disabled',true);
var $inputs = $('#createCustomer :input');
var values = {};
$inputs.each(function() {
values[this.name] = $(this).val();
});
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
})
$.ajax({
url: '/customer',
type : 'POST',
data : values,
success : function(data){
//check if controller validation send customer exist
if(data.confirmation){
$("#confirmation").show();
}
else{
$('#createCustomer :input').val('');
$("#customer").hide();
//assign values to success modal
$('#firstName').val(data.customer.firstName);
$('#lastName').val(data.customer.lastName);
$('#street').val(data.address.street);
$('#businessName').val(data.customer.businessName);
$('#submit').attr('disabled',false);
}
},
error : function(error){
$('#submit').attr('disabled',false);
}
});
//});
}
$('#proceedWithSave').on('click', function(){
var input = $("<input>")
.attr("type", "hidden")
.attr("name", "proceed");
$('#createCustomer').append($(input));
saveCustomer();
});
Related
I got an issue here. I found out that the global variable got changed every time it got into ajax.
$(document).on("keyup input", ".product-id", function () {
var id_prod = this.id.replace('prod_id_', '');
console.log('id_prod (outside ajax): ', id_prod);
var inputVal = $(this).val();
var resultDropdown = $('#result2').css({
"display": "block"
});
if (inputVal.length) {
$.ajax({
type: 'POST',
data: { term: inputVal },
url: 'backend-search-inv.php',
success: function (data) {
resultDropdown.html(data);
$(document).on("click", "#result2 p", function () {
var inv_id = $(this).text();
//console.log('inv_id: ',inv_id);
$.ajax({
type: 'POST',
data: {
term: inv_id
},
url: 'autocomplete_inv.php',
success: function (response) {
var inv_info = jQuery.parseJSON(response);
console.log('id_prod (in ajax): ', id_prod);
},
error: function () {
console.log('Unable to access database.');
}
});
}); //end of result being clicked
}
});
}
else {
resultDropdown.empty();
}
});
I don't get it why the variable id_prod gets incremented everytime when it goes into ajax. Here is the screenshot of the console.log.
Referring to the screenshot, everytime I want to enter something to the id_prod = 2, the ajax always ended up updating the id_prod = 1, and then id_prod = 2 again automatically, and result in duplication of my data.
Can someone help me on this?
So basically I just declare the id_prod as a global variable and assigned 0 as it's default value. Then, for id_prod is basically assigned to new value once it's in the keyup input event.
Thanks to Mohamed Yousef for his answer in my own question's comment section!
//DECLARE id_prod as a global variable...
var id_prod = 0;
$(document).on("keyup input", ".product-id", function(){
id_prod = this.id.replace('prod_id_', '');
var inputVal = $(this).val();
var resultDropdown = $('#result2').css({"display":"block"});
if(inputVal.length){
$.ajax({
type: 'POST',
data: {term:inputVal},
url: 'backend-search-inv.php',
success: function(data){
resultDropdown.html(data);
}
});
}
else{
resultDropdown.empty();
}
});
// WHEN RESULT BEING CLICKED...
$(document).on("click", "#result2 p", function(){
var inv_id = $(this).text();
$.ajax({
type: 'POST',
data: {term:inv_id},
url: 'autocomplete_inv.php',
success: function (response) {
var inv_info = jQuery.parseJSON(response);
console.log('id_prod (in ajax): ',id_prod);
$('#prod_id_'+id_prod).val(inv_info[0]);
$('#prod_qty_'+id_prod).val(1);
$('#prod_disct_'+id_prod).val(0);
$('#prod_type_'+id_prod).val(inv_info[1]);
$('#prod_colour_'+id_prod).val(inv_info[2]);
$('#prod_price_'+id_prod).val(inv_info[3]);
$('#result2').empty();
sumPrice();
},
error: function(){
console.log('Unable to access database.');
}
});});
Can someone say whats wrong with this lane data:... inside saveForm function?
I have list of tasks in my page. Every task has there own form where users can send comments. It means that I have several forms in one page. When I add new task AJAX update list of comments and then I try to send comment by one of the form and it raise error : “CSRF token missing or incorrect”. I have {% csrf_token %} in all my forms.
It seems like I need send CSRF in AJAX. Where I did mistake?
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
function csrfSafeMethod(method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
// TASK
$(function () {
var loadForm = function () {
var btn = $(this);
$.ajax({
url: btn.attr("data-url"),
type: 'get',
dataType: 'json',
beforeSend: function () {
$("#modal").modal("show");
},
success: function (data) {
$("#modal .modal-content").html(data.html_group_task_form);
}
});
};
var saveForm = function () {
var form = $(this);
$.ajax({
url: form.attr("action"),
data: form.serialize().append('csrfmiddlewaretoken', getCookie(csrftoken)),
type: form.attr("method"),
dataType: 'json',
success: function (data) {
if (data.form_is_valid) {
$("#task-list").html(data.html_task);
$("#modal").modal("hide");
}
else {
$("#modal .modal-content").html(data.html_task_form);
}
}
});
return false;
};
// Create task
$("#task-add-button").click(loadForm);
$("#modal").on("submit", ".js-task-add-form", saveForm);
// Update task
$("#task-list").on("click", "#js-edit-task-button", loadForm);
$("#modal").on("submit", ".js-task-edit-form", saveForm);
});
//TASK COMMENT ADD
$(".task-comment-form").submit(function(event) {
event.preventDefault();
console.log(event.preventDefault());
var form = $(this);
$.ajax({
url: form.attr("action"),
data: form.serialize().append('csrfmiddlewaretoken', getCookie(csrftoken)),
type: form.attr("method"),
dataType: 'json',
success: function (data) {
var current_group = form.closest('.custom-list-group');
if (data.form_is_valid) {
current_group.find(".task-comments").html(data.html_task_comment);
}
else {
current_group.find(".task-comment-form").html(data.html_task_comment_form);
}
},
});
form[0].reset();
return false;
});
CODE ABOUT COMMENT ADD:
views.py:
def task_comment_add(request, project_code, task_code):
data = dict()
project = get_object_or_404(Project, pk=project_code)
task = get_object_or_404(Task, pk=task_code)
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.author = request.user
comment.save()
task.comments.add(comment)
data['form_is_valid'] = True
data['html_task_comment'] = render_to_string('project/task_comment_list.html' {'task': group_task})
else:
data['form_is_valid'] = False
else:
form = CommentForm()
context = {'project': project, 'task': task, 'form': form}
data['html_task_comment_form'] = render_to_string('project/task_comment_form.html', context, request=request)
return JsonResponse(data)
JS:
// TASK COMMENT ADD
$(".task-comment-form").submit(function(event) {
event.preventDefault();
console.log(event.preventDefault());
var form = $(this);
$.ajax({
url: form.attr("action"),
data: form.serialize(),
type: form.attr("method"),
dataType: 'json',
success: function (data) {
var current_group = form.closest('.custom-list-group');
if (data.form_is_valid) {
current_group.find(".task-comments").html(data.html_task_comment);
}
else {
current_group.find(".task-comment-form").html(data.html_task_comment_form);
}
}
});
form[0].reset();
return false;
});
.append is for DOM elements.
The result of .serialize is a string.
Why don't you just put the token in a hidden input in the form with a 'name' attr of 'csrfmiddlewaretoken'?
That will serialize it with the rest of your form data.
Here's what I did that worked for ajax forms with Django:
$('#ajax_form').submit(function(e){
e.preventDefault();
var form = this;
var action = $(form).attr('action'); // grab the action as url
var form_array = $(form).serializeArray(); // use serializeArray
form_array.push({ // *expand the array to include a csrf token*
name: 'csrfmiddlewaretoken',
value: getCookie('csrftoken') // getCookie function from django docs
});
var form_data = $.param(form_array); // set it up for submission
$.post(action,form_data,function(resp){
// do stuff after receiving resp
});
});
Basically, I used jquery's .serializeArray() instead of serialize.
.serializeArray() gives you an array of objects like this:
[{name:'name1',value:'value1'},{name:'name2',value:'value2'}]
calling $.param(serilaized_array_data) turns it into a string for submitting. So the key is to add the csrf token to the array. I did that in the code above on the line from_array.push({... with the *'s in the comments.
The problem was in my view. I use this and error disappeared:
context = {...}
context.update(csrf(request))
hey guys i'm trying to make changes in my blade template using ajax , when i press the button it changes the value of data in database and i want to display this data at once on my blade template .
that's my java script code :
(function($){
$('.wishlistForm').on('submit', function(){
var form = $(this);
$.ajax({
url: form.attr('action'),
data: form.serialize(),
method: 'post',
dataType: 'json',
success: function(response){
var wishlistButton = form.find("button[type='submit']");
var x = parseInt($('.wish-btn-count').text());
if(response.actiondone == 'added') {
$('.wish-btn-count').text(x++);
console.log(x);
wishlistButton.text(response.message);
} else if(response.actiondone == 'removed') {
$('.wish-btn-count').text(x--);
console.log(x);
wishlistButton.text(response.message);
}
}
});
return false;
});
})(jQuery);
and here is the part i want to change in my template :
<div class="wish-btn-count" id="wishlist">
{{$wishlistcount}}
</div>
so how can i do it ? and for record it returns the value right in the console but don't show it in my view
Prevent the default submit event, so you can trigger the ajax
$('.wishlistForm').on('submit', function(e){
e.preventDefault();
This may be the solution.
If you are receiving json object response from the ajax call,first you have to parse that object and then use it.
Try this,
(function($){
$('.wishlistForm').on('submit', function(){
var form = $(this);
$.ajax({
url: form.attr('action'),
data: form.serialize(),
method: 'post',
dataType: 'json',
success: function(response){
/*Add this in your code*/
var response = JSON.parse(response.trim());
var wishlistButton = form.find("button[type='submit']");
var x = parseInt($('.wish-btn-count').text());
if(response.actiondone == 'added') {
$('.wish-btn-count').text(x++);
console.log(x);
wishlistButton.text(response.message);
} else if(response.actiondone == 'removed') {
$('.wish-btn-count').text(x--);
console.log(x);
wishlistButton.text(response.message);
}
}
});
return false;
});
})(jQuery);
I'm trying to get a value of several URL input and if value of URL isn't not valid, I just want to animate input element and stop everything.
Is there any way to do it?
$('button').click(function(e){
var linkarr = [];
var $input = $('.default');
var isValidUrl = /[0-9a-z_-]+\.[0-9a-z_-][0-9a-z]/; // URLvalid check
$input.each(function() {
var inputVal = $(this).val();
if(!isValidUrl.test(inputVal)) {
$(this).parent().animateCss('shake');
// if input is not valid, I want to stop the code here.
}
if(inputVal) linkarr.push(inputVal);
});
e.preventDefault();
$.ajax({
url: '/api/compress',
type: 'POST',
dataType: 'JSON',
data: {url: linkarr},
success: function(data){ something
});
});
You need to let outside of your each loop know the condition of the contents.
$('button').click(function(e){
var linkarr = [];
var $input = $('.default');
var isValidUrl = /[0-9a-z_-]+\.[0-9a-z_-][0-9a-z]/; // URLvalid check
var blnIsValid = true;
$input.each(function() {
var inputVal = $(this).val();
if(!isValidUrl.test(inputVal)) {
$(this).parent().animateCss('shake');
// if input is not valid, I want to stop the code here.
// Input isn't valid so stop the code
blnIsValid = false;
return false; // Alternatively don't stop so that any other invalid inputs are marked
}
if(inputVal) linkarr.push(inputVal);
});
e.preventDefault();
// Check to make sure input is valid before making ajax call
if (blnIsValid) {
$.ajax({
url: '/api/compress',
type: 'POST',
dataType: 'JSON',
data: {url: linkarr},
success: function(data){ something
});
}
});
One method is you can use flag to check and execute the Ajax method
$('button').click(function(e){
var linkarr = [];
var $input = $('.default');
var isValidUrl = /[0-9a-z_-]+\.[0-9a-z_-][0-9a-z]/; // URLvalid check
var callAjax = true;
$input.each(function() {
var inputVal = $(this).val();
if(!isValidUrl.test(inputVal)) {
$(this).parent().animateCss('shake');
callAjax = false;
return false;
// if input is not valid, I want to stop the code here.
}
if(inputVal) linkarr.push(inputVal);
});
e.preventDefault();
if(callAjax)
{
$.ajax({
url: '/api/compress',
type: 'POST',
dataType: 'JSON',
data: {url: linkarr},
success: function(data){ something
});
}
});
For some reason, my script isn't writing out the text after I remove the textbox element. Am I incorrectly using the .html or is something else wrong?
$('.time').click(function () {
var valueOnClick = $(this).html();
$(this).empty();
$(this).append("<input type='text' class='input timebox' />");
$('.timebox').val(valueOnClick);
$('.timebox').focus();
$('.timebox').blur(function () {
var newValue = $(this).val();
var dataToPost = { timeValue: newValue };
$(this).remove('.timebox');
if (valueOnClick != newValue) {
$.ajax({
type: "POST",
url: "Test",
data: dataToPost,
success: function (msg) {
alert(msg);
$(this).html("88");
}
});
} else {
// there is no need to send
// an ajax call if the number
// did not change
alert("else");
$(this).html("88");
}
});
});
OK, thanks to the comments, I figured out I was referencing the wrong thing. The solution for me was to change the blur function as follows:
$('.timebox').blur(function () {
var newValue = $(this).val();
var dataToPost = { timeValue: newValue };
if (valueOnClick != newValue) {
$.ajax({
type: "POST",
url: "Test",
data: dataToPost,
success: function (msg) {
}
});
} else {
// there is no need to send
// an ajax call if the number
// did not change
}
$(this).parent().html("8");
$(this).remove('.timebox');
});
$(this) in your success handler is refering to msg, not $('.timebox') (or whatever element that you want to append the html to)
$(this) = '.timebox' element but you have removed it already,
$.ajax({
type: "POST",
url: "Test",
data: dataToPost,
success: function (msg) {
alert(msg);
$(this).html("88"); // This = msg
}
and
else {
// there is no need to send
// an ajax call if the number
// did not change
alert("else");
$(this).html("88"); // this = '.timebox' element but you have removed it already,
}
The value of this changes if you enter a function. So when u use this in the blur function handler, it actually points to '.timebox'
$('.time').click(function () {
var valueOnClick = $(this).html();
var $time=$(this);//If you want to access .time inside the function for blur
//Use $time instead of$(this)
$(this).empty();
$(this).append("<input type='text' class='input timebox' />");
$('.timebox').val(valueOnClick);
$('.timebox').focus();
$('.timebox').blur(function () {
var newValue = $(this).val();
var dataToPost = { timeValue: newValue };
$(this).remove(); //Since $(this) now refers to .timebox
if (valueOnClick != newValue) {
$.ajax({
type: "POST",
url: "Test",
data: dataToPost,
success: function (msg) {
alert(msg);
$(this).html("88");
}
});
} else {
// there is no need to send
// an ajax call if the number
// did not change
alert("else");
$(this).html("88");
}
});
});