Json object converted into a Datatable - javascript

Using a server call the user of my web application is creating a json object d. This object contains numerous keys (think of "Mean", "Stdev", etc.). The user is changing the underlying timeseries on a webpage.
<script type="text/javascript">
function myFunction(d) {
$('#myid').html(d["Mean"])
}
</script>
An jquery $.POST is executed and if successful returns the json object and calls the method above.
The above scheme works already. This updates
<div class="container-fluid">
<div class="row-fluid">
<div id="myid">some value</div>
</div>
</div>
However, I would really like to update a complete datatable (datatable as in http://datatables.net/examples/advanced_init/).
At runtime I don't know what key are in d. Is datatables.js the right tool for dynamic data in a table?

Yep, that is what dataTables.js was made for.
Although it is unclear what you mean exactly with datatable, table and dataTable.
dataTable.js is responsible for the display (rendering) of a table like structure on your page with lots of functionality (like sorting, searching, filtering, pagination, editing etc.) that would otherwise be very difficult to achieve. It is not a tool that helps you to maintain the field in a table (or datatable) of your DB. (But it can be)
dataTable.js uses server sided code with some cleverly helper functions to help you to use a mySql database via PHP. But it does not rely on this examples. You can use any serversided code and any database as long as it understands the query that is sent from dataTables.js and resturns the json-data that dataTables.js expects.
For complex (DB)-table manipulation you need to write your own server sided code.
Regarding your question I guess you should have a look at the serversided examples that come with dataTables.js.
For getting individual values of cell or row values on the actual page the user sees you should look at the column rendering examples.
Don't regard this as an Answer, it is just to lengthy for a comment. Be prepared that using dataTables.js is way different from the working code of your question.

Here's a fragment of the code. It works actually now. However, I find the concept (removing content and adding row-wise) super dodgy:
<div class="col-md-3">
<table id="example" class="display" cellspacing="0" width="100%">
<thead>
<tr>
<th></th>
<th>Value</th>
</tr>
</thead>
</table>
</div>
<script type=text/javascript>
$SCRIPT_ROOT = {{ request.script_root|tojson|safe }};
$TABLE = $('#example').DataTable({
"info": false,
"bPaginate": false,
"paging": false,
"bScrollCollapse": false,
"search": false,
"sort": false,
"filter": false}
);
</script>
<script type="text/javascript">
function myFunction(d)
{
console.log("Refill table");
console.log(d);
$TABLE.clear();
for (var key in d) {
$TABLE.row.add([key, d[key]]);
}
$TABLE.draw();
}
</script>
Please note that I have not included the code for the computation of d (done on the server with a $.ajax POST call.

Related

jQuery DataTables Cannot read property 'mData' of undefined but table is valid markup

I've been attempting to track this one down for a few weeks but without any joy. So far as I can tell my markup is valid, which is not the case for most posts about this on SO.
<div class="container">
<br />
<div style="width:90%; margin:0 auto;">
<table id="example" class="table table-striped table-bordered dt-responsive nowrap" width="100%" cellspacing="0">
<thead>
<tr>
<th>StudentId</th>
<th>Group</th>
<th>Student</th>
<th>4</th>
<th>1</th>
<th>7</th>
</tr>
</thead>
<tbody>
<tr>
<td>4</td>
<td>testgroup1</td>
<td>Test Name2</td>
<td><input type="text" id="row-4-1a" name="row-4-1a" value="0"></td>
<td><input type="text" id="row-4-1b" name="row-4-1b" value="0"></td>
<td><input type="text" id="row-4-2" name="row-4-2" value="0"></td>
</tr>
</tbody>
</table>
</div>
<button id="mytestbutton" type="submit">Submit form</button>
</div>
I have a C# backend that generates a lot of my content using Razor, but I've replicated the same behaviour using the source output from my browser. The JavaScript I'm using is as below, where I set some data into js objects from the backend ready to use, then initialise the DataTable on document ready.
var modelJson = JSON.parse('{"AssessmentId":1,"Name":"test1","Groups":[{"GroupId":1,"Name":"testgroup1","Students":[{"StudentId":4,"Name":"Test Name2","IsActive":true}],"StudentIds":[4],"IsActive":true}],"GroupIds":[1],"Questions":[{"QuestionId":0,"QuestionNumber":"1a","TopicDescription":"Topic goes here","AvailableMarks":4,"AssessmentId":0},{"QuestionId":0,"QuestionNumber":"1b","TopicDescription":"Topic goes here","AvailableMarks":1,"AssessmentId":0},{"QuestionId":0,"QuestionNumber":"2","TopicDescription":"Topic goes here","AvailableMarks":7,"AssessmentId":0}],"GradeBoundaries":{"A":80,"B":70,"C":0,"A*":90},"MarksAttained":[{"StudentId":4,"MarksAttained":{"1a":0,"1b":0,"2":0}}],"StudentIdsInAssessment":[4]}');
var columns = JSON.parse('[{"QuestionId":0,"QuestionNumber":"1a","TopicDescription":"Topic goes here","AvailableMarks":4,"AssessmentId":0},{"QuestionId":0,"QuestionNumber":"1b","TopicDescription":"Topic goes here","AvailableMarks":1,"AssessmentId":0},{"QuestionId":0,"QuestionNumber":"2","TopicDescription":"Topic goes here","AvailableMarks":7,"AssessmentId":0}]');
function InitialiseDataTable(e, t) {
var a = [];
e.forEach(function(e) {
a.push({
data: e.QuestionNumber,
name: e.QuestionNumber,
autoWidth: !0
})
}), $("#example").DataTable({
processing: !0,
serverSide: !1,
filter: !1,
orderMulti: !1,
data: {
test: 100
},
columnDefs: [{
targets: [0],
visible: !1,
searchable: !1
}],
columns: a
})
}
$("#mytestbutton").click(function() {
var e = $("#example").$("input, select").serialize();
return alert("The following data would have been submitted to the server: \n\n" + e.substr(0, 120) + "..."), !1
});
$(document).ready(() => {
InitialiseDataTable(columns, 1);
});
This code is all running live on jsfiddle at https://jsfiddle.net/w4q57hdu/ if you want to see the error in action.
I have been unable to determine why it's erroring where it is, I can only assume that there's something broken in the way I'm initialising the DataTable, but I can't see the wood for the trees. I loop through my columns object from the backend and use the QuestionNumber property from each in an array for initialising the DataTable.
It may be helpful to add that I followed the example at https://datatables.net/examples/api/form.html for this code.
I can see a few potential issues:
1) The columns Option
The columns data that you build contains a data option which is documented here. This expects to find the data for that column in an array containing objects of the given name.
So, for example, one of the values you push into the array is "data": "1a".
This means DataTables expects the first column to get its data from the values named "1a" in the data source.
2) The data Option
The data option (see here) tells DataTables where to look for the table data. For example, it's used by the above columns.data option. This option is supposed to contain an array of arrays, or an array of objects. It also needs to be valid JSON. In your case, it is just this: data: { test: 100 }. This is not valid JSON.
This also does not support the columns.data names expected (e.g. "1a" as noted above).
3) The HTML Table
DataTables also lets you define your data directly in the HTML table - which you have done here. This conflicts with using the data option, too.
A Quick Test
Comment out the data:... and columns:... options in your DataTable definition. You will no longer get any errors. This is just a quick way to confirm the above notes.
If you are providing all your data directly into the HTML table before initializing your DataTable object, then that may be all you need (like the example you are following).
One Way Forward
If you want to pass both the data and column definitions dynamically to DataTables via JSON (which I assume you do) then you can to do the following:
a) Strip down the HTML table by removing all its inner tags (<thead>, <tbody>). You will avoid your current conflicts by having an empty HTML table definition.
b) Provide column headings in the a.push section by using title: e.QuestionNumber, (or whatever field you want to use for headings). See here.
c) Use a function to build the input fields you need for the relevant column values. You need to do this because you no longer have these in the <html> definition.
For step (c), you can see an example here of how to dynamically render different types of data in your cell using render: function(...).
That should give you some pointers.
It may not get you to your end goal - but you should be able to move past your current error, and ask a more specific/targeted question, as needed (assuming it has not already been asked and answered here, of course).

jQuery Datatables increase loading speed

I just included some logging into my application. For testing purpose, I filled the database with some test values (basically the same row over and over again, about 27k rows..).
Now I wanted to print the data on a view, doing this:
<table id="chatLogs">
<thead>
<tr>
<th>ID</th>
<th>Message ID</th>
<th>User Agent</th>
<th>IP:Port</th>
</tr>
</thead>
<tbody>
<?php
foreach($chatlogs as $log){ ?>
<tr>
<td><?=$log['ID'];?></td>
<td><?=$log['messageID'];?></td>
<td><?=$log['userAgent'];?></td>
<td><?=$log['IP'];?></td>
</tr>
<?php }
?>
</tbody>
</table>
$log is a variable I'm getting using the Database-Interface called Medoo.
Additionally, I included jQuery DataTables for better and sortable tables.
<script>
$(document).ready( function () {
$('#chatLogs').DataTable({
dom: 'Bfrtip',
buttons: [
'copy', 'excel', 'pdf'
]
});
} );
</script>
Now, until everything is done and the page is fully loaded, it takes about 15 seconds (with the 27k test-rows).
I just tested the same query directly on the database, and it takes 0.02 seconds, so its definetely about the PHP, not about the SQL.
And it seems like echoing everything in the table takes some time, as well as "loading it into DataTables"...
Now the question is: Is it possible to have it loading faster or instantly, and load the data, when its needed? I mean like only load the data into JSON and not echoing everything first (which is the longest part)? Because in the table, there are only 10 rows first anyway, and everytime I click on the next page, it could render it. Ofcourse though, all data would still need to be available for search.
Any ideas?
You could improve the loading time by loading only a set of records at a time using limit $start $stop to improve performance using php and sql or you could use "iDisplayLength", property of DataTable to do so.

How to update/refresh datatable after an ajax update or insert call?

I have this table right here that is populated by query results from my database:
<div class="card-block">
<table id="catTbl" class="display" width="100%" cellspacing="0" data-toggle="modal" data-target="#cat-update">
<thead>
<tr>
<th>ID</th>
<th>Title</th>
</tr>
</thead>
<tbody>
<?php
include "../processes/getLists.php";
$process = new getLists();
$process->getCatForTbl();
//used PHP PDO for that
?>
</tbody>
</table>
<p id="message" style="margin-top: 15px"></p>
</div>
I can properly update and insert rows in the database using ajax so the page won't load every after process but the problem is if I don't reload my page after every insert/update the datatable won't update with the newly updated/inserted rows.
I tried $("#catTbl").ajax.reload(), $("#catTbl").clear().draw() but they won't work unless my table is somehow made up of json. Is there anything I can do for my table to reload every after ajax call? Add: I don't want the whole page to reload, just the datatable on submit event.
$('#updateCatForm').on("submit", function(event){
event.preventDefault();
$.ajax({
url:"../ajax/updateCat.php",
method:"POST",
data:$('#updateCatForm').serialize(),
success:function(data){
$('#updateCatForm')[0].reset();
$('#cat-update').modal('hide');
$('#message').html(data);
//I put the table reload solutions here and nothing seemed to work :<
}
})
});
Use this
$('#example').DataTable().ajax.reload();
Make sure the selector is same. Or you can simply store in a variable and use it like this
var table = $('#example').DataTable();
Then after ajax
table.ajax.reload();
---Edit----
table.ajax.reload({
"ajax": {
"url": '${ctx}/work/list_ajax.json',
"type": 'POST',
"data":{
data:$('form').serialize()
}
}
});
I'm not entirely sure about this, I didn't give it a try but it's something along this line to get the data and display on the table. I'm sorry I couldn't provide you with a working snippet. Remeber the returned data should be in a proper format or it won't work.

Dyntable sort does not work at all from Ajax

I am using dyna table with Ajax. Sorting, searching, pagination nothing is working. I only get a list in my table but on clicking the column header nothing happens.
Please help.This is my code.
My html file is
<table style="width:100%" id="my-final-table" class="tablesorter" >
<thead>
<tr bgcolor="#239B56">
<th><font style="color:#fff">Rollno</font></th>
<th><font style="color:#fff">Name</font></th>
<th><font style="color:#fff">Marks</font></th>
<th><font style="color:#fff">Percentage</font></th>
</tr>
</thead>
<tbody>
</tbody>
</table>
My Ajax code is
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="/jquery.dynatable.js"></script>
<style src="/jquery.dynatable.css"></style>
<script type="text/javascript">
$(document).ready(function()
{
$('#my-final-table').dynatable({
dataset: {
ajax: true,
ajaxOnLoad: true,
ajaxUrl: '/result_analysis_subject_json.json',
records: []
}
});
});
</script>
And my JSON file is
{"records":[{"rollno":"1","name":"Aditya Kumar Sharma","marks":"12.00","percentage":40},{"rollno":"2","name":"Aksh Kathuria","marks":"19.00","percentage":63},{"rollno":"3","name":"Anant ","marks":"14.00","percentage":47},{"rollno":"4","name":"Arnav Arora","marks":"28.00","percentage":93},{"rollno":"5","name":"Ayush Sai Raina","marks":"26.00","percentage":87},{"rollno":"6","name":"Ayush Rawat","marks":"21.00","percentage":70},{"rollno":"7","name":"Bhagya Dua","marks":"11.00","percentage":37},{"rollno":"8","name":"Bhvesh Gautam","marks":"26.00","percentage":87},{"rollno":"9","name":"Chaitanya Dubey","marks":"18.00","percentage":60},{"rollno":"10","name":"Chanchal","marks":"5.00","percentage":17},{"rollno":"11","name":"Deeksha","marks":"28.00","percentage":93},{"rollno":"12","name":"Dimple Bhatia","marks":"26.00","percentage":87},{"rollno":"13","name":"Ekta Yadav","marks":"27.00","percentage":90},{"rollno":"14","name":"Eshan Sharma","marks":"24.00","percentage":80},{"rollno":"15","name":"Harman Arora","marks":"13.00","percentage":43},{"rollno":"16","name":"Himanya ","marks":"18.00","percentage":60},{"rollno":"17","name":"Hiya Bhatia","marks":"29.00","percentage":97},{"rollno":"18","name":"Ishmeet Kaur","marks":"13.00","percentage":43},{"rollno":"19","name":"Jivitesh Gwadi","marks":"20.00","percentage":67},{"rollno":"20","name":"Jiya Hussain","marks":"7.00","percentage":23},{"rollno":"21","name":"Krish Kohli","marks":"13.00","percentage":43},{"rollno":"22","name":"Krishna Sharma","marks":"22.00","percentage":73},{"rollno":"23","name":"Lisha Kapoor","marks":"27.00","percentage":90},{"rollno":"24","name":"Mannant Sehgal","marks":"20.00","percentage":67},{"rollno":"25","name":"Mayank Mehta","marks":"19.00","percentage":63},{"rollno":"26","name":"Mehak Singh","marks":"26.00","percentage":87},{"rollno":"27","name":"Nandini Bhargava","marks":"29.00","percentage":97},{"rollno":"28","name":"Parth Talwar","marks":"27.00","percentage":90},{"rollno":"29","name":"Pawni Yadav","marks":"27.00","percentage":90},{"rollno":"30","name":"Prachi Dahiya","marks":"21.00","percentage":70},{"rollno":"31","name":"Prachi Sharma","marks":"18.00","percentage":60},{"rollno":"32","name":"Rashi Bainsla","marks":"19.00","percentage":63},{"rollno":"33","name":"Ravinder Singh","marks":"5.00","percentage":17},{"rollno":"34","name":"Riya Sethi","marks":"14.00","percentage":47},{"rollno":"35","name":"Sahib Kharbanda","marks":"24.00","percentage":80},{"rollno":"36","name":"Sajal Kukreja","marks":"23.00","percentage":77},{"rollno":"37","name":"Shrishty Singh","marks":"26.00","percentage":87},{"rollno":"38","name":"Tanisha Kaur","marks":"26.00","percentage":87},{"rollno":"39","name":"Toshiv Mudgal","marks":"16.00","percentage":53},{"rollno":"40","name":"Yash Anand","marks":"23.00","percentage":77}],"queryRecordCount":40,"totalRecordCount":40}
From what i can read from the documentation , the sorting, searching, and paginating needs to be done on the server side
NOTE: When using AJAX to load data, operations such as sorting, searching, and paginating are performed on the server before building the returned JSON. This example has these features disabled since, we're just loading a static JSON file for the purposes of documentation.
When using Dynatable in "AJAX mode" (dataset.ajax = true), delegates all operations (pagination, sorting, and querying/filtering) to the server. For each operation, dynatalbe culls the parameters (sort, search, page) into an AJAX request and fetches the results from dataset.ajaxUrl (if this setting isn't set, it will send an AJAX request to the URL of the current page).
more info
in the ajax call
records: function myFunction(rec){}
perform your js library code in myFunction on rec

X-editable: Smarty Loop Array

The page I am trying to create is an edit page for different labtests. Each labtest has different results that fall under it and different normal ranges (hence the Min/Max) so the values are from a SQL SELECT statement in PHP then sent to Smarty. I am using BootStrap hence why I went with X-editable.
I want to use X-editable to edit these lab test values, but am running into issues in the foreach statement. The edit function works for the first row, but not the following rows. My understanding is it is because they have the same id (I.E. a id=""). Is there any way around this? I am quite new to JS so I am struggling to come up with solutions.
Shooting in the dark here, but I could try using the PK in addition as part of the id and send the array to the JS to loop through as well to make the link editable in JS? It seems a bit silly logically though so hopefully there is a better way?
Here is what I have done.
<table class="table table-striped">
<thead>
<th>Test Type</th>
<th>Measurement Unit</th>
<th>Min. Male</th>
<th>Max. Male</th>
<th>Min. Female</th>
<th>Max. Female</th>
<th>Min. Child</th>
<th>Max. Child</th>
</thead>
{foreach from=$alltests item=alltests}
<tr>
<td>{$alltests.valuename}</td>
<td>{$alltests.Units}</td>
<td>{$alltests.MaleMin}</td>
<td>{$alltests.MaleMax}</td>
<td>{$alltests.FemaleMin}</td>
<td>{$alltests.FemaleMax}</td>
<td>{$alltests.ChildMin}</td>
<td>{$alltests.ChildMax}</td>
</tr>
{/foreach}
{literal}
<script>
$(document).ready(function() {
$('#TestName').editable();
$('#TestPrice').editable();
$('#valuename').editable();
$('#Units').editable();
$('#MaleMin').editable();
$('#MaleMax').editable();
$('#FemaleMin').editable();
$('#FemaleMax').editable();
$('#ChildMin').editable();
$('#ChildMax').editable();
});
</script>
{/literal}
Thank you for your time!
Have you tried doing it with one class instead of id?
<td>{$alltests.valuename}</td>
<td>{$alltests.Units}</td>
and so on, and then:
$('.is_editable').editable();

Categories

Resources