Pass a JavaScript variable to a shiny app contained in a iframe - javascript

I have a website with a DataTable. Following this I create a js event on clicking on a row. The event stores an id corresponding to the clicked row in a variable and following this I posted a message to the shiny-iframe.
$(document).ready(function() {
var table = $('#example').DataTable( {
"columnDefs": [
{
"targets": [ 0 ],
"visible": false,
"searchable": false
}
]
});
$('#example tbody').on('click', 'tr', function () {
var data = table.row( this ).data();
var table_row_id = data[0];
var frame = document.getElementById('shiny-iframe');
frame.contentWindow.postMessage(table_row_id, '*');
} );
} );
Still I am not sure how to proceed from here. The end result is to have shiny reloading the app in the iframe with as argument the variable stored in table_row_id.

Related

Datatables has only 10 rows accessible outside the DataTables creation function

I am using Django and in one of my tamplates I use datatables (1.10.19) to display my table data.
This is how my code looks like:
$(document).ready( function () {
table = $('#mytable').DataTable({
"pagingType": "full_numbers",
data: dataSet,
columns: [
{ title: "Naslov zahtjeva" },
{ title: "Datum slanja" },
{ title: "Status" },
{ title: "Rok Izvršenja." },
{ title: "Id zahtjeva" },
],
"fnCreatedRow": function(row, data, index){
$(row).addClass("clickable-row");
$(row).attr('data-href', data[4]);
$(row).addClass("table_row_point");
},
});
Problem occurs at the line -> $(row).attr('data-href', data[4]);
I have a different function that is suposed to use that 'ID' from 'data-href' attribute in order to go to another page like this
jQuery(document).ready(function($) {
$(".clickable-row").click(function() {
window.location = $(this).data("href");
});
});
Thing is it works fine for first 10 rows, and when I try 'console.log( this );' I get
Only for the first 10 rows, and it acts like other 3000 don't even exist, I believe it is connected to the default value of 10 rows that appear, but it makes no sense to me for data to be displayed normally, but the 'tr' element not to exist for all, but 10 of them.
Note: When I place this function into DataTable creation code (1st snippet) it shows all the tr elements
$('#mytable tbody').on( 'click', 'tr', function () {
console.log( this );
} );
If someone has any idea it would be much appreciated
fnCreatedRow function is executed everytime datatable creates the <tr> element in the dom. Since you have enabled pagination, function is run only on the <tr> elements created at the time. If you move on to next page, you'll see that console prints next set of rows.
By the way I think createdRow is preferred over old fnCreatedRow naming convention. https://datatables.net/reference/option/createdRow

jQuery DataTables duplicates are initially loading

So, adding on to my question from yesterday: jQuery AJAX call function on timeout
Using the first answer from the post from yesterday, the table does indeed reload without refreshing the whole page. It does so after 30 seconds.
But my problem lies before the first refresh...
The page loads, and the records are duplicated. But after the first refresh and every refresh after (unless I manually refresh using F5), everything is fine. No duplicates.
I'm trying to figure out why there are duplicates and how to remove the duplicates upon the page's initial ready event.
Here is the code, starting with the ready event:
$(document).ready(function()
{
$.ajax({
url:'api/qnams_all.php',
type:"GET",
dataType:"json"
}).done(function(response) {
console.log(response.data);
renderDataTable(response.data)
}).fail(function() {
alert( "error" );
}).always(function() {
alert( "complete" );
});
});
Here is the function to load the DataTable:
function renderDataTable(data)
{
var $dataTable = $('#example1').DataTable({
"ajax": 'api/qnams_all.php', // just added this
"data": data,
"bDestroy": true,
"stateSave": true
});
// then I add the reload function
setInterval( function () {
$dataTable.ajax.reload();
}, 30000 );
});
As stated above, the setInterval function works like how it should. It's just the initial page load is duplicating all of the records.
Does anyone see why and how to fix it?
I think you've got some duplication going on. You don't need to load the ajax flie and then load it again when you set up the DataTable.
Try replacing all of your code with this:
$(document).ready(function() {
// load and render the data
var $dataTable = $('#example1').DataTable({
"ajax": 'api/qnams_all.php', // just added this
"data": data,
"bDestroy": true,
"stateSave": true,
// the init function is called when the data table has finished loading/drawing
"init": function() {
// now that the initial data has loaded we can start the timer to do the refresh
setInterval(function() {
$dataTable.ajax.reload();
}, 30000);
}
});
});
Calling clear prevents duplicate rows while loading data into table:
$("#checkResourcesButton").click(function() {
$.post("./get/resources", {
featureName: $('#myvar').val()
}).done(function (data) {
var table = $('#table-output').DataTable();
table.clear();
var json = JSON.parse(data);
for (var row in json) {
var nameVal = json[row].Name;
var emailVal = json[row].emailId;
var roleVal = json[row].role;
var startDateVal = json[row].startDate;
var endDateVal = json[row].endDate;
var toAdd =
{
name: String(nameVal),
emailId: String(emailVal),
role: String(roleVal),
startDate: String(startDateVal),
endDate: String(endDateVal)
};
table.row.add(toAdd);
}
table.draw();
});
});

Delete rows in Datatable before destroying

I am initializing a Datatable each time the function lds is called. The function lds pulls data for table and appends the relevant HTML by
$('#tablebody').html(data);
After that I am initializing a datatable like so,
$('#rTable').Datatable({
paging:false,
destroy: true
});
This solves the problem of the error "Datatables cannot be initialized" if I call the lds function again. But the old rows are retained that were appended previously. I have tried the following approaches:
Assigned var table to the initialization of Datatable and put table.empty() at the beginning of lds. But as expected, the table variable is undefined.
Tried to delete row(0) while length > 0 but that messes the table and deletes the as well.
Tried ('#rTable').empty() but due to this Datatables throws an error d[i] not defined.
What is an approach I can take to empty the rows each time the function lds is called.
Destroy an existing table on a button click
var table = $('#myTable').DataTable();
$('#tableDestroy').on( 'click', function () {
table.destroy();
} );
Reload a full table description from the server, including columns:
var table = $('#myTable').DataTable();
$('#submit').on( 'click', function () {
$.getJSON( 'newTable', null, function ( json ) {
table.destroy();
$('#myTable').empty(); // empty in case the columns change
table = $('#myTable').DataTable( {
columns: json.columns,
data: json.rows
} );
} );
} );

Custom rendering when using server side processing

I was wondering if the rendering of the table after receiving an ajax response can be modified. This seems related to the render function described here: https://www.datatables.net/manual/orthogonal-data.
My server returns Data like
{
"name":
{
id: "123456",
value: "Tiger Nixon"
}
}
I want to add to each name cell the id of the name as data-attribute or as id for the td and want to add a .on( "click", handler ) for each cell.
Is this possible?
Thanks in advance
You can use DT_RowData or DT_RowAttr (requires DataTables 1.10.5 or higher) parameters in your returned data to assign attributes to <tr> element which you can later retrieve in click handler, see Server-side processing chapter in the manual.
Alternatively you can use render method but it may not be as effective. I assumed below that index of your name column is 0 and that you want to set data-id attribute.
var table = $('#example').DataTable({
"columnDefs": [{
"data": "name.value",
"targets": 0,
"render": function ( data, type, full, meta ) {
if(type === 'display'){
$('#example').DataTable().cell(meta.row, meta.col).nodes().to$().attr('data-id', full['name']['id']);
}
return data;
}
}]
});
You can add click event handler using the code below:
$(document).ready(function(){
var table = $('#example').DataTable({
// Define DataTables initialization options here
});
$('#example tbody').on('click', 'td', function(){
// Use table to access various API function
//
// For example:
// var data_cell = table.cell(this).data();
});
});
This is possible by using the columns.createdCell function.
The answer of Gyrocode is correct for an old DataTables version.

Running a function on an image created in the DOM

I'm using dataTables to retrieve, display and organise data from a PHP script (which in turn pulls the information from a MySQL database).
Using the following code, dataTables retrieves the information and puts it into a.. well, table.
$('#content div').html( '<table id="example"></table>' );
var oTable = $('#example').dataTable( {
"bJQueryUI": true,
"bProcessing": true,
"bServerSide": true,
"sPaginationType": "full_numbers",
"sAjaxSource": "dataTables.php",
"aoColumns": [
/* UID */ { "bSearchable": false,
"bVisible": false },
/* Datetime */ { "asSorting": [ "desc" ] },
/* Staff Name */ null,
/* Room */ null,
/* Reason */ null,
/* Urgency */ null,
/* Processed? */ null ],
"fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
var sDirectionClass;
if ( aData[6] === null ) {
sDirectionClass = "new";
if ( row % 2 !== 0 )
sDirectionClass = "new_odd";
} else {
sDirectionClass = "std";
}
row++;
$(nRow).addClass( sDirectionClass );
return nRow;
}
} );
Most of this, I hope, is quite straightforward - this function takes the sAjaxSource property and looks at my dataTables.php file, which simply reads the MySQL DB and returns some information in a JSON-encoded format.
This all works fine, but I'm trying to turn one of my table's columns into a clickable link.
The brief PHP for this is;
if ( $aColumns[$i] == "Processed" )
{
$link = '<img src="tick.png" id="' . $aRow[ $aColumns[0] ] . '" />';
$row[] = ( empty( $aRow[ $aColumns[$i] ] ) ) ? $link : $aRow[ $aColumns[$i] ];
}
The pseudo for that is basically if Processed field is NULL display an image with the UID of that row; otherwise display the value of Processed field.
What I'd like to do now is make that image JS-clickable to run an AJAX function. I thought that the following code (in situ immediately after the above JS):
oTable.find('img').click(function(){
var process = $(this).attr("id");
$.ajax({
url: "check_alerts.php",
data: { process: id }
}).done(function() {
oTable.fnDraw(false);
});
});
Unfortunately, it appears to do nothing. I'd imagine this is because the img I'm creating is created in the DOM and as such when the above function runs, it won't find any img tags.
How can I amend the code so that those images will run my AJAX function?
Thanks in advance,
You need to use the jquery.on() which is specifically meant to bind events on dynamic content.
Try this:
//replace table with the table pointer (class,id)
$('table').on('img','click',function(){
//do your thing
});
To make sure that your new DOM elements also listen to the click event you should use "on".
oTable.on("click", "img", function() {
var process = $(this).attr("id");
$.ajax({
url: "check_alerts.php",
data: { process: id }
}).done(function() {
oTable.fnDraw(false);
});
});
See the documentation
Did you try using firebug to see if the image tag is generated.
Than try running your image click binding function in firebug console tab. If that works than probably you are trying to bind the click event too soon in your original page execution cycle.

Categories

Resources