I am using jQuery Datatables, and am working on an inline editing feature. I have been trying to get a green check to show when the record is updated.
Here is the ajax that populates the datatable:
$.ajax({
url: 'api/massEditorSummary.php',
type: 'POST',
data: data,
dataType: 'html',
success: function(data, textStatus, jqXHR)
{
var jsonObject = $.parseJSON(data);
var table = $('#example1').DataTable({
"data": jsonObject,
"columns": [
{ "data": "partner_name" },
{ "data": "service" },
{
"data": "forecast",
"fnCreatedCell": function (nTd, sData, oData, iRow, iCol)
{
$(nTd).html("<input type='text' class='form-control editForecast'
id='editForecast' data-uid='"+oData.UID+"' data-editforecast='"+oData.forecast+"'
value='"+oData.forecast+"' style='width:75px; height:30px;' />
<span id='testID' style='display: none;'><i class='fa fa-check' id='updatedIcon' aria-hidden='true'
style='color:green;'> </i></span>");
}
}
],
"stateSave": true,
"autoWidth": false
});
},
error: function(jqHHR, textStatus, errorThrown)
{
// show fail stuff
}
});
If you'll notice in the data column "forecast", I have a span with an ID set to testID. This span includes a font-awesome check icon. I initially set it to display: none.
Now I have this update feature that functions on BLUR event:
$('#example1').on('blur', 'tr > td > .editForecast', function(e)
e.preventDefault();
var uid = $(this).attr('data-uid');
var forecastcurval = $(this).attr('data-editforecast');
var forecastnewval = $(this).val();
var forecastData = '';
$.post('api/inlineEditProcess.php', {uid:uid, forecastcurval:forecastcurval, forecastnewval:forecastnewval}, function(data)
{
forecastData = data;
callForecastFunction(forecastData);
});
function callForecastFunction(forecastData)
{
if(forecastData == "Success")
{
$(this).css('display', 'inline-block'); // this is where I want to show the check
}
else
{
// do fail stuff
}
}
});
You'll see in the callForecastFunction function, if the data that is returned from the process script equals 'success', then show the check.
As mentioned above duplicate id attributes are not allowed. You should fix both the input and span id's. The span id you can base off the UID, for example:
"<span id='" + rowData.UID + "' style='display: none;'><i class='fa fa-check' id='updatedIcon' aria-hidden='true' style='color:green;'> </i></span>");
You can add additional text to make it more unique.
Then change the selector in your callForecastFunction() to select the span based on the UID:
$('#' + uid).css('display', 'inline-block'); // this is where I want to show the check
BTW, it looks like you are missing { in the event handler function:
$('#example1').on('blur', 'tr > td > .editForecast', function(e)
Related
I am trying to change the text of the button clicked, using beforeSend and Complete in an ajax function, changing the text from Add to Cart > Adding... > Added to Cart, but the text is changed in all buttons, not sure how to target the button clicked.
HTML - the button text is wrapped in a space with data attributes
<span class="js-btn-cta" data-addbtn="{{ btn_txt }}" data-soldout="{{ btn_txt_soldout }}" data-offerbtn="{{ btn_txt_selling }}" data-adding-cart="{{ btn_adding }}" data-added-cart="{{ btn_added }}">
JS - I am then changing the text before the request is sent and once complete using the following methods;
//START AJAX API ADD TO CART FUNCTION
let miniCartContentsSelector = '.js-mini-cart-contents';
let addingCartBtn = $('.add-to-cart-button');
let addingCartText = $('.js-btn-cta');
let ajaxify = {
onAddToCart: function(event){
event.preventDefault();
$.ajax({
type: 'POST',
url: '/cart/add.js',
data: $(this).serialize(),
dataType: 'json',
beforeSend: function(e) {
//Update btn text on product and collection pages
dataAddingCart = addingCartText.attr('data-adding-cart'),
addingCartText.text(dataAddingCart);
},
complete: function(e) {
//Update btn text on product and collection pages
dataAddedCart = addingCartText.attr('data-added-cart'),
addingCartText.text(dataAddedCart);
},
success: function(){
ajaxify.onCartUpdated();
currencyPicker.setCurrencyText();
},
error: ajaxify.onError
});
shippingBar.update();
},
onCartUpdated: function() {
$.ajax({
type: 'GET',
url: '/cart',
context: document.body,
success: function(context){
let
$dataCartContents = $(context).find('.js-cart-page-contents'),
$dataCartContentsPrice = $(context).find('.js-total'),
dataCartHtml = $dataCartContents.html(),
dataCartItemCount = $dataCartContents.attr('data-cart-item-count'),
dataCartItemTotal = $dataCartContentsPrice.attr('data-cart-item-total'),
$miniCartContents = $(miniCartContentsSelector),
$cartItemCount = $('.js-cart-item-count'),
$closeIcon = $('.js-close-cart'),
$cartItemTotal = $('.js-cart-item-total');
$cartItemCount.text(dataCartItemCount);
$cartItemTotal.html('<span class="money">' + dataCartItemTotal + '</span>');
$miniCartContents.html(dataCartHtml);
//change currency in cart when changed
currencyPicker.setCurrencyText();
Currency.convertAll(shopCurrency, Currency.currentCurrency);
if (parseInt(dataCartItemCount) > 0){
ajaxify.openCart();
$('.js-minus').prop("disabled", true);
}
else {
ajaxify.closeCart();
}
//close the cart drawer when clicking on x in cart header
function closeClick(event){
$('body').removeClass('show-sidebar');
console.log('close icon btn clicked');
}
//end close the cart drawer when clicking on x in cart header
//call the closeClick function
$('.js-close-cart').click(closeClick);
//end call the closeClick function
}
});
//reset pdp qty value to 1 once add to cart has been clicked
$(".js-quantity-field-pdp").val("1");
shippingBar.update();
ajaxify.closeModal();
},
onError: function(XMLHttpRequest, textStatus){
let data = XMLHttpRequest.responseJSON;
alert(data.status + ' - ' + data.message + ': ' + data.description);
},
openCart: function(){
let isInCartPage = window.location.href.indexOf('/cart') === -1;
if(isInCartPage) {
$('body').addClass('show-sidebar');
}
},
closeCart: function(){
$('body').removeClass('show-sidebar');
},
closeModal: function(){
$('.modal').modal('hide');
$('.modal-backdrop').modal('hide');
},
onCartButtonClick: function(event){
event.preventDefault();
//If the body has a class of show-sidebar, return TRUE.
let isCartOpen = $('body').hasClass('show-sidebar');
let isInCart = window.location.href.indexOf('/cart') === -1;
if(!isInCart) {
if(!isCartOpen) {
ajaxify.openCart();
}
else {
ajaxify.closeCart();
}
}
},
init: function(){
$(document).on('submit', addToCartFormSelector, ajaxify.onAddToCart);
$(document).on('click', '.js-menu-toggle active', ajaxify.onCartButtonClick);
$(document).on('click', '#mini-cart .js-keep-shopping', ajaxify.onCartButtonClick);
}
};
//initiate the function
ajaxify.init();
The problem is it changes button text for other buttons not clicked.
Thanks
You get all button with class "js-btn-cta" and you change the text attribute to all button with this class. Not only the action button.
Inside onAddToCart, you have to get the clicked button.
onAddToCart: function(event){
var clickedButton = $(this);
event.preventDefault();
$.ajax({
type: 'POST',
url: '/cart/add.js',
data: $(this).serialize(),
dataType: 'json',
beforeSend: function(e) {
//Update btn text on product and collection pages
dataAddingCart = clickedButton.attr('data-adding-cart'),
clickedButton.text(dataAddingCart);
},
complete: function(e) {
//Update btn text on product and collection pages
dataAddedCart = clickedButton.attr('data-added-cart'),
clickedButton.text(dataAddedCart);
},
I have a data table and in each row I have a button Delete.
ON click of Delete i am making an ajax call and deleting the row from server by passing the id.
But on success of ajax call the row is not getting deleted in the table from UI.
Below si the code.
I have rendered the column for Delete
{
"data": "Action","orderable": false, "render": function(data, type, row) {
userSignum=readCookie("userSignum");
var userIDMGroups=readCookie("nfvDBGroups");
var userIDMGroupsArray=userIDMGroups.split(';')
if((jQuery.inArray(userIDMGroups,userIDMGroupsArray ) !== -1)&&(row['signumId'] == userSignum) )
{
return '<button class="btn btn-action deleterecord" id="'+row.id+'">Delete</button>'
}
else
{
return '<button class="btn btn-action deleterecord" id="'+row.id+'" disabled="disabled">Delete</button>'}
}
}
Below si the ajax call
$("#searchTable tbody").on("click", ".deleterecord", function () {
var table = $('#searchTable').DataTable();
var recordId=$(this).attr("id");
// var $row = $(this);
if(recordId!=null){
$.ajax({
type: 'POST',
url: config.vnfURL + 'vnf/delete',
dataType: "json",
contentType: "application/json; charset=utf-8",
data : JSON.stringify({"id" : recordId }),
processData: false,
success: function(response, textStatus, jqXHR) {
// table.row( $(this).parents('tr') ).remove().draw();
//$(recordId).remove();
table.row($(this).parents('tr')).remove().draw(false);
alert("record deleted");
if(jqXHR.status == "200"){
className = "alert-success";
msg = "Record has been deleted Successfully.";
} else {
className = "alert-danger";
msg = "Something wrong, please try again after sometime.";
}
$("#infoDiv").addClass(className).show();
$("#infoDiv>center>p").html(msg);
setTimeout(function() {
$("#infoDiv").removeClass(className).hide();
$("#infoDiv>center>p").html("");
// window.location = "/resources/search.html";
}, 7000);
},
please help
The reason is that this within AJAX success callback refers to XHR object, so you may assign const tr = table.row($(this).closest('tr')) outside of success callback and then do tr.remove().draw() upon successful deletion server-side.
p.s. also, note that I have used closest('tr') rather than parents('tr') as it is less error prone, since the latter may return array if your button happen to have multiple <tr> parents
Add this line on success call back of ajax
table.row( $(this).parents('tr') ).remove().draw();
I have two jquery dataTables in my php file. First table is loaded in the main file php from mysql database. The second table is loaded with ajax to the same php file but the content depend of row clicked on the first dataTable.
I have a problem, when I click the row of the first dataTable it loads the second table correctly. However when I click a row in the second dataTable not get some value, like not found the row. It show undefined value...
$(document).ready(function() {
**//I create dataTable 1**
var table = $('#example').DataTable({
"language": {
"url": "//cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/Spanish.json"
}, "dom": '<"toolbar">frtip'
});
**//I create dataTable 2**
var table2 = $('#example2').DataTable({
"language": {
"url": "//cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/Spanish.json"
}, "dom": '<"toolbar">frtip'
});
**//I load dataTable 1**
$('#example tbody').on( 'click', 'tr', function () {
if ( $(this).hasClass('selected') ) {
$(this).removeClass('selected');
}else{
table.$('tr.selected').removeClass('selected');
$(this).addClass('selected');
var getted = table.row('.selected').data();
$.ajax({
type:'POST',
data: 'usuario=' + getted,
url: 'loadF1.php',
success: function(msg) {
$('#example2 tbody').html(msg); //Here set content into div2
}
});
**//I load dataTable 2**
$('#example2 tbody').on( 'click', 'tr', function () {
if ( $(this).hasClass('selected') ) {
$(this).removeClass('selected');
}else{
table2.$('tr.selected').removeClass('selected');
$(this).addClass('selected');
var getted2 = table2.row('.selected').data();
$.ajax({
type:'POST',
data: 'usuario=' + getted2,
url: 'loadF2.php',
success: function(msg) {
$('#example3 tbody').html(msg); //Here set content into div3
}
});
What am I doing wrong, why when I select the second table it's not getting get the row selected?
Thanks!
I have a modal that displays a table. And I use datatable plugin so that the data is searchable and sortable. It works properly at first but when I close the modal and click other link to the same modal, it displays error. I have found solution to destroy the DataTable and I put the destroy() before the initialization of the datatable but then no data is displayed inside the table.. if I put it after the initialization it gave me the initialization error the second time I click the button. How am I going to solve this?
here's my code:
$.ajax({
url: "<?php echo site_url('admin/group/getMember')?>",
type: 'POST',
data: { 'groupID': id},
dataType: 'JSON',
success: function(result){
$('#records_table tbody').empty();
// $('#records_table').DataTable({
// "bLengthChange": false,
// "paging":false,
// });
$('.modal-header #hdrmsg').text(result[0].fname);
var trHTML='';
$.each(result, function (i, item) {
trHTML += '<tr><td>' + item.fname + '</td><td>' + item.mname + '</td><td>' + item.lname + '</td></tr>';
});
$('#records_table tbody').append(trHTML);
$('#records_table').DataTable({
"bLengthChange": false,
"paging":false,
});
$('#records_table').DataTable().fnDestroy();
}
});
The main reason for destroying a dataTables instance is if you want to change the initialisation options - like change paging and so on. Or if the table structure should be altered. None of those circumstances seems to be the case here? To answer the question, the safest way to destroy and reinitialise a table is to use the shorthand option destroy: true :
var table = $('#records_table').DataTable({
...
destroy : true
});
To go further, I think you are doing it a little backwards.
Why empty the table with jQuery $('#records_table tbody').empty(); instead of table.clear() ?
Why inject records with jQuery $('#records_table tbody').append(trHTML); instead of using table.row.add([...]) ?
Here is a code scenario similar to the one in the question, which reinitialises the dataTable without conflicts, each time the modal is shown :
var table;
$('#modal').on('show.bs.modal', function() {
$.ajax({
url: url,
dataType: 'JSON',
success: function(response) {
var response = $.parseJSON(response.contents);
//clear the table, if it exists
if (table) table.clear();
//reinitialise the dataTable
table = $('#records_table').DataTable({
destroy: true,
bLengthChange: false,
paging: false
});
$.each(response, function(i, item) {
console.log("inserting", item);
table.row.add([
item.name,
item.position
]).draw();
});
}
});
});
see demo -> http://jsfiddle.net/bz958dxj/
But you really dont need to destroy the table at all, it just slows down performance :
//global table object
table = $('#records_table').DataTable({
bLengthChange: false,
paging: false
});
$('#modal').on('show.bs.modal', function() {
$.ajax({
url: url,
dataType: 'JSON',
success: function(response) {
var response = $.parseJSON(response.contents);
//clear the table
table.clear();
//insert data
$.each(response, function(i, item) {
console.log("inserting", item);
table.row.add([
item.name,
item.position
]).draw();
});
}
});
});
demo -> http://jsfiddle.net/8mjke9ua/
NB: I just assume we are talking about bootstrap modals, based on the reference to .modal-header in the question.
NBĀ²: Notice the $.parseJSON(response.contents), you should do it as you are doing it in the question. The only reason for this is that the examples go trough a proxy to avoid the same-origin policy.
FOUND THE PROBLEM:
Just needed to replace row.replaceWith with row.parent().parent().replaceWith().
I'm trying to update a WebGrid row with JQuery after I've clicked a submit button in a modal dialog, but the updated data just append the last column, not the whole row as I want.
Let's say I want the table to look like this after the update:
ID - Name - Phone number
But with my code it looks like this after the update:
ID - Name - ID - Name - Phone number
as it just replaces the last column with a new table within the last column with the updated data.
I'm getting the correct data as output, but in the wrong place in the row.
Please help! :)
Here is the Javascript code:
$(function () {
$("#edit-event-dialog").dialog({
resizable: false,
height: 300,
modal: true,
autoOpen: false,
open: function (event, ui) {
var objectid = $(this).data('id');
$('#edit-event-dialog').load("/Events/CreateEditPartial", { id: objectid });
},
buttons: {
"Save": function () {
var ai = {
EventID: $(this).data('id'),
Name: $("#Name").val(),
Phone: $("#Phone").val()
};
var json = $.toJSON(ai);
var row = $(this).data('row');
$.ajax({
url: $(this).data('url'),
type: 'POST',
dataType: 'json',
data: json,
contentType: 'application/json; charset=utf-8',
success: function (data) {
var grid = $(".pretty-table");
row.replaceWith('<tr><td>' + data.ev.EventID + '</td><td>' +
data.ev.Name + '</td><td>' + data.ev.Phone + '</td></tr>');
},
error: function (data) {
var data = data;
alert("Error");
}
});
$(this).dialog("close");
},
Cancel: function () {
$(this).dialog("close");
}
}
});
$("#event-edit-btn").live("click", function () {
var url = $(this).attr('controller');
var row = $(this);
var id = $(this).attr('objectid');
$("#edit-event-dialog")
.data('id', id)
.data('url', url)
.data('row', row)
.dialog('open');
event.stopPropagation();
return true;
});
You have set row to $(this) which is your case represents $("#event-edit-btn") ( btw i suggest using classes as identifiers, but it's not a problem ). Later on you replace your actual button with the new <tr> set but what you actually need to do is traverse to the tr parent of that button and replace it.
Change your live handler to:
$("#event-edit-btn").live("click", function () {
var url = $(this).attr('controller');
var row = $(this).closest('tr'); //or use some #id or .class assigned to that element
var id = $(this).attr('objectid');
$("#edit-event-dialog")
.data('id', id)
.data('url', url)
.data('row', row )
.dialog('open');
event.stopPropagation();
return true;
});