Updating rows that are added dynamically using ajax - javascript

I hope I can explain my issue clearly.
I am running a function to get values from a database using ajax, and adding each result as a row in a table. This is so the user can delete or edit any row they want. I'm adding IDs dynamically to the columns and also the edit and delete buttons which are generated. So it looks like this:
My code:
function getstationdata(){
var taildata1 = $('#tailnumber2').val();
var uid = $('#uid').val();
$.ajax({
// give your form the method POST
type: "POST",
// give your action attribute the value ajaxadd.php
url: "ajaxgetstationdata.php",
data: {tailnumber:taildata1, uid:uid},
dataType: 'json',
cache: false,
})
.success(function(response) {
// remove all errors
$('input').removeClass('error').next('.errormessage').html('');
// if there are no errors and there is a result
if(!response.errors && response.result) {
var trHTML = '';
$.each(response.result, function( index, value) {
trHTML += '<tr><td><input type="text" value="' + value[2] + '"></td><td><input type="text" class="weightinputclass"value="' + value[3] + '"></td><td><input type="text" class="arminputclass"value="' + value[4] + '"></td><td><input type="text" class="momentinputclass" value="' + value[5] + '"></td><td><button id="updatecgbtn" onclick="updatecg()"class="editbuttonclass">Edit</button></td><td><button id="deletecgbtn" class="deletebuttonclass"">Delete</button></td></tr>';
});
$('#mbtbody').html('');
$('#mbtbody').html(trHTML);
var ID = 0;
$('.weightinputclass').each(function() {
ID++;
$(this).attr('id', 'weightinputboxID'+ID);
});
var ID = 0;
$('.arminputclass').each(function() {
ID++;
$(this).attr('id', 'arminputboxID'+ID);
});
var ID = 0;
$('.momentinputclass').each(function() {
ID++;
$(this).attr('id', 'momentinputboxID'+ID);
});
var ID = 0;
$('.editbuttonclass').each(function() {
ID++;
$(this).attr('id', 'editbutton'+ID);
});
var ID = 0;
$('.deletebuttonclass').each(function() {
ID++;
$(this).attr('id', 'deletebutton'+ID);
});
} else {
// append the error to the form
$.each(response.errors, function( index, value) {
// add error classes
$('input[name*='+index+']').addClass('error').after('<div class="errormessage">'+value+'</div>')
});
}
});
}
The code I have when adding the info is in a form and it looks like this:
$('#addstations').on('submit', function(e){
e.preventDefault();
$.ajax({
type: $(this).attr('method'),
url: $(this).attr('action'),
data: $(this).serialize(),
dataType: 'json',
cache: false,
})
.success(function(response) {
$('input').removeClass('error').next('.errormessage').html('');
if(!response.errors && response.result) {
$.each(response.result, function( index, value) {
chartdata4=(tailnumber3.value)
});
} else {
// append the error to the form
$.each(response.errors, function( index, value) {
// add error classes
$('input[name*='+index+']').addClass('error').after('<div class="errormessage">'+value+'</div>')
});
}
});
});
I searched a bit on the internet and found out that I can't add a form inside my table for each row which would have been easy to do and I can reuse my code which I use when adding new info.
So, can someone please point me in the right direction?

Here is the direction you could go
$('#formTable').on('click',"button" function(e){
var $row = $(this).closest("tr"), $form = $("#addstations");
var data = {
passenger:$row.find("passengerClass").val(),
weight :$row.find("weightClass").val()
} // no comma on the last item
data["type"]=this.className=="deletebuttonclass"?"delete":"edit";
$.ajax({
type: $form.attr('method'),
url: $form.attr('action'),
dataType: 'json',
cache: false,
})
...

I assume that the problem is that you want to add a form as a child of a table / tbody element to wrap your row. You cannot do that and the browser will most likely strip the form tags, leaving you with nothing to serialize.
There are different solutions for that, for example:
Build the data object manually in javascript when a button on a row is clicked;
Use a non-form grid solution for your layout.
Add each row in its own table and have the form wrap that table
The third solution is a bit of a hack, I would use the first or the second myself.

Related

How to make ajax call works only for inputs in the same row, when using (.clone())

I’ve ajax code to append “unit menu” based on “product item” selection.
When I create a new row, and select an item from “product menu” I expected that the “unit input” of the same row must affect and append the “unit menu” belongs to the selection of the "product item" in the same row.
But I noticed that when a new row created by cloning and I select a product (all the above rows also affect, i.e after product item selection the "unit menu" of the same row and the "unit menu" of the above rows also affected)
The next code illustrate what I mean....
$(document).ready(function() {
var purchase = $('.purchase-row').last().clone();
let purchaseCount = 0;
$(document).on('click', '.add_item', function() {
var clone = purchase.clone().prop('id', 'product_' + purchaseCount);
// var clone = purchase.clone().prop('class', 'product_' + purchaseCount);
console.log('clone: ', clone);
$(this).prevAll('.purchase-row').first().after(clone.hide());
clone.slideDown('fast');
$('#product_'+ purchaseCount).find('#id_pro-product').removeClass('product').addClass('newProduct');
$('#product_'+ purchaseCount).find('#id_pro-unit').removeClass('unit').addClass('newUnit');
purchaseCount++;
console.log('PURCHASE-COUNT: ', purchaseCount);// $(this).parent().slideUp('fast');
// The next code for reinitialize select2
var $example = $(".js-programmatic-init").select2();
$example.select2();
});
$(document).on('click', '.purchase-minus', function() {
if (purchaseCount == 0) {
// Do nothing.
alert('You can not delete this row' );
} else {
$(this).closest('.purchase-row').remove();
purchaseCount--;
console.log('PURCHASE-COUNT2: ', purchaseCount);
}
});
$(document).on('click', '.purchase-broom', function() {
$(this).closest('.purchase-row').find('input').val('');
});
$(document).on('change', '.product', function(e){
var id = $(this).val();
console.log('CHANGED-PRODUCT: ', id);
$.ajax({
type: 'POST',
url: '{% url "purchases:get_product_unit" %}',
// dataType: 'json',
// async: true,
// cache: false,
data: {
'pro-product': $('.purchase-row select').closest('.product').val(), // this is right
// find('#id_pro-product')
},
success: function (data) {
console.log(
'FROM SUCCESS: ', data['unit'],
);
var values_3 = data['unit'];
// $('#id_pro-unit').text('');
// $('select').closest('.unit').find('select').text('');
$('select').closest('.unit').text('');
if (values_3.length > 0) {
for (var i = 0; i < values_3.length; i++) {
// $('#id_pro-unit').append('<option>' + values_3[i] + '</option>');
$('select').closest('.unit').append('<option>' + values_3[i] + '</option>');
}
}
},
error: function (){
console.log('ERROR with ajax request in Adding Purchase !!!');
},
});
e.preventDefault();
});
The next image indicates the main row which I want to clone
Image of the main row
The next image indicates an example for creating 2 rows from the main one.
Image of cloning rows
You can notice a bug in the cloning inputs due to using of (select2 plugin),I raised an issue in Select2 forum(but I havegot no answer till now), So I'll ask a new question here about that behavior..
My view to handle ajax
from django.http import JsonResponse
def get_product_unit(request):
data = {}
product = request.POST.get('pro-product')
if product is not None:
unit = UOM.objects.values('unit__name', 'uom_options', 'unit').filter(product_id=product)
print('purchase not purchase')
else:
unit = []
data['unit'] = [(obj['unit__name']) for obj in unit]
print(
'PRODUCT: ', product,
'UNIT: ', unit,
)
return JsonResponse(data)
My tries to fix this problem
1- In fact I tried to make a new ajax call for the new cloned row, but I realize that it can solve by the above ajax code (I don't know how).
I think if I knew to access the "class and id" of the new row itself
$(document).on('change', '.newProduct', function(e){
var id = $(this).val();
console.log('SUCCESS-CHANGE-PRODUCT-FROM-NEW-CLASS: ', id);
$.ajax({
type: 'POST',
url: '{% url "purchases:get_new_row_unit" %}',
// dataType: 'json',
// async: true,
// cache: false,
data: {
'pro-product': id,
// $('#product_'+purchaseCount).closest('.newProduct select').val(),
// find('#id_pro-product')
},
success: function (data) {
console.log(
'FROM SUCCESS-NEW-CLASS: ', data['unit'],
'PRODUCT-FROM-NEW-CLASS: ', data['product'],
);
var values_3 = data['unit'];
// $('#id_pro-unit').text('');
// $('select').closest('.newUnit').text('');
if (values_3.length > 0) {
for (var i = 0; i < values_3.length; i++) {
// $('#id_pro-unit').append('<option>' + values_3[i] + '</option>');
// $('.newUnit select').closest('#product_'+ purchaseCount).append('<option>' + values_3[i] + '</option>');
// $('select').closest('#product_'+ purchaseCount).find('.newUnit').append('<option>' + values_3[i] + '</option>');
//$('select').closest('.newUnit').append('<option>' + values_3[i] + '</option>');
$('.purchase-row #id_pro-unit').append('<option>' + values_3[i] + '</option>');
}
}
},
error: function (){
console.log('ERROR with ajax request in Adding Purchase-New Class !!!');
},
});
e.preventDefault();
});
});
My view
def get_new_row_unit(request):
data = {}
product = request.POST.get('pro-product')
data['product'] = product
if product is not None:
unit = UOM.objects.values('unit__name', 'uom_options', 'unit').filter(product_id=product)
else:
unit = []
data['unit'] = [(obj['unit__name']) for obj in unit]
print(
'PRODUCT: ', product,
'UNIT: ', unit,
)
return JsonResponse(data)
2- Also I tried to do like this Answer But I failed.
3- Also I follow instructions in this answer
But I get the "unit menu" of the main row in all new row when I select an item from the "product menu" in the new row.
My Problem in brief
When I select an item from "product" menu in the first "new cloned row" (or from any new rows)."unit menu" append to all above rows.
What I want to achieve
I want when I select an item from "product menu" only "unit menu" append to the "unit input" of the same row.
I knew that I've missed something but I failed to discover it.
Any suggestions will be appreciated.
=============================================================
My Answer To This Issue After searching and Thinking
=============================================================
Finally I fix my issue as usual (thanks to stackoverflow community).
I want to share my solution of this issue.
Really it took time to understand how it works and how to access the new row or (in other words "how to access the row inputs itself").
My Problem in brief :
When I select an item from "product" menu in the first "new cloned row" (or from any new rows)."unit menu" append to all above rows.
After searching on the web and searching here in the community questions. I found the next answers are useful and helpful.
Thanks to this answer by #martynas
Thanks to this answer by #Евгений Одинец
Thanks to this tutorial
And as I said it can be done by one ajax call.
1- In fact I tried to make a new ajax call for the new cloned row, but I realize that it can solve by the above ajax code (I don't know how).
The final code has became as follow
$(document).on('change', '.product', function(e){
var product_id = $(this).val();
let $el = $(this).closest('.purchase-row');
console.log('SUCCESS-CHANGE-PRODUCT: ', product_id,);
$.ajax({
type: 'POST',
url: '{% url "purchases:get_product_unit" %}',
data: {
'pro-product': product_id,
},
success: function (data) {
if (purchaseCount == 0) {
console.log('purchase count equal to ZERO: ');
console.log(
'FROM SUCCESS: ', data['unit'],
);
var values_3 = data['unit'];
if (values_3.length > 0) {
for (var i = 0; i < values_3.length; i++) {
$el.find('.unit').append('<option>' + values_3[i] + '</option>');
}
}
} else {
let unit = $el.find('.newUnit'); // here I can access the "unit input" of the same row of the "product input"
var values_3 = data['unit'];
unit.text('');
console.log('COUNT IS NOT EQUAL TO ZERO:', values_3);
if (values_3.length > 0) {
for (var i = 0; i < values_3.length; i++) {
unit.append('<option>' + values_3[i] + '</option>');
}
}
}
},
error: function (){
console.log('ERROR with ajax request in Adding Purchase !!!');
},
});
e.preventDefault();
});
Also I found some answers about how to copy table row to another table and these answers help me a lot.
Here is some of them
How to pass clicked/selected row data from one table to another table
Remove row from one table and add it to another with jQuery
How to read dynamically generated HTML table row's 'td' value

Get the value of input tag for Ajax Request

<input type="text" id="autocomplete">
<ul></ul>
<script>
var value;
var wikiapi;
$('#autocomplete').on('keypress',function(e){
if(e.which==13){
value=$(this).val();
wikiapi="https://en.wikipedia.org/w/api.php?action=query&prop=iwlinks&iwprop=url&titles="+value+"&format=json";
$.ajax({
url:wikiapi,
crossDomain:true,
dataType:"jsonp",
xhrFields: {
withCredentials: true
},
success: function(data){
var links=data.query.pages[171166].iwlinks;
var title=data.query.pages[171166].title;
$.each(links,function(i,val){
$('ul').append('<li><a href='+val.url+'>'+title +'</a></li>');
});
console.log(data.query.pages[171166].iwlinks[0].url);
}
});
}
});
</script>
Hi, I am trying to retrieve the value from input tag. But It seems the method I've tried is not working. The value is not passed to the wikiapi var at all. Hence the ajax request cannot proceed. Can anyone point out the problem please.
I've also tried "..$('#autocomplete').on('click',function(){
........} also but not working.
I did a quick check inside the success function as to what data was storing. After just a couple of examples I noticed the key (the six digits) were different for each example. Therefore, var links=data.query.pages[171166].iwlinks; and var title=data.query.pages[171166].title; will only work for test. In order to get the keys of data.query.pages you need a for loop. I've also added $('ul').empty() to empty out whatever was in the list. Here's the code needed to get it to work:
var value;
var wikiapi;
$('#autocomplete').on('keypress', function(e) {
if (e.which == 13) {
value = $(this).val();
wikiapi = "https://en.wikipedia.org/w/api.php?action=query&prop=iwlinks&iwprop=url&titles=" + value + "&format=json";
$.ajax({
url: wikiapi,
crossDomain: true,
dataType: "jsonp",
xhrFields: {
withCredentials: true
},
success: function(data) {
$('ul').empty();
for (var key in data.query.pages) {
if (data.query.pages.hasOwnProperty(key)) {
var links = data.query.pages[key].iwlinks;
var title = data.query.pages[key].title;
}
}
$.each(links, function(i, val) {
$('ul').append('<li><a href=' + val.url + '>' + title + '</a></li>');
});
}
});
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="autocomplete">
<ul>
</ul>
When I paste your code to jsfiddle with this success function success: function(data){ console.log(data) } the ajax call works fine.
So you have an Problem to handle your result from the API.
I have rewritten your code to make it more readable:
$(document).on('keypress', '#autocomplete', function (e) {
if (e.which === 13) {
var options = {
url: "https://en.wikipedia.org/w/api.php",
data: {
action: "query",
prop: "iwlinks",
iwprop: "url",
titles: $(this).val(),
format: "json"
},
crossDomain: true,
dataType: "jsonp",
xhrFields: {
withCredentials: true
}
};
$.ajax( options ).done(function (data) {
var html ='';
$.each(data.query.pages, function(pageKey, pageValue) {
$.each(pageValue.iwlinks, function(linkKey, linkValue) {
html += '<li>' + pageValue.title + '</li>';
});
});
$('ul').html(html);
}).fail(function (err) {
console.log(err);
alert('Ooops');
});
}
});
I have extracted the ajax options and added the GET parameter from the URL to them. I also iterate over result pages and the link object to generate the listitems.
Here can you read about the jQuery ajax method and the options: https://api.jquery.com/jQuery.ajax/

How to make table updating content without refresh the whole page

i've made a project using php ajax i use it for input data and displaying data into a table. the code work fine but when displaying data the table content didnt update the latest input in there i need to refresh page to update them.
anyone know how to make it update without refresh the whole page?
this my ajax function for input and displaying
INPUT
$(document).on('click','#ok',function(e) {
if ($('#netto').val() == '') {
alert('Kolom Netto Tolong Di Isi');
} else {
var data = $("#form_input").serialize();
$.ajax({
data: data,
type: "post",
url: "../php/bkk/bkk_i.php",
success: function(data){
alert("Data: " + data);
}
});
}
clearInput();
});
$("#form_input").submit( function() {
return false;
});
function clearInput() {
$("#form_input :input").each( function() {
$('#nopol').val('');
$('#netto').val('');
});
}
Display
$(document).ready(function(){
$.ajax({
type: "Post",
url: "../php/bkk/bkk_isel.php",
success: function(data){
var list = JSON.parse(data);
for(var i = 0; i < list.length; i++){
$('#mat').val((list[i]['material']));
$('#lok').val((list[i]['lokasi']));
$('#kpl').val((list[i]['kapal']));
$('#po_numb').val((list[i]['po']));
$('#dok').val((list[i]['doc_mat']));
var tr = "<tr>";
tr += "<td>"+list[i]['no']+"</td>";
tr += "<td>"+list[i]['tanggal']+"</td>";
tr += "<td>"+list[i]['no_pol']+"</td>";
tr += "<td>"+list[i]['netto']+"</td>";
tr += "</tr>";
$("#table_s tbody").append(tr);
}
return false;
}
});
});

Value posts firstly and then only it finishes input (if clicked). needed backwards(code is corect)

I have dropdown list of country suggestions and input above. When i click on one of them - AJAX should work(and it does) and add value to #msg_native. HTML:
echo '<div class="search_native"><input type="text" name="native_input" id="native"/>';
echo "<div id='output'></div></div>";
All JQUERY :
<script type="text/javascript">
$(document).ready(function() {
$("input").keyup(function(){
$array = ['usa','france','germany'];
$input_val = $("input[name='native_input']").val();
$('#output').text('')
r = new RegExp($input_val)
for (i = 0; i < $array.length; i++) {
if ($array[i].match(r)) {
$('#output').append('<p class="match">' + $array[i] + '</p>')
}
}
});
$(document).on('click', '.match', function(){
$value = $(this).text();
$('#native').val($value);
});
});
</script>
<script type="text/javascript">
$(function() {
$('#native').change(function() {
alert('cl');
$.ajax({
type: "POST",
url: "home.php",
dataType: 'json',
encode: true,
data: {native_input: $("input[name='native_input']").val()},
cache: false,
success: function(data){
alert(data);
$("#msg_native").after(data);
}});
return false;
});
});
</script>
The problem is that the value that gets posted is only what Ive typed myself, regardless on clicked element. But I want complete value- not only typed letters...so it firstly posts value and then 'finishes' the input (if clicked)
What can you practically advice to me?
data: {native_input: $value},
returns empty string
Some of this might be debatable but I put those in place for maintainability of the code and/or to match the most recent jQuery.
Only use one document ready handler (if possible)
Remove all the global objects (put var in front of them)
Use the native id when possible as fastest selector (not $("input[name='native_input']") for instance)
use this in the event handler, not the full selector (see next item)
If I enter "France" not "france" match does not work so need to case that input to equality var $input_val = $(this).val().toLowerCase();
You start with an empty field, might be good to show the match for that - simply trigger the keyup on startup to show all the array: }).trigger('keyup'); Now they are available for your clicking.
Attach the click handler on the wrapper for the "match" elements: $('#output').on('click', '.match', function() {
Use the promise form of the ajax .done(
Create a new custom event instead of the "change" on the native. We can then trigger that event as/when needed (the real issue you describe) Example: $('#native').trigger('myMatch'); and as I use it here:
trigger the event on a full match:
if (jQuery.inArray($input_val, $array) !== -1) {
$(this).trigger('myMatch');
}
Revised code:
$(document).ready(function() {
$("#native").on('keyup', function() {
var $array = ['usa', 'france', 'germany'];
var $input_val = $(this).val().toLowerCase();
$('#output').html('');
var r = new RegExp($input_val);
for (var i = 0; i < $array.length; i++) {
if ($array[i].match(r)) {
$('#output').append('<p class="match">' + $array[i] + '</p>');
}
}
// full match entered, trigger the match
if (jQuery.inArray($input_val, $array) !== -1) {
$(this).trigger('myMatch');
}
}).on('myMatch', function() {
alert('cl');
var nativeMatch = {
native_input: $("#native").val()
};
$.ajax({
type: "POST",
url: "home.php",
dataType: 'json',
encode: true,
data: nativeMatch,
cache: false
}).done(function(data) {
alert(data);
$("#msg_native").after(data);
});
return false;
}).trigger('keyup');
$('#output').on('click', '.match', function() {
var $value = $(this).text();
$('#native').val($value).trigger('myMatch');
});
});

how to clean option values under select - html tag

I am using two drop down(first drop-down category and second drop-down sub category) in a page,both drop-down will be loaded dynamically, in which I will be selecting a value from first drop-down accordingly I have to load value to second drop-down.I has done that,but thing is that it will get done for first time.
But when I click on some other option in states drop-down, its not getting updated on second drop-down.
And My code is:
This piece of code is to get list of category while loading page ie under document.ready
$.ajax({
url : "../category/getCategory",
type : "post",
contentType : "application/json",
dataType : "json",
success : function(data) {
var categoryBOs = data.categoryBOs;
$.each(categoryBOs, function(key, value) {
$("#productCategory").append(
'<option value='+value.categoryId+'>'
+ value.categoryName
+ '</option>');
});
}
});
This part of ajax is to load sub category
$("#productCategory").on('change', function() {
alert($(this).val());
$.ajax({
url : "../category/getSubCategory",
type : "post",
cache : false,
dataType : "json",
data : "categoryId=" + $(this).val(),
success : function(data) {
var subCategoryBOs = data.subCategoryBOs;
$.each(subCategoryBOs, function(key, subCategoryBO) {
subCategories.push({lable:subCategoryBO.categoryId , value:subCategoryBO.categoryName});
$("#productSubCategory").append(
'<option value='+subCategoryBO.categoryId+'>'
+ subCategoryBO.categoryName
+ '</option>');
});
}
});
});
From what I see in your code you always append new entries, yet never remove old ones before. So possibly your list just keeps getting longer with new entries at its end? Try to remove the entries before append new ones:
$("#productSubCategory option").remove();
$("#productSubCategory").append(
'<option value=' + subCategoryBO.categoryId + '>' + subCategoryBO.categoryName + '</option>');
In my experience $.each with $.append can get very slow at some amount of list entries. I would rewrite it in native javascript with for() and createElement().
Try adding $("#productCategory").empty() before the first $.each and $("#productSubCategory").empty() before the second $.each.
you need to make html in .each and append after .each end. No option change from first drop down you need to remove the previous on by using $("#productSubCategory option").remove();
$.ajax({
url: "../category/getCategory",
type: "post",
contentType: "application/json",
dataType: "json",
success: function (data) {
var categoryBOs = data.categoryBOs;
var html = '';
$.each(categoryBOs, function (key, value) {
html += '<option value=' + value.categoryId + '>' + value.categoryName + '</option>';
});
$("#productCategory").append(html);
}
});
$("#productCategory").on('change', function () {
alert($(this).val());
$.ajax({
url: "../category/getSubCategory",
type: "post",
cache: false,
dataType: "json",
data: "categoryId=" + $(this).val(),
success: function (data) {
var subCategoryBOs = data.subCategoryBOs;
var html = '';
$.each(subCategoryBOs, function (key, subCategoryBO) {
subCategories.push({ lable: subCategoryBO.categoryId, value: subCategoryBO.categoryName });
html += '<option value=' + subCategoryBO.categoryId + '>' + subCategoryBO.categoryName + '</option>';
});
$("#productSubCategory").append(html);
}
});
});
Just simple thing you have to do here is that every time when you load sub-categories just place following before that .
$(dropdown).empty();
Thanks !
$("select#catname").change(function () {
// part of code
$("#subcatname").append($newOpt1);
// appending the category of dropdown
}
$("#subcatname").trigger('contentChanged');
// changing the contenet
}
});
$("select#subcatname").change(function () {
// something changes after trigger in dropdown
});
// removing the content or clearing the content after selecting
$("#subcatname").empty();
});
});

Categories