Why does this DataTables Ajax call not work properly? - php

I am attempting to get dataTables plugin to work with information for a website. I have read the documentation and various support threads for datatables as well as various StackOverflow questions, to no avail in resolution. According to the above documentation, the code I have should work just fine... it doesn't.
Javascript:
$(document).ready( function(){
$('#results_table').dataTable( {
'bServerSide': true,
'sAjaxSource': 'results.php',
'fnServerParams': function ( aoData ) {
aoData.push( { 't': Math.random() });
}
});
});
HTML Code:
<div id='results'>
<table id='results_table' >
<thead>
<tr>
<th>Num</th>
<th>Type</th>
<th>Access date</th>
<th>Access name</th>
</tr>
</thead>
<tbody>
</div>
PHP snippet (after retrieving/formatting SQL data:
$output = array('sEcho'=>1,'iTotalRecords'=>$count, 'iTotalDisplayRecords'=>$count, 'aaData'=> $results);
echo json_encode($output);
Returned data (small subset of the total for testing):
{"sEcho":1,"iTotalRecords":3,"iTotalDisplayRecords":3,"aaData":[["1707052901-1A","D","Aug 17, 2012 1:54 PM","aqr"],["1707052901-1A","C","Aug 17, 2012 1:53 PM","aqr"],["2835602-4A","D","Aug 15, 2012 7:39 AM","aqr"]]}
Now, when I load the page with datatables I receive an extremely helpful answer regarding -
Uncaught TypeError: Cannot read property 'length' of undefined jquery.dataTables.min.js:49
and the table does not populate with information.
Question: What am I doing wrong; why does my implementation of server-side processing for dataTables not work?? How can I fix this to display properly?

aoData.push( { 't': Math.random() });
should be used like this:
aoData.push( { 'name': 't', 'value':Math.random() });
not sure if this is the issue, but this fixed some of my problems when using datatables

Related

How to ajaxify a PHP function that does SQL in the backend?

I have broken down my problem to provide a concise example with no overhead.
Yet enough to give you an idea.
I have a simple index.php
<?php
include 'myClass.php';
?>
<html>
<head></head>
<body>
<div> <?php myClass->printTable(); ?> </div>
</body>
</html>
The function returns an entire table filled with data that is being prepared in the backend.
<?php
function printTable()
{
// printing static table header
echo ' <table class="table" style="zoom: 0.75;">
<thead class="thead-dark">
<tr>
<th scope="col">Date</th> // current date
<th scope="col">Order Number</th> // an int
<th scope="col">Current Value</th> // an int
</tr>
</thead>
<tbody>
';
$result = mysqli_query($this->link, "SELECT * FROM `someData`");
while ($row = mysqli_fetch_assoc($result))
{
$orderNumber = $row['orderNumber'];
$currentValue = $row['currentValue'];
$date = $this->getDate($orderNumber); // member function that returns a timestamp from the database
//printing actual table
echo ' <tr>
<td>'. $date .'</td>
<td>'. $orderNumber .'</td>
<td>'. $currentValue .'</td>
</tr>
';
}
echo ' </tbody>
</table>
';
}
?>
The data I'm querying from my database is constantly changing. I want a "live" view on the frontend. I know this is done by using Ajax. But I don't understand how to do it. I looked up different resources, although none of them were actually specific enough in this approach.
On a high level: You need a PHP file ("endpoint", e.g. 'localhost/data.php') returning only the HTML code from printTable. You then use JavaScript (e.g. jQuery - $.ajax, you can lookup how it works in detail) to fetch the contents of this page each n seconds and insert into your page.
I was looking for broad or unspecific way to get some data from the backend and display it within a div on my page.
The solution was to create a separate PHP (fetch.php) file that echoes only the data I need to display within my div
from my page which contains my div I'd do the following:
<div id="result"></div>
<script>
function load_data()
{
$.ajax({
url:"fetch.php",
method:"POST",
success:function(data)
{
$('#result').html(data);
}
});
}
load_data()
</script>
Inside fetch.php I can do whatever I want, including querying my database and store the values in a variable which will be echoed at the end. This response (echo) from fetch.php will then be displayed inside my div.
Similarly, I could also specify a .txt inside the ajax function (url:"sometext.txt")
The contents of the .txt could also be displayed inside my div this way. My lack of understanding of how this works made it really difficult to understand.
Additionally, I have added a function to refresh the contents (or response) every second.
If I would echo time() from fetch.php it would automatically increment without page reload inside my div
setInterval(function(){
load_data()
}, 1000);

Resetting a div to load new json/ajax information?

Alrighty. So it's been a while since i've worked with Ajax/json/jquery/javaeverything and I cannot for the life of me remember how to "reset" a div/wipe the buffer after running a json/ajax function.
Case in point: I've got a button that is effected by ajax function, the code is below.
function CMA(id)
{
$('#capture').on('click',function(){
$.ajax({
url:'cma.php',
type:"POST",
data:{sid:id,uid:uid},
dataType:"json",
success: function(data) {
if(data.status == 'attack')
{
$('#capture').fadeOut('slow',function(){
$(this).html('CAPTURING').prop('disabled',true).fadeIn('slow')});
}
}
})
});
}
It is directly effecting this bit of code
$html .="<table>
<tr>
<th colspan='2'>Star Information</th>
</tr>
<tr><th>Star ID</th><td id='starID'></td></tr>
<tr><th>Current Owner</th><td id='owner'></td></tr>
<tr><th colspan='2'><button id='capture'>CAPTURE</button></th></tr>
</table>";
($html is echoed else where but that's a lenghty bit of code)
The information in the starID information will change, so does the owner information (as far as I can tell). However, the CAPTURE button will not change back. as I've said, It's been a while since i've worked with anything java, so if this is something super obvious, i apologize -- but my google foo is failing me spectacularly and my brain is running solely off mountain dew and pringles.

Datatable: update table in realtime with animation

I am trying to implement functionality where it updates data in real time of my datatable with animation just like facebook ticker (last friends activities on the sidebar) but no solution found !
model file :Topic.php
public function getTopics()
{
return $this->db->select('SELECT * FROM topics');
}
index file:
<table id="example" class="table table-striped table-bordered" cellspacing="0">
<thead>
<tr>
<th>ID</th>
<th>Sujet</th>
<th>Pièce jointe</th>
<th>Coordonnées</th>
</tr>
</thead>
<tbody>
<!--content table -->
<?php
if($data['topics']){
foreach($data['topics'] as $row){
echo '<tr>';
echo '<td>'.$row->id.'</td>';
echo '<td>'.$row->subject.'</td>';
echo '<td>'.$row->document.'</td>';
echo '<td>'.$row->x.','.$row->y.'</td>';
echo '</tr>';
}
}
?>
</tbody>
</table>
controller:
$data['topics'] = $this->_topic->getTopics();
$data['js'] = "<script>
$(document).ready(
function ()
{
$('#example').DataTable().ajax.reload();;
}
);
</script>";
View::renderTemplate('header');
View::render('account/topics', $data);
View::renderTemplate('footer', $data);
This is called real time functionality! There are a few days to do it!
Use ajax to update data and setInterval on the ajax function for maybe like 5s or 10s whatever you like.
The other way that I'd do is by using getting an API Pusher. Pusher is a real time functionality web app! It can be used to achieve real time functionality on your site!
You can use setInterval() to check for topics every x seconds, minutes etc:
setInterval(function(){
$.ajax({
type: 'GET',
url: 'path/to/query',
success:function(data){
if(data != ""){
$('#datatable-table').dataTable()._fnAjaxUpdate();//reloads table, syntax will differ based on datatables version
}
}
})
}, 5000);//every 5 seconds
This is only an example. You'll need to plan (for example, what happens when the response takes longer than 5 seconds?)

Angular search filter not working (data returned by PHP)

I dont get the search filter working.
projects template:
<h3>Projekte</h3>
Search: <input ng-model="searchText">
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>Title</th>
<th>Long Title</th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="(key, project) in projects | filter:searchText">
<td>{{key}}</td>
<td>{{project.title}}</td>
<td>{{project.longTitle}}</td>
<td><button class="btn btn-default" ng-click="edit()"><i class="fa fa-pencil"></i></button></td>
</tr>
</tbody>
</table>
controller:
var secProjects = function ($http,$scope, $modal) {
$http.post('php/data.php').
success(function(data) {
$scope.projects = data;
})
}
php:
while($row = mysql_fetch_object($result)){
$data[$row->ID] = array ('id'=>$row->ID,'title'=>$row->Title,'longTitle'=>$row->TitleLong, 'textDE'=>$row->DescriptionDE,'start'=>$row->DateStart,'end'=>$row->DateEnd);
}
echo json_encode($data);
i hope you can help me :( I think the reason ist the way i get the data in my scope. but iam not sure.
EDIT: Change the PHP solved the Problem:
$data = array();
while($row = mysql_fetch_object($result)){
array_push($data,['id'=>$row->ID,'title'=>$row->Title,'longTitle'=>$row->TitleLong]);
}
echo json_encode($data);
The problem is that your backend returns the data as an object instead of an array.
But the filter works only on arrays (according to the docs):
Selects a subset of items from array and returns it as a new array.
So, you have two options:
1.
Before assigning the data to your scope, convert them from object to array. E.g.:
$http.post(...).success(function (data) {
$scope.projects = [];
for (var key in data) {
$scope.projects.push(data[key]);
}
});
2.
Have your backend return the data as a JSONified array, instead of an object.
The reason PHP is interpreting your $data "array" as an object is that the indices are not sequential (starting from 0). I.e. instead of having indices 0, 1, 2..., you had 1,2,3.... (See, this answer for more info.)
To fix this, you can change your code, like this:
$data[] = array (...
See, also, this short demo.
I've duplicated your work, without the service call here. It's exactly the same except for your post (should be a get). And it works fine. Take some more time to check your work. Javascript errors may disable further functionality.
.
$scope.projects = [{
title: 'one',
longTitle: 'one long title'
}, {
title: 'two',
longTitle: 'two long title'
}];

Is there any way to fetch ajax data as separate variable instead of full HTML?

I am trying to fetch book rows by books' first letter with jquery $.post into my <td> </td> which is part of my table.
My table looks like :
<table id="myTable">
<thead>
<tr>
<th class="page">pages</th>
<th class="book_name">Book Name</th>
<th class="author">Author</th>
</tr>
</thead>
<tbody id="result_list">
<!--Here is data which will come with ajax($.post) -->
</tbody>
</table>
Writing jquery code, I become successful but with $("#result_list").html(data) like this:
$.post( "/ajax.php", { book_first_letter: 'A'},
function( data ) {
$( "#result_list" ).html( data );
}
);
But I dont want to fetch all data as HTML and insert into <tbody> . I want to fetch data from ajax.php as separate variable. For example; book_name,logo,pages,author. And I want to insert them into <td> </td>.
My ajax.php is like this:
$letter= trim($_POST['book_first_letter']);
$query = $this->book_model->get_books_by_letter($letter);
foreach ($query as $book) { ?>
<tr>
<td> <?php echo $book->page; ?> </td>
<td> <?php echo $book->name; ?> </td>
<td> <?php echo $book->author; ?> </td>
</tr>
<?php
}
?>
Is there any way to take each variable(i.e. $book->name) and insert it into <td></td> ?
Not only can you, but you should.
Rather than having PHP return html as text, have it return a JSON object.
You're going to need to do a few things.
First add a fourth argument to your $.post() call for a dataType of "json".
$.post( "/ajax.php", { book_first_letter: 'A'}, callback, "json" );
Then, its good form to have PHP send JSON headers for the result so before you send out any data in PHP use
header('Cache-Control: no-cache, must-revalidate');
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Content-type: application/json');
And rather than echoing out the properties of your book model, just use json_encode()
$letter= trim($_POST['book_first_letter']);
$books = $this->book_model->get_books_by_letter($letter);
echo json_encode( $books );
So the client now has the raw data and you can use js/jQuery to loop through the books and add it to your table.
function callback( books)
{
var i = 0, len = books.length, html = "";
for( ; i < len; ; )
{
html += "however you want to structure the data";
}
$( "#result_list" ).html( html );
}
You could just transform your data into JSON by using json_encode():
$letter= trim($_GET['book_first_letter']);
$query = $this->book_model->get_books_by_letter($letter);
echo json_encode( $query );
On the client side you then use getJSON() and have a similar object in JavaScript as you had in PHP:
$.getJSON( "/ajax.php", { book_first_letter: 'A'},
function( data ) {
// data has the same properties as $query did in PHP
}
);
EDIT
As pointed out by #MrCode getJSON() just does a GET request. So i changed the way to access the parameter in the PHP code from $_POST to $_GET.
Here a GET request is probably the better choice, anyway, as GET requests here could be cached by the browser, whereas POST request will have to be executed each time.
The other option would be to leave the POST request in place, which would change the client side JS to
$.post( "/ajax.php", { book_first_letter: 'A'},
function( data ) {
// data has the same properties as $query did in PHP
}
, 'json'
);
JSON will be your best way to do this
And depending on what you are getting back into $query it should be as easy as
echo json_encode($query)
Then you will have to process the data on the client-side javascript
Yes, there is - use JSON. PHP has json_encode function. Just create an json-like array from your data nad use json_encode to send them to client.
On client side, use $.post with dataType: json.
Json encode. It also seems to me like soon you might start considering backbone & underscore stack for your ajax needs. It features templating on the client, which looks like one of things you could definitely use in that example
you can return your variables as JSON.
In your ajax.php:
$arr = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5);
echo json_encode($arr);
In your jquery AJAX call:
$.post('ajax.php', { book_first_letter: 'A'}, function(data) {
console.log(data) //view the data returned in the console of firebug
},'json');

Categories