I have to change in one function, after the initialization of a datatable, bSearchable property of a column. I need first to enable and then disable it.
I found an example for visibility:
$(document).ready(function() {
var table = $('#example').DataTable( {
"scrollY": "200px",
"paging": false
} );
$('a.toggle-vis').on( 'click', function (e) {
e.preventDefault();
// Get the column API object
var column = table.column( $(this).attr('data-column') );
// Toggle the visibility
column.visible( ! column.visible() );
} );
} );
Can something similar be used also in my case? Something like column.seachable?
This is an old question, but one that cost me several hours to research the answer to... mostly based on my lack of JS skill though.
The usecase was that I have a table with an ID column that is a GUID. This Id is seldom used uses a lot of space, so it's hidden and not searchable by default. But for internal users who might have access to logs or the database, we need to be able to search the ID column as well.
I added a checkbox for these users and it should change visibility and the searchable attribute of the ID column.
My solution is based on another question regarding searching on columns. But in this question, the search was only intended on one single column and not on all searchable columns as well (normal DataTable.search() API). Sadly, to change the searchable property, there seems to be no public API. If you change the searchable property, you have to invalidate the data in the table afterwards, otherwise the columns data will still be / not be present in the tables aoFilterData. This forces the table to reload the data from the datasource (in this case, the DOM).
I had a lot of problems with registering the eventhandlers at the right place. The filter field is not present at the first draw event of the table, so i had to register the handlers in the init event that is fired after the table is fully initialized.
var userTable;
var idSearchCbx;
var searchField;
$(document).ready(function () {
userTable = document.getElementById("table-users");
if (userTable) {
userTable = $("#table-users").DataTable(
{
"columnDefs": [
{
//First column invisible and not searchable by default
"targets": [0], //first column = ID
"visible": false,
"searchable": false
}],
//Other initialization options
); //Table creation
userTable.on("init",
function () {
$("input[type='search']").on("change cut input keypress keyup paste search recheck",
function () {
var searchValue = $(this).val();
userTable.search(searchValue).draw();
//width attribute is calculated and added to the table
//it loses 2 pixels everytime the checkbox is checked/
//unchecked somehow - so delete it
document.getElementById("table-users").removeAttribute("style");
});
idSearchCbx = $("#cbx-search-id");
idSearchCbx.on("change",
function () {
if (this.checked === true) {
//this makes the first column searchable, not official API
userTable.context[0].aoColumns[0].bSearchable = true;
//make it visible as well, official API
userTable.columns(0).visible(true);
//invalidates cached table data so that the column values are
//added to the filterdata
userTable.rows().invalidate().draw();
} else {
userTable.context[0].aoColumns[0].bSearchable = false;
userTable.columns(0).visible(false);
userTable.rows().invalidate().draw();
}
//trigger the normal search again so that the
//filter is / is not applied to the first column
$("input[type='search']").trigger("recheck");
});
}); //DT on init
} //table present
});//document ready
I assume context is related to settings(), so keep in mind that names in the context might change and this is most likely not version-stable even in minor releases. But I didn't find any other way. Hope it helps someone.
Related
I'm trying to filter a datatable by setting the search input value to what I want to find:
document.querySelector("#searchinput").value = $whatiwant;
The value is being set successfully, but it doesn't affect the datatable results. I tried to submit it (but it isn't a form, so it did't work) and to simulate the enter key press (but it didn't work either and didn't return any errors). I also tried to use the DataTables filter function, but nothing seems to happen.
After all, what can I do to search/filter a datatable?
You can use Datatables API search()
The global search is performed across all searchable columns
link: search()
Example snippet code:
var table = $('#example').DataTable();
// #myInput is a <input type="text"> element
$('#myInput').on( 'keyup', function () {
table.search( this.value ).draw();
} );
Or use API column().search() for specific column
provides the ability to search globally across the table, this method,
and its plural counterpart, provide the ability to search for data on
a specific column.
link: column().search()
var table = $('#example').DataTable();
// #column3_search is a <input type="text"> element
$('#column3_search').on( 'keyup', function () {
table
.columns( 3 )
.search( this.value )
.draw();
} );
Did you set searching:false in datatable options? you can set searching enable and disable from that option.
datatables searching
You can enable searching by coding as follows. by doing this you don't need to add a separate input to search in datatable.
$('#example').dataTable( {
"searching": true
} );
This is a problem I had with jQuery Datatables that I really don't know why it is happening in the first place!
I have multiple select elements which all filters the original data set. I do the filtering logic on the select change event.
This my Datatables init (using state saving, from the documentation) :
var table = $('#orders-listing').DataTable({
bStateSave: true,
bFilter:true,
paging: true,
bPaginate:true,
language: { url: /* Language File URL */ },
fnStateSave: function(oSettings, oData){
localStorage.setItem('DataTables_'+window.location.pathname, JSON.stringify(oData));
},
fnStateLoad: function(oSettings){
return JSON.parse(localStorage.getItem('DataTables_'+window.location.pathname));
}
});
And this is my filtering logic on the select change event:
$('.filter-select').on('change', function() {
$.fn.dataTable.ext.afnFiltering.push(
function(settings, data, dataIndex) {
// Some logic, return a boolean, wether we keep the row being processed or not.
}
);
table.draw();
$.fn.dataTable.ext.afnFiltering.pop();
});
Now, the filtering works fine. The rows, pagination links, everything changes accordingly.
But, once I click on the 2nd link on the pagination links, the original dataset returns.
Example: I had 200 rows in the first place, after filtering, it was reduced to 150 (So 50 rows were filtered, and removed from the original dataset), then once I click on the second link on the pagination, the original dataset returns, with the first 200 rows.
What am I missing here ? What is causing the original dataset to return when paginating ?
Any help is greatly appreciated. Thanks.
You're doing $.fn.dataTable.ext.afnFiltering.pop() immediately after drawing the table with draw() which removes your custom filter and it will no longer be applied if table is sorted, page is changed, etc.
Try adding $.fn.dataTable.ext.afnFiltering.pop() before $.fn.dataTable.ext.afnFiltering.push() to remove previous custom filter only on filter change but before adding a new filter.
I have a web application that uses ExtJS 4 that incorporates a Ext.grid.EditorGridPanel.
One of the columns of the Ext.grid.EditorGridPanel has a combobox editor that I would like to disable programmatically when the store loads based on the value of another field in the store.
It seems like this should be pretty simple - but so far nothing seems to work.
When the Grid's store loads, I have a listener to check each row and disable the combobox in index 4 depending on the value of another field.
The only thing that I can't get to work is actually disabling the combobox.
Any suggestions?
Here is the psuedo-code. Thanks in advance
listeners: {
'load': function(st, records, options) {
var view = getMyEditorGridPanel().getView();
for (var i = 0; i < this.getCount(); i++) {
if (store.getAt(i).get('setDisabled') === 'Y') {
//The cell at index 4 has a combobox editor - I CAN'T GET IT TO DISABLE!!
view.getCell(i,4).setDisabled(true);
}
}
}
From my point of view you have two different things you need to manage here:
Cell Styling, the way a cell looks when not being edited (either is enabled or disabled)
Editor Availability, how to react when a cell is about to be edited (should be possible to edit the cell)
Cell Styling
For the first one I would advice to provide a style to each cell in order to make it look disabled, this can be achieved during rendering time instead trying to do it when the store loads (btw nothing ensures you that the grid items have been fully rendered just after getting the load event callback). You can return a custom class per row by providing an implementation to Ext.grid.ViewView.getRowClass
viewConfig: {
getRowClass: function(record, rowIndex, rowParams, store) {
return record.get("disabled") ? "mail-disabled" : "";
}
}
Editor Availability
You will also need to handle the Ext.grid.plugin.CellEditingView.beforeedit event and provide a custom logic to determine when the editor will be available
plugins: [
Ext.create('Ext.grid.plugin.CellEditing', {
clicksToEdit: 1,
listeners: {
beforeedit: function(editor, e, eOpts) {
return e.record.get("disabled") == false;
}
}
})]
You can find a working example of both solutions here, hope it helps to solve your problem.
Im moving rows between tables, it seems to works fine but once the row is in the other table all javascript functions related to that row no longer work and I have no idea why.
The javascript is pretty straight forward I take the html for the row and move it into the other table.
If you click the child tabs they work fine, but click on waitlist (or approve to move to the table above) to move it to the below table and the tabs for that row no longer work.
The weird thing is no error is thrown, and nothing is logged in the console.
http://jsfiddle.net/Ha3Jq/16/
Jquery
$( ".enrolled-participants" ).on("click","button.remove-participant",function(){
if($(this).hasClass('remove-participant'))
{
$(this).html('Approve');
$(this).removeClass('remove-participant').addClass('add-participant');
var className = $(this).closest('tr').attr('class');
var childClass =$(this).closest('tr').next().attr('class');
var current_row = $(this).closest('tr').html();
var child_row = $(this).closest('tr').next().html();
$(this).closest('tr').next().remove();
$(this).closest('tr').remove();
$('.waitlisted > tbody:last').append('<tr class="'+className+'">'+current_row+'</tr><tr class="'+childClass+'">'+child_row+'</tr>');
}
Im also using the table sorter plugin.
tablesorter
$(".enrolled-participants,.waitlisted")
.tablesorter({
theme : 'blue',
// this is the default setting
cssChildRow: "tablesorter-childRow",
// initialize zebra and filter widgets
widgets: ["zebra", "filter"],
widgetOptions: {
// include child row content while filtering, if true
filter_childRows : true,
// class name applied to filter row and each input
filter_cssFilter : 'tablesorter-filter',
// search from beginning
filter_startsWith : false,
// Set this option to false to make the searches case sensitive
filter_ignoreCase : true
}
});
// hide child rows
//$('.tablesorter-childRow td').hide();
// Toggle child row content (td), not hiding the row since we are using rowspan
// Using delegate because the pager plugin rebuilds the table after each page change
// "delegate" works in jQuery 1.4.2+; use "live" back to v1.3; for older jQuery - SOL
$('.tablesorter').delegate('.toggle', 'click' ,function(){
//alert('ok');
// use "nextUntil" to toggle multiple child rows
// toggle table cells instead of the row
$(this).closest('tr').nextUntil('tr:not(.tablesorter-childRow)').find('td').toggle();
return false;
});
// Toggle widgetFilterChildRows option
$('button.toggle-option').click(function(){
var c = $('.tablesorter')[0].config.widgetOptions,
o = !c.filter_childRows;
c.filter_childRows = o;
$('.state').html(o.toString());
// update filter; include false parameter to force a new search
$('input.tablesorter-filter').trigger('search', false);
return false;
});
Use detach instead of remove.
remove removes it from the DOM, and it removes all of the (JavaScript) event listeners.
detach simply removes it from the DOM; the event listeners are left intact.
I am working with some custom ajax functionality using Telerik's MVC Grid and I am trying to hide/remove child elements of a cell based on specific criteria, I found a similar question here: Telerik MVC Grid making a Column Red Color based on Other Column Value but couldn't get it working right.
Basically when the row is databound in the grid this event fires:
function onRowDataBound(e) {
if (e.dataItem.Status == "Submitted") {
$.each(e.row.cells, function (index, column) {
alert(column.innerHTML);
//var $header = $(column).closest('table').find('th').eq($(column).index());
//if(header text == "Actions)
//{
//Get the <a> child elements in the 'Actions' column whose class contains t-grid-Edit,
//t-grid-edit, t-grid-Delete, or t-grid-delete and set their display to none, add a css class, and remove the element entirely
//}
}
}
}
So far it's working in that I can get and iterate through each column in the row, but I am not sure what to do at this point, I found this How can I get the corresponding table header (th) from a table cell (td)? to check to make sure the column name name is Actions, but I couldn't get it working. I am not sure how to convert the javascript HTMLTableCellElement object into a jQuery object so I can use syntax I am more familiar with.
Here is what I need to do after that:
Get the child elements in the 'Actions' (has to go by column header name instead of cell index because the number of columns can change) column whose class
contains t-grid-Edit, t-grid-edit, t-grid-Delete, or t-grid-delete
Take those elements and (each of these actions would be used on different pages using similar setups):
a. Set the element's display style to none
b. Add a class to the element of name "Hidden"
c. Remove the element from the code entirely
How can I put the above functionality into my onRowDataBound function?
Thank you SO =).
I was able to figure this out with a lot of playing:
function onRowDataBound(e) {
if(e.dataItem.Status == "Submitted"){
var $row = $(e.row);
$.each($row.children("td"), function (index, column) {
var $column = $(column);
var $headerText = $column.closest('table').find('th').eq($column.index()).children(".t-link").text();
if ($headerText == "Actions") {
$.each($column.children("a.t-grid-delete, a.t-grid-Edit"), function (subIndex, link) {
$(link).remove();
});
}
});
}
}