how to append json array in datatable using render function - javascript

I want to append json array into one popover attribute called data-content.
I am using jQuery DataTables plugin to perform UI functionalities. Using data variable table is populated with the data.
How could I insert titleDescription array from data variable into the attribute name called as data-content inside a tag in js , check my fiddle and go to datatable function there inside columnDefs there is render function. In that function I have return and append a tag, there only I have to append titleDescription array.
Check this JSFiddle for demonstration.

You can use the row attribute, and have the data in a non visible column.
Check the example
https://datatables.net/examples/advanced_init/column_render.html
$(document).ready(function() {
$('#example').DataTable( {
"columnDefs": [
{
// The `data` parameter refers to the data for the cell (defined by the
// `data` option, which defaults to the column being worked with, in
// this case `data: 0`.
"render": function ( data, type, row ) {
return data +' ('+ row[3]+')';
},
"targets": 0
},
{ "visible": false, "targets": [ 3 ] }
]
} );
} );
That would do the trick.

You just need to add another column at the last of each row then you can access it from row like this
render : function(data, type, row) {
return '<span class="favlist-icon"></span><span class="immediate-attention-icon"> </span> <span class="docx-name-list-link"> <a class="apopoverdata" href="#" data-content="'+row[4]+'" rel="popover" >'+data+'</a></span>';
}
Here is working fiddle
https://jsfiddle.net/2cn4b8bz/4/

I'm not sure what library you were using for your pop over so I used tooltipster seeing as you had jQuery already for the DataTable. Your data didn't have everything you needed either so I've altered it a wee bit:
$(function() {
$('#documentListing-data').DataTable({
data: json.documentAll.document,
pageLength: 10,
columns:[
{
"data": "documentTitle",
"title": "Name",
"render": (data, type, row) => '' + data + '',
},
{
"data": "category",
"title":"Category",
"render": (data, type, row) => data.map((k, v) => k.trim()).join(", "),
},
{
"data": "publishedDate",
"title":"Published Date"
},
{
"data": "lastUpdatedDate",
"title": "Last Updated Date"
},
],
"drawCallback": function(settings) {
$('.tooltip').tooltipster();
}
});
});
Working JSFiddle. Hope that helps!

Related

how to destroy table and reinitialize same table with new updated data using Datatables Jquery plugin

I am using Datatables plugin and dynmically populating the table with the data returned from server. on different table draws the returned data has variable no of columns. On each table intilization the code is checking if there has been previous initializations and removes it before creating a new table with dynamic data, using this code:
if ( $.fn.dataTable.isDataTable( '#contracts_forecast' ) ) {
$('#contracts_forecast').DataTable().clear();
$('#contracts_forecast').DataTable().destroy();
$('#contracts_forecast tbody').empty();
$('#contracts_forecast thead').empty();
}
On the serverside I am manually editing the data and updating the database. When the database is updated with new data , I want to refresh the table so the change is reflected in the table. In order to do that I am using an POST SUBMIT event, which is triggered after the data is submitted to server and then call the function getDT(filter_product_code, filter_product_name) to update the table with new data
PROBLEM:
When the post submit event is triggered , it recalls the function getDT(filter_product_code, filter_product_name); and change is reflected. BUT THE NEW TABLE with UPDATED IS ADDED TO CURRENT TABLE WITHOUT THE OLD TABLE BEING DESTROYED Which leaves me with two same tables on screen
p.s I am assuming every time getDT() function is called it should check for if table is initialized and destroy it before creating a new one using the same
$(document).ready(function() {
$('#filter').click(function(){
var filter_product_code = $('#filter_product_code').val();
var filter_product_name = $('#filter_product_name').val();
if(filter_product_code == '' || filter_product_name == '')
{
alert('Select Both filter option');
}
var columns = [];
getDT(filter_product_code, filter_product_name);
function getDT(filter_product_code, filter_product_name) {
$.ajax({
serverSide: true,
type:'POST',
url: "/XXX/_fetch.php",
data: {filter_product_code: JSON.stringify(filter_product_code),
filter_product_name: JSON.stringify(filter_product_name)},
success: function (data) {
data = JSON.parse(data);
columnNames = Object.keys(data.data[0]);
for (var i in columnNames) {
columns.push({data: columnNames[i],
title: capitalizeFirstLetter(columnNames[i])});
}
if ( $.fn.dataTable.isDataTable( '#contracts_forecast' ) ) {
$('#contracts_forecast').DataTable().clear();
$('#contracts_forecast').DataTable().destroy();
$('#contracts_forecast tbody').empty();
$('#contracts_forecast thead').empty();
}
table = $('#contracts_forecast').DataTable({
data: data.data,
columns: columns,
dom: "Bfrtip",
select: true,
buttons: [
{ extend: "create", editor: editor },
{ extend: "edit", editor: editor },
{ extend: "remove", editor: editor }
],
"columnDefs": [
{
"targets": [0],
"visible": false,
"searchable": false
},
{ className: "tablecolumns", targets: "_all" },
]
} );
$('#contracts_forecast').on( 'click', 'tbody td:not(:first-child)', function (e) {
editor.inline( this );
} );
}
});
editor.on( 'postSubmit', function ( e, json, data, action, xhr ) {
getDT(filter_product_code, filter_product_name);
});
}
});
} );
I was doing a mistake by declaring the column variable outside function. Each time the function was called it was adding to already existing columns. So just needed to define column variable inside function.
getDT(filter_product_code, filter_product_name);
function getDT(filter_product_code, filter_product_name) {
var columns = [];
$.ajax({
serverSide: true,
// paging: true,
// retrieve:true,
type:'POST',

Jquery how to use this in a event datatable generated td row

I am trying to add a function call "onblur" where i can type a new value in the TD cell. What I need is the new value to be passes by the function to a other Jquery script. My problem is that the datatable wont see the This value as it seems the code is not written correctly. What am I doing wrong? I cant find anything that helped me so far..
This is the php version that works, this is what I am trying to implent in the Datatable table.
<td
contenteditable="true"
data-old_value="name"
onBlur="saveInlineEdit(this,'name','23')"
onClick="highlightEdit(this);"
>
name
</td>
Concrete. How do i use the new typed value as "this" in the folowing line, or how do i implement the code that works in the HTML table in the jQuery DataTable?
var options = {
data: 'my_data',
render: function ( data, type, row, meta ) {
return '<div onBlur="saveInlineEdit('this.innerHTML,'name', + row.data_id + ') " onClick="highlightEdit(this);"><font color='+row.cat_color+'>'+data+'</font></div>';
}
}
The part in the DataTables script to add the attributes:
createdRow: function (row, data, dataIndex) {
$('td:eq(4)',row).attr('contenteditable',true);
$('td:eq(4)',row).attr('data-old_value', data.bullets);
}
I want to use the following script to post the value of the saveInlineEdit function
function highlightEdit(editableObj) {
$(editableObj).css("background","");
}
function saveInlineEdit(editableObj,column,id) {
// no change change made then return false
if($(editableObj).attr('data-old_value') === editableObj.innerHTML) {
return false;
}
// send ajax to update value
$(editableObj).css("background","#FFF url(loader.gif) no-repeat right");
$.ajax({
url: "update_inlinedata.php",
cache: false,
data:'column='+column+'&value='+editableObj.innerHTML+'&id='+id,
success: function(response) {
console.log(response);
// set updated value as old value
$(editableObj).attr('data-old_value',editableObj.innerHTML);
$(editableObj).css("background","");
}
});
}
There are a couple of different pieces to your question - the following covers the capturing of changed cell data, and making sure the DataTable reflects the edits made in the DOM by the user.
(I did not tackle the highlighting, but I think you can extend the below approach to cover that as well, since it's handling the same data.)
I think using a createdCell option in a columnDef may be a bit easier than using a createdRow, because you will get direct access to the column's value:
columnDefs: [ {
targets: 4,
createdCell: function (td, cellData, rowData, rowIdx, colIdx) {
// 'td' is the DOM node, not the DataTable cell
td.setAttribute('contenteditable', true);
td.setAttribute('spellcheck', false);
td.setAttribute('data-old_value', cellData);
td.addEventListener("focus", function(e) {
original = e.target.textContent;
})
td.addEventListener("blur", function(e) {
if (original !== e.target.textContent) {
console.log( 'row ID: ', rowData.id );
console.log( 'new DOM value: ', td.innerHTML);
// 'cell' is the DataTable cell, not the DOM node:
let cell = $('#example').DataTable().cell(rowIdx, colIdx);
console.log( 'before cell update: ', cell.data() );
cell.data(td.innerHTML);
console.log( 'after cell update: ', cell.data() );
}
})
}
} ]
Acknowledgement: The above approach is modified from the one shown in this answer.
Here is a self-contained demo:
var my_data = [
{
"id": "123",
"name": "Tiger Nixon",
"position": "System Architect",
"salary": "$320,800",
"bullets": "lorem ipsum",
"office": "Edinburgh",
"extn": "5421"
},
{
"id": "456",
"name": "Donna Snider",
"position": "Customer Support",
"salary": "$112,000",
"bullets": "dolor sit amet",
"office": "New York",
"extn": "4226"
}
];
$(document).ready(function() {
var table = $('#example').DataTable( {
data: my_data,
columns: [
{ title: "ID", data: "id" },
{ title: "Name", data: "name" },
{ title: "Office", data: "office" },
{ title: "Position", data: "position" },
{ title: "Bullets", data: "bullets" },
{ title: "Extn.", data: "extn" },
{ title: "Salary", data: "salary" }
],
columnDefs: [ {
targets: 4,
createdCell: function (td, cellData, rowData, rowIdx, colIdx) {
// 'td' is the DOM node, not the DataTable cell
td.setAttribute('contenteditable', true);
td.setAttribute('spellcheck', false);
td.setAttribute('data-old_value', cellData);
td.addEventListener("focus", function(e) {
original = e.target.textContent;
})
td.addEventListener("blur", function(e) {
if (original !== e.target.textContent) {
console.log( 'row ID: ', rowData.id );
console.log( 'new DOM value: ', td.innerHTML);
// 'cell' is the DataTable cell, not the DOM node:
let cell = $('#example').DataTable().cell(rowIdx, colIdx);
console.log( 'before cell update: ', cell.data() );
cell.data(td.innerHTML);
console.log( 'after cell update: ', cell.data() );
}
})
}
} ]
} );
} );
<head>
<meta charset="UTF-8">
<title>Demo</title>
<script src="https://code.jquery.com/jquery-3.5.1.js"></script>
<script src="https://cdn.datatables.net/1.10.22/js/jquery.dataTables.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.22/css/jquery.dataTables.css">
<link rel="stylesheet" type="text/css" href="https://datatables.net/media/css/site-examples.css">
</head>
<body>
<div style="margin: 20px;">
<table id="example" class="display dataTable cell-border" style="width:100%">
</table>
</div>
</body>
Update
I don't have a server which can handle your ajax call, so I cannot test a "success" response. Having said that, here are my notes:
For the saveInlineEdit function, you will no longer need this:
if($(editableObj).attr('data-old_value') === editableObj.innerHTML) {
return false;
}
This is because you have already performed that check in the event listener:
if (original !== e.target.textContent) { ... }
Also, you have already determined what the new value of the cell is - so you might as well just pass that directly to the function:
saveInlineEdit(td, 'bullets', rowData.id, cell.data());
The above line needs to be placed in the event listener shown above:
td.addEventListener("blur", function(e) {
if (original !== e.target.textContent) {
console.log( 'row ', rowIdx, ' col ', colIdx );
console.log( 'row ID: ', rowData.id );
console.log( 'new DOM value: ', td.innerHTML);
// 'cell' is the DataTable cell, not the DOM node:
let cell = $('#example').DataTable().cell(rowIdx, colIdx);
console.log( 'before cell update: ', cell.data() );
cell.data(td.innerHTML);
console.log( 'after cell update: ', cell.data() );
let columnName = $('#example').DataTable().settings();
console.log( 'column name: ', columnName );
saveInlineEdit(td, 'bullets', rowData.id, cell.data()); // NEW LINE HERE
}
})
Your saveInlineEdit function therefore changes, to reflect the above points:
I removed the unnecessary if condition.
I added an extra parameter newValue - since we don;t need to keep retrieving it from the cell (we've already done that).
function saveInlineEdit(editableObj, column, id, newValue) {
console.log( 'in ajax call' );
console.log(editableObj);
console.log(column);
console.log(id);
console.log(newValue);
// send ajax to update value
$(editableObj).css("background","#FFF url(loader.gif) no-repeat right");
$.ajax({
url: "update_inlinedata.php",
cache: false,
data:'column=' + column + '&value=' + newValue + '&id=' + id,
success: function(response) {
console.log(response);
// set updated value as old value
$(editableObj).attr('data-old_value', newValue);
$(editableObj).css("background","");
}
});
}
I put logging statements into the function, so you can see what the parameters are.
So, for example, the query parameter data submitted by the ajax call will be:
column=bullet&value=lorem%20ipsum%20editedbyme&id=123
And just to say again, I cannot test this ajax call - so bear that in mind, i case I made a stupid mistake there, somewhere.
That leaves 2 additional point which are outside the scope of the question, but which need to be considered:
The question assumes only column index 4 is editable. If you want every cell in a row to be editable you need to enhance this to use the relevant column names. One good way to do this is to use the DataTables name option:
{ title: "Bullets", data: "bullets", name: "bullets" },
This value can be retrieved and used by the blur event handler, before you call your saveInlineEdit function:
let columnName = $('#example').DataTable().settings()[0].aoColumns[colIdx].sName;
Then your call becomes:
saveInlineEdit(td, columnName, rowData.id, cell.data());
The current code updates the data in the DataTable here:
cell.data(td.innerHTML);
This happens before the return from the ajax call. If that call fails then you have updated data in your data table, but not in the back end database. So you may want to move that logic around to ensure the DataTable data is updated only in the event of a successful ajax call.

How to update model data when using jQuery Data table with ASP.NET MVC

I have large amount of data returning from JSON and to sort,filter and page, I am using jQuery dataTable.
This is working perfect with sorting, searching and pagination.
But I have an issue when I am trying to bind model with View controls.
For example, I have following JSON returned,
{
"data":
[
{"IsSelected":true,"Name":"SMyDataPoint__01"},
{"IsSelected":true,"Name":"SMyDataPoint__04"},
{"IsSelected":true,"Name":"SMyDataPoint__07"},
{"IsSelected":true,"Name":"SMyDataPoint__08"},
{"IsSelected":true,"Name":"SMyDataPoint__09"},
{"IsSelected":true,"Name":"SMyDataPoint__10"},
{"IsSelected":true,"Name":"SMyDataPoint__11"}
]
}
And now I am using jQuery to populate the json data in my browser,
$('#myTableName').DataTable(
{
"ajax": {
"url": "/API/Loaddata",
"type": "GET",
"datatype": "json"
},
"columns": [
{
"data": "IsSelected",
"render": function (data, type, row) {
if (type === 'display') {
return '<input type="checkbox" class="editor-active">';
}
return data;
},
"className": "dt-body-center"
// "autoWidth": true
},
{ "data": "Name", "autoWidth": true }
],
"rowCallback": function (row, data) {
// Set the checked state of the checkbox in the table
$('input.editor-active', row).prop('checked', data.active == 1);
}
}
);
Though I am getting ISelected as true from JSON, in UI , they are not ticked.
The json objects you have shown do not have a property named active (and therefore data.active would return undefined). Use the IsSelected to set the checkedproperty.
$('#myTableName').DataTable({
....
"rowCallback": function (row, data) {
// Set the checked state of the checkbox in the table
$('input.editor-active', row).prop('checked', data.IsSelected);
}
})

Datatables update single column every 5 seconds

I'm using datatables to show several information and button.
This is the javascript used to initialize the datatables
if ( ! $.fn.DataTable.isDataTable( '#datatableTable' ) ) {
datatableTable = $('#datatableTable').DataTable({
responsive: true,
columnDefs: [
{ "width": "25%", "targets": 4},
{
targets: [4,5,6],
//set priority to column, so when resize the browser window this botton stay on the screen because have max priority
visible: (document.getElementById('role').value == '[ROLE_ADMIN]' || document.getElementById('role').value == '[ROLE_FLEET_ENG]'
|| document.getElementById('role').value == '[ROLE_SUPPLIER]'),
responsivePriority: 1,
orderable: false,
searchable: false,
},
...
],
//fix problem with responsive table
"autoWidth": false,
"ajax":{
"url": "datatable/" + $("#selectedCar").val(),
"dataSrc": ...
return json.result.data;
},
"error": function (xhr, error, thrown) {
window.location.href = "/DART/500";
}
},
"columns": [
....
{data:null, render: function ( data, type, row ) {
var datId="deleteDat"+row.idAcquisition;
if (row.datUploaded){
return '<button type="button" class="btn btn-danger" name="deleteDat" target="'+row.idAcquisition+'" id="'+datId+'" data-toggle="modal"'
+'data-target="#deleteDatModal">Delete</button>'
}else
return '<button type="button" class="btn btn-danger" name="deleteDat" target="'+row.idAcquisition+'" id="'+datId+'" data-toggle="modal"'
+'data-target="#deleteDatModal" disabled>Delete</button>'
},
],
"fnDrawCallback": function(data, type, row, meta ) {
//Initialize checkbox for enable/disable user
$("[name='my-checkbox']").bootstrapSwitch({size: "small", onColor:"success", offColor:"danger"});
},
});
}
else {
datatableTable.ajax.url("datatable/" + $("#selectedCar").val()).load();
}
Column 5 (starting from 0) has buttons, each button may be disabled or enabled depends on the datUploaded boolean value.
This variable change if user load file ,but this value has setted after async task, so I don't know in my javascript when this task end.
I thought to update every 5 seconds only this column, but how can I do it?
I find datatableTable.column(5).cells().invalidate().render() but I receive an error (unknow parameter "isShow" for row 0) and update doesn't work.
Can you help me? Thanks
As I said in a comment, you can pass .load() a callback function that will be called automatically when the ajax request is complete. In this callback you can update your table as you prefer. After you update the table, remember to call datatableTable.draw(); to apply the changes.
I don't think invalidate() and render() are necessary.
So your else branch would be something like
datatableTable.ajax.url("datatable/" + $("#selectedCar").val()).load(function() {
/*
...do something to the table...
*/
datatableTable.draw();
});

Javascript keyword "this" becomes undefined

I am using DataTables to create a list of selectable phone numbers, my function is as follow:
function search(areacode) {
areacode = typeof areacode !== 'undefined' ? areacode : 239;
$("#did_search").fadeIn();
var table = $('#example').DataTable( {
"bDestroy": true,
"ajax": "/Portal/manage/search_bulkvs/" + areacode,
"columns": [
{ "data": "did" },
{ "data": "city" },
{ "data": "state" },
{ "data": "action" },
],
"columnDefs": [
{ "visible": false, "targets": 3 }
]
} );
$('#example tbody').on( 'click', 'tr', function () {
var row_object = table.row( this ).data();
$("label[for = did_label]").text(row_object.action);
$('input[name="did"]').val(row_object.action);
} );
}
The end of the function $('#example tbody') -- allows me to select the data from the table that I need and set the value of my label/input for form processing. However, after I run this function a second time I am unable to select this data anymore.
My debugging has led to this error: Uncaught TypeError: Cannot read property 'action' of undefined
I thought that row_object would be defined every time that the function is run, but it looks like it isnt.
Does anyone have any suggestions as to how I can retrieve this data from the table after the function has been run more than once?
If the ajax call replaces the tbody element of the table, you will need to attach your delegated event handler to a non-changing ancestor (e.g. $('#example').on or even $('#example').parent().on(.
You also want to avoid repeatedly setting up handlers if search is called multiple times (or call off before on).
e.g.
$('#example tbody').off('click').on( 'click', 'tr', function () {
var row_object = table.row( this ).data();
$("label[for = did_label]").text(row_object.action);
$('input[name="did"]').val(row_object.action);
} );
Since you're using ajax, you need to bind your click object on each draw using DataTables.fnDrawCallback, like this:
function search(areacode) {
areacode = typeof areacode !== 'undefined' ? areacode : 239;
$("#did_search").fadeIn();
var table = $('#example').DataTable( {
"bDestroy": true,
"ajax": "/Portal/manage/search_bulkvs/" + areacode,
"columns": [
{ "data": "did" },
{ "data": "city" },
{ "data": "state" },
{ "data": "action" },
],
"columnDefs": [
{ "visible": false, "targets": 3 }
],
"fnDrawCallback": function(){
$("tbody tr td",$(this)).click(function(e){
.... Your click code here ....
});
}
} );
}
It is not that this becomes undefined. This error message
Uncaught TypeError: Cannot read property 'action' of undefined
usually means that you are calling a function from an undefined object (here is row_object), or the function you are calling (action) is not on the object.
Yes, the definition of variable row_object is fine. But I think you can console.log it to see whether it is assigned to some value correctly every time.

Categories

Resources