After doing some research on this issue trying to find a solution (unfortunately to no avail) I decided that it might be best to post my problem. I currently have a Datatable containing asset information on a view and I'm trying to prevent a user from continuing change an option on a select field until an asset is added to the asset table.
Listed below is my assets datatable code in my .js file under the document.ready function
assets = $('#assets').dataTable({
sAjaxSource: "http://" + window.location.hostname + "/request/get-request-assets/?id=" + $('#id').val(),
fnDrawCallback: function (oSettings) {
setIncompleteTD();
enableRequestStatus();
},
scrollY: '185px',
scrollCollapse: true,
paging: false,
aaSorting: [[1, 'asc']],
bPaginate: false,
bFilter: false,
bLengthChange: false,
bAutoWidth: false,
bInfo: false,
aoColumns: [
{sWidth: '35px', bSortable: false},
{sWidth: '40px'},
{},
{},
{},
{},
{},
{sWidth: '80px'}
],
language: {
sLoadingRecords: '',
sEmptyTable: 'This request has no asset records.',
sInfoEmpty: ''
}
I've found table.fnSettings().aoData.length===0 as a means to check if a table is empty. However, after stepping through the code (via Chrome debugger) it seems Datatables (at least in my case) calls the function before the table is fully generated...
I have this code below
assetPresent = (assets.fnSettings().aoData.length===0) ? false : true;
console.log(assetPresent);
in my document.ready function after $('#assets').dataTable() function (if this matters). AssetPresent will be used as a flag to toggle the status select box. Unfortunately before I can utilize that...
console.log(assetPresent);
Seems to always be set to false even if there are clearly records in the table, and...
assetPresent = (assets.fnSettings().aoData.length===0) ? false : true;
Tends to be ignored...
I'm curious to see if table.fnSettings().aoData.length===0 might not be the best option. Thank you in advance.
Have you tried, table.data().length yet?
you can try this
var table = $('#assets').DataTable();
if ( ! table.data().any() ) {
alert( 'Empty table' );
}
Related
I am using Angular-Slickgrid in my angular application.
Grid is working fine but I am facing issue with Headermenu.
When I run the application unable to see Headermenu icon on mousehover in any header.
I am using below gridoptions :
this.gridOptions = {
enableAutoResize: true,
enableCellNavigation: true,
autoEdit: false,
enableRowSelection: true,
rowHeight: 30,
editable: true,
enableGrouping: true,
forceFitColumns: true,
enableHeaderButton: true,
enableHeaderMenu: true,
gridMenu: {
hideExportCsvCommand: true,
hideExportTextDelimitedCommand: true,
hideExportExcelCommand: true,
hideClearAllSortingCommand: true,
hideForceFitButton: true,
onBeforeMenuShow: (a, b) => {
}
}
};
As you can see I have set enableHeaderMenu: true, even after this unable to see the header menu.
Below is the image my grid look like:
When I mousehover on any header unable to see header menu icon(on which I need to click to open the header menu)
I have added the reference of required css files also and I think css is working.
Below is code of angular.json file:
"styles": [
"src/styles.scss",
"./node_modules/font-awesome/css/font-awesome.css",
"./node_modules/bootstrap/dist/css/bootstrap.css",
"./node_modules/flatpickr/dist/flatpickr.css",
"./node_modules/#fortawesome/fontawesome-free-webfonts/css/fontawesome.css",
"./node_modules/#fortawesome/fontawesome-free-webfonts/css/fa-regular.css",
"./node_modules/#fortawesome/fontawesome-free-webfonts/css/fa-brands.css",
"./node_modules/#fortawesome/fontawesome-free-webfonts/css/fa-solid.css",
"src/slickgrid-styles.scss",
"./node_modules/angular-slickgrid/lib/multiple-select/multiple-select.css"
],
"scripts": [
"./node_modules/jquery/dist/jquery.js",
"./node_modules/jquery-ui-dist/jquery-ui.min.js",
"./node_modules/slickgrid/lib/jquery.event.drag-2.3.0.js",
"./node_modules/bootstrap/dist/js/bootstrap.js",
"./node_modules/angular-slickgrid/lib/multiple-select/multiple-select.js"
]
code of slickgrid-styles.scss file :
#import './node_modules/angular-slickgrid/styles/sass/slickgrid-theme-bootstrap.scss';
After investigatng my code finally I found the route cause for the issue.
I am using 12 columns in my grid out of which I want to display only some columns on page load say 9 columns(user can the check the column from grid menu to make visible).For this purpose I am using below code:
setGridDefaultVisibleColumns() {
const visibleColumns = this.columnDefs.filter((c) => {
return c['visible'] !== false;
});
this.angularSilkGrid.slickGrid.setColumns(visibleColumns); }
I am calling this method in angularGridReady
angularGridReady(angularGrid: AngularGridInstance) {
this.dataGrid = angularGrid.slickGrid;
this.angularSilkGrid = angularGrid;
this.setGridDefaultVisibleColumns();
}
After commenting the setGridDefaultVisibleColumns function call my issue is resolved
Below is the workaround for the issue.setColumns method of slick gird is also affecting the headermenu.
I can hide the column like below without affecting the headermenu.See the below code
setGridDefaultVisibleColumns() {
this.columnDefs.forEach(c => {
if (c['visible'] === false) {
this.angularSilkGrid.extensionService.hideColumn(c);
}
}); this.angularSilkGrid.slickGrid.setColumns(visibleColumns);
}
I have the following problem. I've written a server and client scripts for node js that work as live collaboration code editing. 2 or more people can code in the same instance of CodeMirror editor. Until i have enabled autocomplete feature and auto closing brackets it was working perfect, but after i did it messed up the work. When you use autocomplete list or when bracket or tag will be closed by module not by you manually it will not be recognized as change. I have inspected an object that CodeMirror instance is returning and it doesnt contain change that have been done automatically. its not even strictly problem for node js beacuse if you want lets say, send changes to server via ajax and save in a file, it wont happen beacuse its not present in change object. Anyone had similiar problem and can help?
client code:
var appCM = CodeMirror.fromTextArea(document.getElementById('app-cm'), {
mode: 'text/html',
theme: "monokai",
styleActiveLine: true,
lineNumbers: true,
matchBrackets: true,
indentUnit: 4,
indentWithTabs: true,
autoCloseTags: true,
autoCloseBrackets: true,
matchTags: false,
extraKeys: {
"Ctrl-Space": "autocomplete",
"Ctrl-Q": function(appCM) {
appCM.foldCode(appCM.getCursor());
}
},
foldGutter: true,
gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
readOnly: access
});
appCM.on('change', function(i, op) {
socket.emit('change', op);
});
socket.on('change', function(data) {
appCM.replaceRange(data.text, data.from, data.to);
});
server code:
socket.on('change', function(op) {
if(op.origin === '+input' || op.origin === 'paste' || op.origin === '+delete') {
clients.forEach(function(client) {
if(client !== socket)
client.emit('change', op);
});
};
});
You are explicitly filtering out changes whose origin isn't one of input/paste/delete. Why are you doing that? You'll need to propagate all changes if you want peers to stay in sync.
JQuery dataTables are used extensively in our web app, and usually they don't give a problem. But there's this one that has this bug where during the execution of fnReloadAjax, it gives the error "TypeError: k is undefined", which is coming from the dataTables.js line where "fnServerData:function(e,j,m,k)" occurs. Here's the dataTable definition:
url = '?p=user.creation_rules_browser&page_action=getData';
data_table = jQuery('#data').dataTable({
bJQueryUI: true,
sDom: '<"template-box"fl><"template-box"ip><"template-box"r><"ui-widget ui-widget-content ui-helper-clearfix ui-corner-all template-box" t><"template-box"p<"toolbar">>',
sAjaxSource: url,
bPaginate: false,
bProcessing: true,
bAutoWidth: false,
bSort:false,
bFilter:false,
bInfo:false,
aoColumns: [
{ "bSortable": false },
{ "bSortable": false },
{ "bSortable": false },
{ "bSortable": false },
{ "bSortable": false },
{ "bSortable": false },
{ "bSortable": false }
]
} );
It loads up perfectly, but there's a column with an action menu that lets you edit the row. This pops up a jQuery Dialog which executes the following when you hit "Save":
jQuery.getJSON('index.php',{
p: "user.creation_rules_browser",
page_action: "edit_rule",
rule_name: rule_name_val,
target_field: $('#input_target_field').val(),
action_value: action_value_val,
action_set_to_blank: action_set_to_blank_val,
id: data.id
}, function (json) {
if (json.error) {
Dialog.alert({title: "Error Saving Rule"}, json.error);
} else {
jQuery(self).dialog('close');
url = 'index.php?p=user.creation_rules_browser&page_action=getData';
data_table.fnReloadAjax(url);
}
}
The Save actually works, but the dataTable doesn't get reloaded because of that error. It should go back to that url and "getData" and reload, but it gets stuck in fnServerData because k is undefined. This k corresponds to oSettings in the non-min fnServerData declaration, but I've done a console.log and verified that fnGetSettings returns the expected copy of oSettings. Originally, url wasn't being passed in the call to fnReloadAjax, so I thought that might be a problem and added it in, but got the same result.
So I don't get why it's undefined. I guess my next step would be to use the non-min version of dataTables.js, and add some debugging in there, but I'm hoping somebody here will find some simple thing that's being done wrong in the code.
Never mind, I found where obsolete versions of dataTables and fnReloadAjax were being loaded in addition to the current versions. Taking that out fixed it.
I have a jQuery Datatable with 3 headers. One header contains two radio buttons, another header contains a select box. By default, one of the options is checked.
When I use the search function in the Datatable to search for specific records, it does not display which radio button was checked. I inspected the DOM after I used the datatable search, and the input element still contains the CHECKED attribute. The select box is not affected. It still retains the value of the select box.
Also, IE behaves fine. O_o FF and Chrome are not recognizing the checked value.
I tried a $(selector).datatable().fnDraw();... no dice.
How do I get the datatable to recognize the checked attribute after, or during, the search? Has anyone experienced something similar?
Any help is appreciated. Thanks.
Edit: After further investigation, it looks like the fnDraw is clearing the value of the radio button.
Code
Initialize datatable (Javascript)
$.get('store_handler.ashx', { cmd: '9', pubId: pubId, sub: sub }, function(o) {
$("#researchTableDiv").html(o.datatableContent);
$('#ResearchTable').dataTable({
"bJQueryUI": true,
"bPaginate": false,
"sScrollY": "450px",
"bSort": false
});
if (o.radioCheck == "single")
$('#radioSingle').attr("checked", "checked");
else
$('#radioSub').attr("checked", "checked");
}, "json");
HTML of datatable headers (C# .Net)
htmlString.Append("<thead>");
htmlString.Append("<tr>");
htmlString.Append("<th valign=\"middle\" style=\"width: 200px; text-align: left;valign:top;border-right:0px;padding-bottom:0px\" class=\"header\">Filter: ");
htmlString.Append("<select name=\"nonSort2\" style=\"height:20px;padding:0px;margin-top:-0px;font-size:11px\">");
htmlString.Append("<option value=\"AKLPH\">All</option>");
htmlString.Append("<option value=\"-\">---------------</option>");
htmlString.Append("<option value=\"AK\">Alaska</option>");
htmlString.Append("<option value=\"AL\">Etc...</option>");
htmlString.Append("</select>");
htmlString.Append("</th>");
htmlString.Append("<th align=\"left\" class=\"header\" >");
if (sub == "0")
{
htmlString.Append("<input type=\"radio\" value=\"0\" name=\"rdoSubscription\" id=\"radioSingle\" checked=\"CHECKED\" style=\"margin-left:1px\"/>Single Report");
htmlString.Append("<input type=\"radio\" value=\"1\" name=\"rdoSubscription\" id=\"radioSub\" onclick=\"getPubDetails('" + pubId + "','1');\" style=\"margin-left:1px\"/>Subscription");
jOut.Put("radioCheck", "single");
}
else
{
htmlString.Append("<input type=\"radio\" value=\"0\" name=\"rdoSubscription\" id=\"radioSingle\" onclick=\"getPubDetails('" + pubId + "','0');\" style=\"margin-left:1px\"/>Single Report");
htmlString.Append("<input type=\"radio\" value=\"1\" name=\"rdoSubscription\" id=\"radioSub\" checked=\"CHECKED\" style=\"margin-left:1px\"/>Subscription");
jOut.Put("radioCheck", "sub");
}
htmlString.Append("</th>");
htmlString.Append("<th class=\"header\" align=\"center\">Action</th>");
htmlString.Append("</tr>");
htmlString.Append("</thead>");
Try setting the radio button after the draw event:
$.get('store_handler.ashx', { cmd: '9', pubId: pubId, sub: sub }, function(o) {
$("#researchTableDiv").html(o.datatableContent);
$('#ResearchTable').dataTable({
"bJQueryUI": true,
"bPaginate": false,
"sScrollY": "450px",
"bSort": false,
"fnDrawCallback": function() {
if (o.radioCheck == "single")
$('#radioSingle').attr("checked", "checked");
else
$('#radioSub').attr("checked", "checked");
}
}
});
}, "json");
I just had a similar problem, and solved it by reading the issue in red on this link. Maybe it can help you, maybe not, but hopefully it can.
I build a lot of DataTables in my applications, but it seems like in a way you're attempting to "brute force" a server side solution. Technically, what you're doing is a dom-based table because you're outputting HTML and having DataTables format it, though it appears from the $.get that you could be trying to leverage a server-side solution. Server side is actually far more efficient because the server is limiting what it sends to the jQuery and lessening the need to deal with hundreds (or in my case millions) of records at once. Obviously, it's also faster to take a raw json stream and build a table rather than having to traverse dom structure to get the same information.
I'd suggest trying a true server side solution.....for the sole reason that the data comes straight from your server-side technology of choice and doesn't get heavily manipulated as it obviously is here. So, first, setup your a file (perhaps your store_handler.ashx) to output what you need in JSON (the most efficient transfer method for this operation) The string should look something like this:
{"sEcho": 1, "iTotalRecords": 1, "iTotalDisplayRecords": 1, "aaData":[["one", "for", "each", "column"]]}
Make sure when doing this that you get your JSON outputting to screen first, and test it to ensure validity via jsonlint.com
Then, the jQuery would look something like this:
$('#detailstable').dataTable( {
"aaSorting": [[ 1, "asc" ]],
"bProcessing": true,
"bServerSide": true,
"sAjaxSource": "handler.ashx",
"bJQueryUI": true,
"sPaginationType": "full_numbers",
"bAutoWidth": false,
"bLengthChange": true,
"bPaginate": true,
"bSort": true,
"iDisplayLength": 10,
"bInfo": true,
"aoColumns": [
{ "sTitle": "One", "sWidth": "15%" , "sClass":"center"},
{ "sTitle": "For", "sWidth": "15%" , "sClass":"center"},
{ "sTitle": "Each", "sWidth": "15%", "sClass":"center" },
{ "sTitle": "Column", "sWidth": "15%" , "sClass":"center"}
],
"fnServerData": function ( sSource, aoData, fnCallback ) {
var something = $('#something').val();
var somethingelse = $('#somethingelse').val();
aoData.push( { "name": "something", "value": something },
{ "name": "somethingelse", "value": somethingelse }
);
$.ajax( {
"dataType": 'json',
"type": "POST",
"url": sSource,
"data": aoData,
"success": fnCallback
} );
}
});
-- edit --
I added the fnServerData section which is a callback that sends data to the query. In the example given, it will make the variables something and somethingelse available in a $_REQUEST string to be used in the query. You could use this to get the values of the selected fields back to the query to give you results.
-- edit --
Now, for the searching, you would have to add some elements to your source page to handle sorting/filtering/searching/etc. This is a lot simpler than it sounds...each variable is passed via a $_REQUEST variable. Check the tutorial online for an example of what comes in and how to sort on it. Yes, the tutorial is in PHP, but the important part is figuring what values it's passing you and from that you can build your query accordingly. Ignore the PHP specific elements of the tut. We can help you out if it's still confusing.
Voila...more efficient, less confusing, and doing nearly exactly what you're talking about works in my applications without a problem. No javascript voodoo required.
I have a grid constructed with jqGrid, that uses the search toolbar, a custom formatter to insert radio boxes and a loadComplete handler.
Everything works fine in FF but when I go to IE8 (shame!!!) the screen would freeze with the data loaded and the Loading... box on the screen. I can do nothing on the screen.
Here is my code:
function loadCompleteHandler(){
jQuery("#listTable").jqGrid('setGridHeight', Math.min(300,parseInt(jQuery(".ui-jqgrid-btable").css('height'))));
}
function radio(value, options, rowObject){
var radio = '<input type="radio" value=' + value + ' name="radioid" ondblclick="inDetail();"/>';
return radio;
}
function statusSelect(){
#set($select = ":$l10n.lbl_123")
#foreach($se in $status_list)
#set($select = $select + ";$se.getValue():$se.getValue()")
#end
return "$select";
}
jQuery(function(){
jQuery("#listTable").jqGrid({
url: '$content.getURI("/servlet/ajax/MyServlet.json")' + '?loggedUserId=$loggedUserId&pageNo=0&locale=' + '$l10n.getLocale().toString()',
datatype: 'json',
mtype: 'POST',
colNames:['','$l10n.lbl_copy','$l10n.lbl_476','$l10n.lbl_380', '$l10n.lbl_2547<br/>$l10n.lbl_3768','$l10n.lbl_owner','$l10n.lbl_256 $l10n.lbl_92','$l10n.lbl_1558<br>$l10n.lbl_185','$l10n.lbl_348'],
colModel :[
{name:'column1', index:'column1', width:'3%', search:false, align:'center', formatter: radio, editable:false, sortable: false, resizable:false},
{name:'column2', index:'column2', width:'6%', search:false, align:'center', formatter:'checkbox', sortable: false, resizable:false},
{name:'column3', index:'column3', width:'12%', sortable: false, stype:'select', editoptions:{value: statusSelect()}, resizable:false},
{name:'column4', index:'column4', width:'17%', search:false, sortable: false, resizable:false},
{name:'column5', index:'column5', width:'10%', search:false, sortable: false, resizable:false},
{name:'column6', index:'column6', width:'13%', sortable: false, resizable:false},
{name:'column7', index:'column7', width:'13%', sortable: false, resizable:false},
{name:'column8', index:'column8', width:'12%', sortable: false, resizable:false},
{name:'column9', index:'column9', width:'14%', sortable: false, resizable:false}
],
width:'768',
height: 300,
loadonce:true,
pager: '#pagerDiv',
gridview: true,
rowNum:15,
rowTotal: 500,
sortorder: 'desc',
viewrecords: true,
loadComplete: loadCompleteHandler
});
});
jQuery(function(){
jQuery("#listTable").jqGrid('filterToolbar',{
stringResult: true,
searchOnEnter: false,
defaultSearch:'cn'}); /* search strategy meaning: contains */
});
I am using Velocity, jQuery 1.4.2. IE gives an invalid argument error in the jQuery library
at this line:
if ( set ) {
style[ name ] = value;
}
Maybe the problem is with jQuery in IE8, I don't know....
EDIT : more specific data added
I am using jqGrid 3.8.2.
The statusSelect after Velocity has processed it looks like this:
function statusSelect(){
return ":All;status1:status1;status2:status2";
}
I think there is no problem with the JSON data transfer since the grid previously worked in IE8 when there was no setGridHeight, loadComplete handler. I have also done some minor modifications which I can only partially recount (i.e. column resize disabled).
For testing purposes here is a JSON object:
{
"page":"1",
"records":2,
"rows":[{"id":150,"cell":[150,false,"status1","columnData4","columndata5","columndata6","columndata7","Test1\u003cbr/\u003e\u003cspan style\u003d\u0027float:right;\u0027\u003e10.12.2010\u003c/span\u003e","columnData"]},
{"id":157,"cell":[157,false,"status2","columnData41","columndata51","columnData61","columnData71","Test2\u003cbr/\u003e\u003cspan style\u003d\u0027float:right;\u0027\u003e22.12.2010\u003c/span\u003e","columnData"]}],
"total":50.0
}
I don't know how to use the total parameter, so I just declared an arbitrary value (50D).
The inDetail function just submits the form (I am using Apache Turbine parameter here):
function inDetail(){
document.forms['myForm'].eventSubmit_doAction.value = 'doSomeAction';
document.forms['myForm'].submit();
}
I could not reproduce the problem which you describe. How you can see here the grid can be loaded without any problem in IE. It looks not fine because of missing CSSs, but all works in general. So I suppose you have problem in the code which you not publish here. I recommend you to verify your HTML page in http://validator.w3.org/, your test JSON results in http://www.jsonlint.com/ and JavaScript code in http://www.jslint.com/.
I would only not recommend you to use radio variable inside of the function with the same name radio. Better to choose another name. It is better also to add 10 as the second parameter of the parseInt function. In my tests your original code worked also without the corresponding code changes.