This might be a straight forward question, but I'm struggling to implement the solution I found. Lack of experience with JavaScript.
I'm trying to implement a custom search in a DataTables table, but the function I have only fires on startup and not on typing in the search box.
here is my original question.
and here is the solution for the search I'm trying.
$.fn.dataTable.ext.search.push(function( settings, data, dataIndex ) {
var term = $('.dataTables_filter input').val().toLowerCase()
for (var i=0, l=data.length; i<l; i++) {
if ($(data[i], 'label').text().toLowerCase().indexOf(term) == 0 ) return true
}
return false
})
Ive tried it outside the $(document).ready(function(){, but it does not work.
here is the initialization of the DataTables table.
$(document).ready(function(){
.
.
.
var oTable = $('#desktop_table').dataTable({
"bInfo": false,
"iDisplayLength": 15,
"aLengthMenu": [15, 30, 50, 100],
"sPaginationType": "full_numbers",
"sDom": '<"top"i>frt<"bottom"lp><"clear">',
"oLanguage": {
"sLengthMenu": "Show _MENU_"
},
"sStripeOdd": "odd",
"sStripeEven": "even",
"rowReorder": true,
});
}
Preview of a cell in my DataTables table
<td>
<div class="plCell_desktop">
<input type="radio" class="" data-lnk_id="414107671" data-group="RUTH">
<label for="414107671">RUTH</label>
</div>
</td>
$('input[type="radio"]').change(function () {
$.fn.dataTable.ext.search.push(function( settings, data, dataIndex ) {
var term = $('.dataTables_filter input').val().toLowerCase()
for (var i=0, l=data.length; i<l; i++) {
if ($(data[i], 'label').text().toLowerCase().indexOf(term) == 0 )
return true;
}
return false;
});
var table = $('#desktop_table').DataTable();
table.draw();
});
Related
I have a datatable that shows mock json data retrieved from a text file. I have removed the first column as it contains the id and it isn't ideal to display the id on the table. I appended a buy button on each row on the first column only. However, when I sort the table the button disappears and the original first column data also appears.
JavScript:
$(document).ready(function() {
$.getJSON('/apps/mchp/clientlibs/clientlib-site/components/parametrictable/data.txt', function(json) {
var data = json.data;
var $thead = $('#parametrictable').find('thead');
var tr = $("<tr>");
$thead.append(tr);
var columns = [];
var obj = Object.keys(data[0]);
console.log(data[0])
var button = '<div class="left-btn"><i class="download fas fa-file-download"></i></div><div class="right-btn"><div class="input-group"><div class="input-group-area"><input type="text" value="100"></div><div class="input-group-icon">BUY</div></div></div>';
$.each(data[0], function(name, value) {
var column = {
"data": name,
"title":name
};
$('tr').find('th:first-child',).remove();
columns.push(column);
});
for (i=1; i<obj.length; i++) {
$(".dropdown-content").append('<li><input type="checkbox" class="dropcheck" data-column="'+i+'"/>'+obj[i]+'</li>');
}
var table= $('#tableId').DataTable({
data: data,
columns: columns,
columnDefs: [ {
orderable: true,
className: 'select-checkbox',
targets: 1
} ],
select: {
style: 'multi',
selector: 'td:first-child'
},
order: [[ 1, 'asc' ]]
});
$('tr').find('th:first-child').remove();
$('tr').find('td:first-child').remove();
$('tr').find('td:first-child').append(button);
$('tr').on('change', function(e){
e.preventDefault();
console.log('change!');
});
$('input[type=checkbox]').on( 'change', function (e) {
e.preventDefault();
var column = table.column( $(this).attr('data-column') );
column.visible( ! column.visible() );
} );
$('.show-all').on( 'click', function (e) {
e.preventDefault();
var obj = Object.keys(data[0])
for (i=1; i<obj.length; i++) {
var col = table.columns([i]);
if (col.visible().join(', ') == 'false') {
col.visible(true);
$(".dropcheck").prop("checked", false);
}
}
} );
});
})
First, it is not a good practice to hide datatable columns by .remove(), datatables have a built-in code for that by columnDefs refer:
https://datatables.net/examples/basic_init/hidden_columns.html
Second, that is not the right way to append data/html in datatable columns, use rowCallback function for datatable, see:
columnDefs: [
{
"targets": [ 0 ],
"visible": false,
"searchable": false
},
],
rowCallback: function(row, data, index) {
if($('td:eq(1)', row).find('.download').length == 0)
{
$('td:eq(1)', row).append(button);
}
},
When using datatable sort or search or any datatable actions it always refreshes the table therefore, any initialization before the action will be disregarded unless executed again.
I have used 2 table one with oututField and another with InputFields in my code and using jquery datatable i am constructing a table.
Button Clicks: Edit -- Opens Datatable in Edit Mode (Input Field)
Cancel -- Opens datatable in ReadOnly Mode(OutputField)
Desc: When i click Edit Button, Table is opened in EDIt MODE, if i change some values of input field and click cancel, rendered table in RO mode.
Problem: If again i click Edit button the changes i have made in last step persist.
I want: Table list should be refreshed from DB and should show original list.
Script Tag:
<apex:outputPanel id="DtscriptId">
<script>
var j$ = jQuery.noConflict();
var EditCheck = "{!EditCancelDispCheck}";
var extdisplayPopup ="{!extdisplayPopup}";
console.log('EditCheck'+extdisplayPopup);
var table;
if(EditCheck == 'false' || extdisplayPopup == 'false'){
console.log('Inside Data Table Script1');
document.getElementById("divextdataEditTableId").style.display = "none";
document.getElementById("divextdataTableId").style.display = "block";
table = $('#extdataTableId').DataTable();
}
if(EditCheck == 'true'){
document.getElementById("divextdataTableId").style.display = "none";
document.getElementById("divextdataEditTableId").style.display = "block";
$("#extdataEditTableId").fadeTo(0,1.00);
$('#extdataEditTableId').DataTable().destroy();
$.fn.dataTable.ext.order['dom-select'] = function ( settings, col )
{
return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
return $('select', td).val();
} );
}
/* Create an array with the values of all the input boxes in a column, parsed as numbers */
$.fn.dataTable.ext.order['dom-text-numeric'] = function ( settings, col )
{
return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
return $('input', td).val().replace(/\s/g,'') * 1;
} );
}
/* Create an array with the values of all the input boxes in a column */
$.fn.dataTable.ext.order['dom-text'] = function ( settings, col )
{
return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
return $('input', td).val().replace( /,/g, "." ).replace(/\s/g,'') * 1;
} );
}
/* Initialise the table with the required column ordering data types */
$('#extdataEditTableId').DataTable( {
"bDestroy" : true,
"columns": [
null,
{ "orderDataType": "dom-select" },
null,
null,
{ "orderDataType": "dom-select" },
{ "orderDataType": "dom-select" },
{ "orderDataType": "dom-text-numeric" },
{ "orderDataType": "dom-text"},
null
]
} );
}
if(extdisplayPopup == 'true'){
$("#extdataEditTableId").fadeTo(0,0.4);
}
function renderFirstTable(){
document.getElementById("divextdataEditTableId").style.display = "none";
document.getElementById("divextdataTableId").style.display = "block";
var dataTable = $('#extdataTableId').DataTable();
dataTable.clear();
<apex:repeat value="{!existingRowList}" var="i">
dataTable.row.add([
'{!i.Product__r.Name}',
'{!i.OS__c}',
'{!opportunitymarket}',
'{!opportunitycountry}',
'{!i.Quarter__c}',
'{!i.Year__c}',
'{!i.Quantity__c}',
'{!i.Total__c}',
'{!opportunitycurrency}'
]).draw();
</apex:repeat>
}
</script>
</apex:outputPanel>
I want: Is there any possibility to refresh Edit Table with DB list using jquery and render the script panel only, because if I render the table panel it looses it's jquery Datatable property.
You do not need JQuery to do what you are trying to do.
I would suggest you create a class Property in your Extension or Custom Controller class to keep the state of the edit mode:
public with sharing class ExampleExtensionClass {
public Boolean editMode {
get {
if (editMode == null) {
editMode = false;
}
return editMode;
}
set;
}
}
Then in your VF page you can bind a Apex Action Function to a Checkbox onchange event to rerender the table in edit mode:
<apex:page standardController="SObject" extensions="ExampleExtensionClass">
<apex:actionFunction name="rerenderTable" reRender="tablePanel"/>
<apex:inputCheckbox value="{!editMode}" onChange="rerenderTable();"/>
<apex:outputPanel layout="block" id="tabelPanel">
<apex:dataTable value="{!sObjectList}" var="sObjectrecord">
<apex:column>
<apex:outputField value="{!sObjectrecord.Name}" rendered="{!NOT(editMode)}"/>
<apex:inputField value="{!sObjectrecord.Name}" rendered="{!editMode}"/>
</apex:column>
</apex:dataTable>
</apex:outputPanel>
</apex:page>
I solved the problem.
Rendering won't solve the problem as inputfield binds the value and to refresh it there are two ways
Refresh the list in jquery(as no matter you refersh in controller or use any other list it won't leave the value)
copy the data of output field to input field on cancel.
function ResetValues(){
var opptid ="{!opptid}";
result = sforce.connection.query("select id, Country__c,Price_Per_Unit__c, Product__r.Name, Quantity__c, OS__c, Quarter__c, Total__c, Year__c from Shipped_Units__c where opportunity__c = '"+opptid+"'");
records = result.getArray("records");
for (i = 0; i < records.length; i++) {
console.log('records1'+records[i].Quantity__c);
var inpos = i +'-inpOS';
var inpqtr = i +'-inpQtr';
var inpyear = i +'-inpYear';
var inpunit = i +'-inpUnit';
var inptotal = i +'-inpTotal';
var osid=document.getElementById(inpos).childNodes[0];
var qtrid=document.getElementById(inpqtr).childNodes[0];
var yearid=document.getElementById(inpyear).childNodes[0];
var unitid=document.getElementById(inpunit).childNodes[0];
var totalid=document.getElementById(inptotal).childNodes[0];
document.getElementById(osid.id).value=records[i].OS__c;
document.getElementById(qtrid.id).value=records[i].Quarter__c;
document.getElementById(yearid.id).value=records[i].Year__c;
document.getElementById(unitid.id).value=parseInt(records[i].Quantity__c);
document.getElementById(totalid.id).value=parseInt(records[i].Total__c);
}
}
or Similar to below line of code
j$(InpIdmodsp).val(document.getElementById(outsp.id).innerText);
I'm working on a system of medical transportation. Every day I have around 700 trips, so the table is pretty large.
I want the app, after the user adds a trip, the screen is positioned in the newly added trip. (scroll) ,for the user to corroborate the trip successfully added (not my idea, my client wants it that way) . For this, I am sending to the page by parameter the ID of the new trip added.
I'm using a function "fnFindCellRowIndexes" that i found on datatables page, but i can't make it work. The column i wait to search in is index 1.
Here's my code:
<script type="text/javascript">
$(document).ready(function() {
var table = $('#tabla').DataTable({
"deferRender": true,
"language": {
"url": "include/DataTables/Spanish.json"
},
"paging": false,
"ordering": false,
"info": false,
"searching": true,
"columnDefs": [
{
"targets": [ 0 ],
"visible": false,
"searchable": true
},
{
"targets": [ 1 ],
"visible": false,
"searchable": false
}
],
"stateSave": true
});
var index = table.fnFindCellRowIndexes( '<?=$idNuevo?>', 1 );
alert(index);
jQuery.fn.dataTableExt.oApi.fnFindCellRowIndexes = function ( oSettings, sSearch, iColumn )
{
var
i,iLen, j, jLen, val,
aOut = [], aData,
columns = oSettings.aoColumns;
for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ )
{
aData = oSettings.aoData[i]._aData;
if ( iColumn === undefined )
{
for ( j=0, jLen=columns.length ; j<jLen ; j++ )
{
val = this.fnGetData(i, j);
if ( val == sSearch )
{
aOut.push( i );
}
}
}
else if (this.fnGetData(i, iColumn) == sSearch )
{
aOut.push( i );
}
}
return aOut;
};
</script>
I'm getting error "fnFindCellRowIndexes is not a function"
Can anyone help me? if anyone has any idea to do it in a better way, suggestions are accepted.
Declare fnFindCellRowIndexes before you instantiate your dataTable!
You must instantiate with dataTable(). fnFindCellRowIndexes is an oldschool none-API plugin. As far as I can see in your code, you should not have problems with that. If you still want to use the new API, you can always use table.api().<api-functions>
The PHP variable does not magically echo itself out (no offense :-) - you forget to actually print it :
var index = table.fnFindCellRowIndexes( '<? echo $idNuevo ?>', 1 );
Remember that fnFindCellRowIndexes is an equal / == search. If you search for 1 in column #1 it only return columns that hold the value 1 and nothing more, not rows holding 10, 101, 1.1 etc.
I've implemented a JQGrid table with loadonce:true like this :
jQuery("#list").jqGrid({
datatype: 'jsonstring',
datastr : maVarJSON,
colNames:['AA','BB', 'CC','DD','EE','FF'],
colModel :[
{name:'invid', index:'invid', align:'center'},
{name:'invdate', index:'invdate'},
{name:'amount', index:'amount', align:'right'},
{name:'tax', index:'tax', align:'right'},
{name:'total', index:'total', align:'right'},
{name:'note', index:'note'}
],
pager: jQuery('#pager'),
rowNum: 50,
rowList: [50, 100],
caption: '',
height: 470,
width: 1000,
loadonce: true
});
jQuery("#list").jqGrid('filterToolbar',{afterSearch: function(){
var rowsFiltered = jQuery("#list").getRowData();
}});
My problem is :
I have 500 rows in maVarJSON. I see 50 rows and 10 pages. I decide to filter my column AA. Only 100 rows accept this filter. So, I see 50 rows and 2 pages.
I would get the 100 rows data. (The method jQuery("#list").getRowData() give me only the 50 first rows data.)
Thanks
You will push only the searched for rows across all pages to the obj.items object:
var obj = new Object();
var numpages = jQuery(id).getGridParam('lastpage');
obj.items = new Array();
var realname = id.split("_");
realname = "input_jqGridPager_" + realname[1];
var curpage = jQuery('#'+realname);
curpage = curpage.children('input');
curpage = curpage[0].value;
for (var i = 1; i <= numpages; i++)
{
jQuery(id).trigger("reloadGrid",[{page:i}]);
selRowIds = jQuery(id).jqGrid ('getRowData');
obj.count = selRowIds.length;
for(elem in selRowIds) {
obj.items.push(selRowIds[elem]);
}
}
jQuery(id).trigger("reloadGrid",[{page:curpage}]);
The method getRowData get the data from the current page only. If you need get all the grid data you can use getGridParam to get 'data' parameters and get all grid data. I don't really understand what you want to do with the data inside of afterSearch callback. The goal of filterToolbar to display the data for the user and not to get you JavaScript interface to filter some JavaScript data.
By the way you can remove caption: '' option which is default, remove loadonce: true which will be ignored for local data inclusive datatype: 'jsonstring' and replace pager: jQuery('#pager') option to pager: '#pager'. If you would use pager: jQuery('#pager') jqGrid will have to convert it to pager: '#pager' itself internally.
I am using datatables in my application. Whenever user click on any row I want to highlight it and pick some values from selected row.
"oTableTools": {
"sRowSelect": "single",
"fnRowSelected": function ( node ) {
var s=$(node).children();
alert("Selected Row : " + $s[0]);
}
I tried sRowSelect and fnRowSelected but no luck. The row is not highlighted and neither fnRowSelected is called. Even no error on console.
Here is my complete code
var userTable = $('#users').dataTable({
"bPaginate": true,
"bScrollCollapse": true,
"iDisplayLength": 10,
"bFilter": false,
"bJQueryUI": true,
"sPaginationType": "full_numbers",
"oLanguage": {
"sLengthMenu": "Display _MENU_ records per page",
"sZeroRecords": "Enter a string and click on search",
"sInfo": "Showing _START_ to _END_ of _TOTAL_ results",
"sInfoEmpty": "Showing 0 to 0 of 0 results",
"sInfoFiltered": "(filtered from _MAX_ total results)"
},
"aaSorting": [[ 0, "asc" ]],
"aoColumns": [/* Name */ null,
/*Institution*/null,
/*Email*/null],
"oTableTools": {
"sRowSelect": "single",
"fnRowSelected": function ( node ) {
alert("Clicked");
}
}
});
Am I missing anything ?
EDIT:
Now able to highlight selected row.Added class="display" to HTML table. Still wondering why I didn't find this in datatable docs. Now looking how to collect selected values.
Here is how I do it
just add this function to your page (if users is your table id)
$("#users tbody").delegate("tr", "click", function() {
var iPos = userTable.fnGetPosition( this );
if(iPos!=null){
//couple of example on what can be done with the clicked row...
var aData = userTable.fnGetData( iPos );//get data of the clicked row
var iId = aData[1];//get column data of the row
userTable.fnDeleteRow(iPos);//delete row
}
When you are using fnRowSelected (i.e. when creating new tabletool) you have to use
"sRowSelect": "multi",
That will resolve the issue. Please increment my comment count if it helps. I need to have more points.
I used it in my code as follows
pqrtbl = new TableTools(NameOfTbl, { "sRowSelect": "multi",
"fnRowSelected": function ( node ) {
var s= $(node).children();
fnAddToSelLst(s[1].innerText);
},.......................
//column index depend upon your req.
The selected class should be, Within your function you used $s and you define var s which is not the same var.
"oTableTools": {
"sSelectedClass": "yourclassname",
"sRowSelect": "single",
"fnRowSelected": function ( node ) {
var s=$(node).children();
alert("Selected Row : " + s[0]);
}
}
If you wanna select multiple row, wanna get the data of selected row for ajax purpose check this
http://jsfiddle.net/ezospama/1/
DataTable code will be as follows
$(document).ready(function() {
var table = $('#datatable').DataTable();
$('#datatable tbody').on( 'click', 'tr', function (){
$(this).toggleClass('selected');
} );
$('#btn').click( function () {
console.log(table.rows('.selected').data());
alert("Check the console for selected data");
} );
})