I have used a datatable in my codeigniter application to dynamically print database values. I am trying to sum up all the columns including numeric and string values. The numeric values are correct but the string column sum is weirdly wrong. The sum only works for some of the values of the column. For example it sums up 8 out of 10 rows. But the numeric sum shows sum of all 10 rows.
I am providing the code below.
Note: I am trying to use the headercallback() to print the sums of the columns. I have used two headers for this.
Datatable HTML code:
<table id="tabular" class="table table-striped table-bordered" cellspacing="0" width="100%">
<thead>
<tr>
<th>Company</th>
<th>Status</th>
<th>Created Date</th>
<th>Total Contacts</th>
<th>Total Versions</th>
<th>Articles Assigned</th>
</tr>
</thead>
<thead id="totals">
<tr>
<th id="name">asdfasf</th>
<th></th>
<th></th>
<th id="contact"></th>
<th id="version"></th>
<th id="article"></th>
</tr>
</thead>
<tbody>......(Rest of the code)
JS code to initialize the datatable on the given HTML
$(document).ready(function() {
var oTable = $('#tabular').DataTable({
// "stateSave": true,
// "order": [],
"dom": '<"row search-padding" <"col-md-12 search-padding" <"col-md-6 search-padding pull-left" <"#inp">> <"col-md-6 search-padding" <"datatable-n pull-right" l >> > >rt <"row" <"col-md-6" i > <"col-md-6" p > >',
"columns" : [
{"width": "25%" },
{"width": "18.7%" },
{"width": "18.7%" },
{"width": "14%" },
{"width": "10.7%" },
{"width": "18.7%" },
],
"stashSave":true,
"order": [],
"processing": true,
"searching" : true,
"orderCellsTop": true,
"language": {
"emptyTable": "No companies found for the selected range."
},
//code to sum up columns...
"headerCallback": function () {
var api = this.api(),
columns = [0,3,4,5]; // Add columns here
for (var i = 0; i < columns.length; i++) {
$('#totals th').eq(columns[i]).html('Total: ' + api.column(columns[i], {filter: 'applied'}).data().sum() + '<br>');
}
}
} );
I have used the sum() api :
jQuery.fn.dataTable.Api.register( 'sum()', function ( ) {
return this.flatten().reduce( function ( a, b ) {
if ( typeof a === 'string' ) {
a = a.replace(/[^\d.-]/g, '') * 1;
}
if ( typeof b === 'string' ) {
b = b.replace(/[^\d.-]/g, '') * 1;
}
return a + b;
}, 0 );
} );
I have tried all the ways to get correct value. I have cross checked the database queries and I am getting the right data.
Hope I have made it clear. Suggestions would be helpful. Thanks
Related
this is in my controller
$scoreboard = HistoryPenjualan::select('kodeSales', 'departemenId');
$day = 1;
for($i = 0; $i < $bulanCount; $i++){
if (array_key_exists($i, $bulanInterval)){
$compare = $bulanInterval[$i];
}else {
$compare = 0;
};
for ($j = 0; $j < $compare; $j++){
$dateFormat = $hariSama[$j];
$scoreboard->selectRaw("SUM(CASE WHEN tgl IN ($dateFormat) THEN score ELSE 0 END) AS '$day'");
$day++;
};
};
$scoreboard
->whereBetween('tgl', [$tglA, $tglB])
->where('departemenId', $request->departemenId)
->groupBy('departemenId','tgl')
->get();
$tglA and $tglB is a Date , $bulanCount is how many month is given in from $tglA to $tglB, $bulanInterval is an array that have the last day of all month from $tglA to $tglB, and $hariSama is an array that has implode of the same day in date so like '2023-01-01, 2023-02-01, 2023-03-01' in Index 0 and it continue till the end of the month.
and then Datatable will add column with their value like so :
$columns = [];
for($hari = 0; $hari < 31; $hari++){
$dt->addColumn($hari, function($data) use ($hari){
return $data->$hari;
});
array_push($columns,$hari);
};
array_push($columns, 'action', 'karyawan', 'cabang', 'score');
return $dt
->rawColumns($columns)
->addIndexColumn()
->skipPaging()
->make(true);
Action, Karyawan, cabang, score just ignore that cause their not part of the problem
then i have the dataTable in view with ajax:
$('.tableCustom3').DataTable().destroy();
var columns = [];
columns.push(
{ data: 'DT_RowIndex', name: 'DT_RowIndex', orderable: false, searchable: false },
{ data: 'cabang', name: 'cabang' },
);
for(var count = 0; count < 31; count++){
columns.push(
{ data: count, name: count}
);
};
columns.push(
{ data: 'action', name: 'action' },
);
$('.tableCustom3').DataTable({
processing: true,
serverSide: true,
bPaginate: false,
ajax: {
url: "{{ route('scoreboard.index') }}",
type: "GET",
data: {
tglA: tglA,
tglB: tglB,
departemenId: departemenId,
group: group,
seperate: seperate,
pisah: pisah,
},
},
columns: columns
});
}
Basically i add 0 until 30 named column + the manually i add , then it will display the result in tableCustom3 which contain
<div class="card-body table-dinamis3">
<div class="table-responsive">
<table class="table table-bordered tableCustom3">
<thead>
<tr>
<th width="5%">No</th>
<th>Nama Cabang</th>
<?php for ($count = 1; $count <= 31; $count++) { ?>
<th>Day <?php echo $count; ?></th>
<?php }; ?>
<th width="10%">Action</th>
</tr>
</thead>
</table>
</div>
</div>
So its all going good and all in the perfect place except the query to get the data , now here is the database table that iam gonna get data from :
then the result of using the query in the first code is this :
This pattern continue until Day 31 Then it continue again from start but luckily its the another month score
Sorry if this too much pic and code, but i think its necessary to know how this code flow work, what iam trying to achieve here is i want to show in row instead in column so example i give a date range from January to March then Day 1 - 30 column gonna contain the SUM of all the respective Day so Day 1 is the SUM of All January 1st score in that departementId then in the first row is for January then the 2nd Row is for february and then the 3rd Row is for march
I tried many solution from changing on datatables or in php or in query directly but it seem i cant just get to what i want, whats the best way to achieve this ? iam really weak in this kind of stuff
I have a table as the following datatable table :
<button id="addRow">Add New Row</button><br>
<table class="table table-striped table-bordered table-hover " id="example" cellSpacing=0 width="100%">
<thead>
<tr>
<th>1</th>
<th>2</th>
<th>3</th>
<th>4</th>
<th>5</th>
</tr>
</thead>
<tr style="text-align: center;">
<td>hola</td>
<td>ciao</td>
<td>bonjour</td>
<td>yo</td>
<td>salut</td>
</tr>
</table>
I'd like to append elements using a javascript script as the following :
<script type="text/javascript">
$(document).ready(function () {
debugger;
var t = $('#example').DataTable({ "searching": true, "paging": true });
var counter = 1;
$('#addRow').on('click', function ciicici() {
var now = new Date();
var now = now.toMysqlFormat();
var tii = new Date();
tii.setSeconds(tii.getSeconds() - 50000);
var tii = tii.toMysqlFormat();
$.post( "sqlmachine_test_ajax.php", { timing: now,seconding: tii })
.done(function( data ) {
t.row.add([
counter +'.1',
counter +'.2',
counter +'.3',
counter +'.4',
counter +'.5'
]).draw();
counter++;
// });
//setTimeout(function(){ciicici();}, 5000);
}); // Automatically add a first row of data
$('#addRow').click();
});
</script>
The two are working properly, the only thins is that I'd like to retreive the elements to append trough an Jquery AJAX script.
Let's say I have a php page sending back 5 values I'd like to add to each column (instead of the counter1, counter2 etc...) as the following :
<?php
echo 'counter1, counter2, counter3, counter4, counter5';
?>
and in the javascript I wanted to put simply :
...
.done(function( data ) {
t.row.add([
data //(instead of the counters)
]).draw();
counter++;
...
I have tried this, as well as arrays and json encoded arrays, but all I get is the 5 results in the same first cell of the table.
So how could I append the ajax php response to a table as data in different cells of the table?
marko
When you get your data back from the call, you have to separate using .split().
so you can do this when you get your callback
.done(function( data ) {
var splitData = data.split(", ") //Split your data with the comma and space
$.each(splitData, function(e){ //For each piece of data
//Add your rows here one by one
t.row.add([
splitData[e] //Make sure the 'e' in the function and here are the same
]).draw();
})
counter++;
});
This a loose answer, I'll try to add more soon.
Edit: More info
what I normally do is echo everything with separators. So, in your case, I would echo 1, 2, 3, 4, 5:A, B, C, D, E. So when the data returns, that's what you'll see.
In your data success, you would do something like
var dataParts = data.split(":") //This splits your data into the 2 parts using the : separator
var dataPart1 = dataParts[0] //This will get 1, 2, 3, 4, 5
var dataPart2 = dataParts[1] //this will get A, B, C, D, E
Then from there, you split using commas.
var dataPieces1 = dataPart1.split(', ');
var dataPieces2 = dataPart2.split(', ');
Then run the loops. (using javascript's for loop is usually better than using jQuery's .each())
for(var i = 0; i < dataPieces1.length; i++){ //Start your for loop on the first part
//Create a row here using dataPieces1[i], this will loop and make a new
//row every time the next loop finishes
for(var j = 0; j < dataPieces2.length; j++){ //Start the second loop
//Not sure how you would want to do this, but here's some example code
//Since you're inside a row now, append your dataPieces2[j] to that row
//This will loop for every dataPieces2 and append each one as a column
//in that single row.
}
}
I'm working with this Datatables Demo to display child rows. And i'm using php to return an array or data. I have it functioning pretty well, but have a few issues.
Here is an image of what I have currently.
As you see in the picture, there are two parent rows with the same question, and the child rows with different answers.
1. I need a way to limit one parent row for each distinct question.
2. I also need a way to loop through and display multiple child rows in the same child table.
3. Another option is how to assign data to the parent rows and another set of data to the child rows.
I know I should do that in my query, but the question column is single to many results, in two separate tables. The only way to do it with queries would be to return one result for the questions and then make another ajax call to fill the child rows. I was assuming this would be easier.
CODE:
Table:
<table id="car" class="display" cellspacing="0" width="100%">
<thead>
<tr>
<th class="details-control" style="max-width: 80px;">Expand</th>
<th>Question</th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<th></th>
<th>Question</th>
</tr>
</tfoot>
</table>
Script:
function format(d) {
//d is the original data object for the row
var tbl = '<table cellpadding="5" cellspacing="0" border="0" style="margin-left:110px; width:100%; font-size:12px;">' +
'<tr>' +
'<th style="width:60%; color:3383bb;">Answer Choices</th>' +
'<th style="width:15%; color:3383bb;"># of Answers</th>' +
'<th style="width:15%; color:3383bb;">Percentage</th>' +
'</tr>' + '<tr>' +
'<td>' + d.Answer + '</td>' +
'<td>' + d.NumberOfAnswers + '</td>' +
'<td>' + d.Percent + '</td>' +
'</tr>' + '</table>';
return tbl;
}
var table2 = $('#car').DataTable({
"ajax": "/rmsicorp/clientsite/reset/survey/surveyajax.php",
"scrollY": "400px",
"paging": false,
"bAutoWidth": true,
"columns": [
{
"className": 'details-control',
"orderable": false,
"data": null,
"defaultContent": ''
},
{ "data": "Question" },
],
}).columns.adjust().draw();
Query result:
The question column is just repeating for each answer. The rest of the columns are distinct.
It's a common problem, you can solve it on query side or language side. With this scenario i prefer the language side. What you can try to do:
Order you query by Question text;
Check if last and actual Question have the same text;
If so, add the answer to actual Question;
Otherwise create a new Question entry.
You will have to edit you format function to do that, i can suggest you to split it in two parts, one with Question header and one with the data of answers, and then you control: render or not the header.
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'
}];
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