so I'm trying to change the td class of my datatables elements dynamically. From my research i found fnRowCallback, it seems to be the solution but I can't get it to work. From 1 of the questions here at Stack I found:
"fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
for (var i in aData) {
// Check if a cell contains data in the following format:
// '[state] content'
if (aData[i].substring(0,1)=='[') {
// remove the state part from the content and use the given state as CSS class
var stateName= aData[i].substring(1,aData[i].indexOf(']'));
var content= aData[i].substring(aData[i].indexOf(']')+1);
$('td:eq('+i+')', nRow).html(content).addClass(stateName);
}
}
}
But this does not work for me, I get the error: Uncaught SyntaxError: Unexpected token, and my elements keep the "[class name] content" format. Here is my javascript function:
$('#tableId').DataTable({
"ajax" : "function.php",
"columns" : [
{
"data" : "id"
}, {
"data" : "firstElement"
}, {
"data" : "secondElement"
}, {
"data" : "thirdElement"
}],
"fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
for (var i in aData) {
// Check if a cell contains data in the following format:
// '[state] content'
if (aData[i].substring(0,1)=='[') {
// remove the state part from the content and use the given state as CSS class
var stateName= aData[i].substring(1,aData[i].indexOf(']'));
var content= aData[i].substring(aData[i].indexOf(']')+1);
$('td:eq('+i+')', nRow).html(content).addClass(stateName);
}
}
},
"iDisplayLength": 5,
"scrollX": true,
"orderFixed": [[ 0, "asc"]]
});
function.php gives me a JSON with all the fields, and in the ones I want the class altered I use "[class name] content" in the field. Any ideas on how to get it to work?
Thanks
Problem with your code is that aData would be an associative array, for example:
{ "id": 1, "firstElement": "[class] content" }
When you enumerate properties with for...in construct, i would hold property name (id, firstElement) and not numerical index.
Therefore you cannot use i to access cell within given row.
Another problem with your code is that it sets HTML content after it has been created. jQuery DataTables will be unaware that you've updated cell content.
Related
I am trying to add datatable info i.e "Page 1 of 1" between pagination text. Is it possible to achieve this?
var table = $('#example').DataTable({
pagingType: "full",
pageLength: 5,
info: true,
language: {
info: "Page _PAGE_ of _PAGES_",
paginate: {
previous: '<',
next: '>'
}
}
})
Add this to your code:
I edit my code to fit your case. Also it appears that datatable need to keep the original info element in order to do the update after you switch to another page, so you need to clone it to the new place instead of cut and paste, and set hide
drawCallback: function( settings ) {
$(".dataTables_paginate").children(':eq(1)').after($(".dataTables_info").hide().clone().css({'display':'inline-block', 'float': 'unset'}));
}
https://jsfiddle.net/96oy3buk/3/
using DataTables, I can see this error in the console, even if my table is correctly displayed ... I guess it's not so important but could it have any collateral effect late ?
the error in the console is :
## assets => DataTable-1.10.9/js/jQuery.dataTables.js
Uncaught TypeError: Cannot read property 'replace' of null
and the faulty line is : var sTitle = col.sTitle.replace( /<.*?>/g, "" )
#### DataTable-1.10.9/js/jQuery.dataTables.js
function _fnSortAria ( settings )
{
var label;
var nextSort;
var columns = settings.aoColumns;
.../...
// ARIA attributes - need to loop all columns, to update all (removing old
// attributes as needed)
for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
{
var col = columns[i];
var asSorting = col.asSorting;
var sTitle = col.sTitle.replace( /<.*?>/g, "" );
var th = col.nTh;
../...
Checking it, col.sTitle is null... no default settings
The DataTables.net documentation ( https://datatables.net/reference/option/columns.title ) indicates 2 ways of setting the column titles : I am using the columns() way, and all my titles are correctly displayed ... It doesn't indicates WHEN we should use one way or the other way ...
$('#example').dataTable( {
"columnDefs": [
{ "title": "My column title", "targets": 0 }
]
} );
$('#example').dataTable( {
"columns": [
{ "title": "My column title" },
null,
null,
null,
null
]
} );
I "guess" it's related to the fact I am using the DataTable API rather than the jQuery dataTable selector ...
# here is my table initialisation
// Let datatables render it now - accessing API
var table = $('#sheet').DataTable({
dom: "<'row'<'col-xs-6'><'col-xs-6'f>r>t<'row'<'col-xs-6'l><'col-xs-6'p>>",
language: { url: langUrl },
ordering: true,
searching: true,
paging: true,
info: false,
select: true,
data: sheet.data,
columns: column_titles
columnDefs: [{"targets": [ 0 ],"visible": false}]
});
I wrote a dataTables directive for AngularJS. Its working fine except that i trying to add an button to the row that removes an row with an ng-click.
In my opinion is that the problem occurs because the table row doesn't now the scope.
Can somebody help me out solving this problem.
jsFiddle Example: http://jsfiddle.net/A5Zvh/7/
My directive looks like this.
angular.module('DataTables', [])
.directive('datatable', function() {
return {
restrict: 'E',
transclude: true,
replace: true,
require: 'ngModel',
template: '<table></table>',
link: function(scope, element, attrs, model) {
var dataTable = null,
options;
var buttons = jQuery.parseJSON(attrs['buttons']) || null;
options = {
"bJQueryUI": false,
"sDom": "<'row-fluid'<'span4'l><'span8 filter' <'pull-right'T> <'pull-right'f>>r>t<'row-fluid'<'span6'i><'span6'p>>",
"sPaginationType": "bootstrap",
"oTableTools": {
}
};
if(_.has(attrs, 'datatableOptions')) {
jQuery.extend(true, options, scope.$eval(attrs['datatableOptions']));
}
scope.$watch(attrs.ngModel, function(data) {
if(data && _.size(data.aaData) > 0 && _.size(data.aoColumns) > 0) {
_.extend(options, scope.$eval(attrs.ngModel))
dataTable = $(element).dataTable(options);
dataTable.fnClearTable();
dataTable.fnAddData(data.aaData);
}
});
}
}
})
I'm using Angular-datatbles, and I was trying to dynamically add, Edit & Remove links to the datatble rows and display modal on ng-click;
This was the solution for my case;
$scope.dtOptions.withOption('fnRowCallback',
function (nRow, aData, iDisplayIndex, iDisplayIndexFull) {
$compile(nRow)($scope);
});
All the datatable binding code;
$scope.reloadData = function () {
$scope.dtOptions.reloadData();
};
$scope.dtColumnDefs = [
DTColumnDefBuilder.newColumnDef(2).renderWith(function (data, type, row) {
var html = '<i class="fa fa-pencil hidden-xs"></i> Edit' +
'<i class="fa fa-times hidden-xs"></i> Remove';
return html;
})
];
$scope.dtColumns = [
DTColumnBuilder.newColumn('name').withTitle('Name'),
DTColumnBuilder.newColumn('type').withTitle('Type'),
DTColumnBuilder.newColumn('id').withTitle(''),
];
$scope.dtOptions.withOption('fnRowCallback',
function (nRow, aData, iDisplayIndex, iDisplayIndexFull) {
$compile(nRow)($scope);
});
I solved this by going through each td and calling $compile. Using the datatable row callback function. Hope this helps.
options.fnCreatedCell = function (nTd, sData, oData, iRow, iCol) {
$compile(nTd)($scope);
}
//or row
options.fnCreatedRow = function( nRow, aData, iDataIndex ) {
$compile(nRow)($scope);
}
The delete function in your controller isn't called because AngularJS doesn't know anything about DataTables's insertion of those elements to the DOM, thus ngClick directive within those elements isn't compiled and linked. So change:
dataTable.fnAddData(data.aaData);
To
dataTable.fnAddData(data.aaData);
$compile(element)(scope);
And to inject $compile service:
.directive('datatable', function () {
To
.directive('datatable', function ($compile) {
And your delete function is broken in the jsFiddle, hope that's not the case in your actual project!
You might want to give a look at the first couple of Zdam's post on this Google Groups thread, especially to his/her two linked jsFiddles. I basically copied them and they work at a basic level. I have not tried yet to get some action starting from a click on a row.
I see that you implemented a slightly different approach, recreating the <table> HTML node altogether. Not sure if this is causing issues.
By the way, on the scope.$watch call I had to make sure there was a third parameter set to true, in order to make value comparison (instead of reference comparison) on the returned resource$ object. Not sure why you don't need that.
fnCreatedCell be supplied in aoColumns or fnCreatedRow supplied to mRender
1 )fnCreatedCell is column based
ex :
tableElement.dataTable({
"bDestroy": true,
oLanguage : {
sLengthMenu : '_MENU_ records per page'
},
aoColumnDefs: [
{
bSortable: false,
aTargets: [ -1,-2,-3 ],
"fnCreatedCell": function (nTd, sData, oData, iRow, iCol)
{
$compile(nTd)($scope)
}
}
],
2 ) fnCreatedRow is a 'top level' callback
tableElement.dataTable({
"bDestroy": true,
oLanguage : {
sLengthMenu : '_MENU_ records per page'
},
aoColumnDefs: [
{
bSortable: false,
aTargets: [ -1,-2,-3 ]
}
],
"fnCreatedRow": function( nRow, aData, iDataIndex ){
compile(nRow)(scope);
},
I'm using DataTables (datatables.net) to display data from an Ajax source and having trouble customizing it. One thing I would like to do is add a column so I can have for example an 'edit' button for each row.
The closest thing to that in the examples is here but I can't get that to work with an ajax source.
Currently, I'm using the following code to display my table:
fnServerObjectToArray = function ( aElements ){
return function ( sSource, aoData, fnCallback ) {
$.ajax( {
"dataType": 'json',
"type": "POST",
"url": sSource,
"data": aoData,
"success": function (json) {
var a = [];
for ( var i=0, iLen=json.aaData.length ; i<iLen ; i++ ) {
var inner = [];
for ( var j=0, jLen=aElements.length ; j<jLen ; j++ ) {
inner.push( json.aaData[i][aElements[j]] );
}
a.push( inner );
}
json.aaData = a;
fnCallback(json);
}
} );
}
}
$(document).ready(function() {
$('#example').dataTable( {
"bProcessing": true,
"sAjaxSource": 'get_data.php',
"fnServerData": fnServerObjectToArray( [ 'username', 'email' ] )
} );
});
Why don't you use fnRenderFunction in the aoColumns? As an example:
aoColumns: [ { "bVisible": false} , null, null, null, null,
{ "sName": "ID",
"bSearchable": false,
"bSortable": false,
"fnRender": function (oObj) {
return "<a href='EditData.php?id=" + oObj.aData[0] + "'>Edit</a>";
}
}
]
You can use it to format the value from the server side.
See similar example on the http://jquery-datatables-editable.googlecode.com/svn/trunk/ajax-inlinebuttons.html (ignore specific settings for the editable plugin)
I've created columns with edit button and links and so on, but usually i do everything server side by custominzg the data i return and then show/hide them with the aoColumns option. I don't really understand what you are tring to achieve: display server side data as a link?
Had the same problem a few months back. This is what I did.
By no means an elegant slution, but this worked.
As you might already know, DataTables do have an overload to accept Javascript Arrays.
So I made by $.ajax call. got my json, parsed it to a javascript array and then while parsing I created an extra element (an anchor tag) with href="edit.php?email=passed_email" Then on the column headers and added a column called Edit. Those values were fed to "aaData" and "aoColumns". And then the table was populated.
And BTW, if you looking for inline editing, check the following link.
DataTables editing example - with jEditableplugin
i have some RND on this problem and get this hope this will help you out.
I want to add some class to row when I render a table, sample code:
$("#id").dataTable({
bProcessing: true,
sAjaxSource: com.mycompany.path.api.message[component],
aoColumns: [
{}, {},
{
sWidth: "37px",
fnRender: function(obj) {
return "<span>" + myData + "</span>";
}
}
]
});
In this example I could only control "td" tags, but I want to add some class for "tr" tag based on data that I get in fnRender() in cycle.
How I can do it with datatables?
Thanks,
Looks like in 1.7.3 available new functionality:
http://www.datatables.net/examples/advanced_init/row_callback.html