Related
Tabulator doesn't accept bottomCalcFormatter in column definition
My Tabulator table works pretty well and I can successfully add bottomCalc and formatter, but I can't seem to add bottomCalcFormatter. so I have a column of money with formatter:"money" and a bottomCalc:"sum" but the sum is not formatted as money. If I try to add bottomCalcFormatter:"money" the table doesn't render.
This renders although the sum is not in a "money" format:
columns:[
{title:0, titleFormatter:closeButton},
{title:"Revision#", field:"revNum", sorter:"number", align:"center", formatter:revisionDoc, formatterParams:{urlField:"hyperlink"}},
{formatter:pdfIcon, align:"center", formatterParams:{urlField:"hyperlink"}},
{title:"TO Amount", field:"toAmount", sorter:"number", formatter:"money", align:"right", bottomCalc:"sum"},
{title:"Adjusted", field:"adjusted", align:"right", formatter:"money", bottomCalc:"sum"},
],
This table does not render at all:
columns:[
{title:0, titleFormatter:closeButton},
{title:"Revision#", field:"revNum", sorter:"number", align:"center", formatter:revisionDoc, formatterParams:{urlField:"hyperlink"}},
{formatter:pdfIcon, align:"center", formatterParams:{urlField:"hyperlink"}},
{title:"TO Amount", field:"toAmount", sorter:"number", formatter:"money", align:"right", bottomCalc:"sum"},
{title:"Adjusted", field:"adjusted", align:"right", formatter:"money", bottomCalc:"sum", bottomCalcFormatter:"money"},
],
I just checked the Tabulator.js there is an additional parameter
bottomCalcFormatterParams
Check this code it sums currency and the calculation shows $ sign
<!DOCTYPE html>
<html lang="en">
<head><link href="https://unpkg.com/tabulator-tables#4.2.4/dist/css/tabulator.min.css" rel="stylesheet"></head>
<body>
<div id="example-table"></div>
<script
src="https://code.jquery.com/jquery-3.4.0.min.js"
integrity="sha256-BJeo0qm959uMBGb65z40ejJYGSgR7REI4+CW1fNKwOg="
crossorigin="anonymous"></script>
<script type="text/javascript" src="https://unpkg.com/tabulator-tables#4.2.4/dist/js/tabulator.min.js"></script>
<script>
const tabledata = [
{id: 1, name: "Oli Bob", money: "12", col: "red", dob: ""},
{id: 2, name: "Mary May", money: "1", col: "blue", dob: "14/05/1982"},
{id: 3, name: "Christine Lobowski", money: "42", col: "green", dob: "22/05/1982"},
{id: 4, name: "Brendon Philips", money: "125", col: "orange", dob: "01/08/1980"},
{id: 5, name: "Margret Marmajuke", money: "16", col: "yellow", dob: "31/01/1999"},
];
const table = new Tabulator("#example-table", {
height: 205, // set height of table (in CSS or here), this enables the Virtual DOM and improves render speed dramatically (can be any valid css height value)
data: tabledata, //assign data to table
layout: "fitColumns", //fit columns to width of table (optional)
columns: [ //Define Table Columns
{title: "Name", field: "name", width: 150},
{
title: "money",
field: "money",
align: "left",
formatter: "money",
bottomCalc: "sum",
bottomCalcParams: {
precision: 3
},
bottomCalcFormatter: "money",
bottomCalcFormatterParams: {
decimal: ".",
thousand: ",",
symbol: "$"
},
formatterParams: {
decimal: ".",
thousand: ",",
symbol: "$"
}
},
{title: "Favourite Color", field: "col"},
{title: "Date Of Birth", field: "dob", sorter: "date", align: "center"},
]
});
</script>
</body>
</html>
When i don't have any data in subgrid i am getting empty grid in subgrid. Also need to hide the expand icon. Below is the code i used.
$(document).ready(function() {
'use strict';
var myData = [
{
id: "10",
c1: "My Value 1",
c2: "My Value 1.1",
subgridData: [
{ id: "10", c1: "aa", c2: "ab" },
{ id: "20", c1: "ba", c2: "bb" },
{ id: "30", c1: "ca", c2: "cb" }
]
},
{
id: "20",
c1: "My Value 2",
c2: "My Value 2.1",
subgridData: [
{ id: "10", c1: "da", c2: "db" },
{ id: "20", c1: "ea", c2: "eb" },
{ id: "30", c1: "fa", c2: "fb" }
]
},
{
id: "30",
c1: "My Value 3",
c2: "My Value 3.1"
}
],
$grid = $("#list"),
mainGridPrefix = "s_";
$grid.jqGrid({
datatype: "local",
data: myData,
colNames: ["Column 1", "Column 2"],
colModel: [
{ name: "c1", width: 180 },
{ name: "c2", width: 180 }
],
rowNum: 10,
rowList: [5, 10, 20],
pager: "#pager",
gridview: true,
ignoreCase: true,
sortname: "c1",
viewrecords: true,
autoencode: true,
height: "100%",
idPrefix: mainGridPrefix,
subGrid: true,
subGridRowExpanded: function (subgridDivId, rowId) {
var $subgrid = $("<table id='" + subgridDivId + "_t'></table>"),
pureRowId = $.jgrid.stripPref(mainGridPrefix, rowId);
$subgrid.appendTo("#" + $.jgrid.jqID(subgridDivId));
$subgrid.jqGrid({
datatype: "local",
data: $(this).jqGrid("getLocalRow", pureRowId).subgridData,
colModel: [
{ name: "c1", width: 178 },
{ name: "c2", width: 178 }
],
height: "100%",
rowNum: 10000,
autoencode: true,
autowidth: true,
gridview: true,
idPrefix: rowId + "_"
});
$subgrid.closest("div.ui-jqgrid-view")
.children("div.ui-jqgrid-hdiv")
.hide();
}
});
$grid.jqGrid("navGrid", "#pager", {add: false, edit: false, del: false});
});
My output like below screenshot. How to remove the expand icon and subgrid if we don't have any data for subgrid.
Is there any way to achieve this behavior. My output like below.
The solution of the problem depends on the version and the fork of jqGrid, which you use. I develop free jqGrid fork and have implemented hasSubgrid callback, which I described in the answer (see the demo).
The items of your input data contains subgridData property as the array of subgrid data. Thus one should create the subgrid only if subgridData property is defined and subgridData.length > 0. Thus you need just to upgrade to the current version of jqGrid (4.13.4 or 4.13.5pre) and to add the option
subGridOptions: {
hasSubgrid: function (options) {
// the options contains the following properties
// rowid - the rowid
// iRow - the 0-based index of the row
// iCol - the 0-based index of the column
// data - the item of the data, with the data of the row
var subgridData = options.data.subgridData;
return subgridData != null && subgridData.length > 0;
}
}
to the main grid. The callback subGridOptions.hasSubgrid will be called during building the grid data, thus it works very effective like rowattr, cellattr and custom formatters.
I took code from this answer and I'm tying to do something like in first picture, to see if it's possible (I know it's is, it's just some JavaScript, HTML and CSS;) ).
Tha second picture is my progress so far.
I put Details text in header:
$("#list_subgrid").append("Details").css('width', '100px');
I changed width of first column:
$(".jqgfirstrow").find("td:first").css({"height":"0px", "width":"100px"});
I can get to result in third picture if I change width of bunch of elements all over the place, but not sure that's correct way. And I can't get rid off horizontal scroll bar.
Have no idea how to put Details text into every cell in first column instead of plus sign, but plus sign can stay there.
And how to switch "subgrid" column to be last instead of first is completely beyond my knowledge...
I wrote the answer, which you used as an example, many years ago. Now I would just to place the subgrid data together with the main data of the row, like details property below:
var myGridData = [
// main grid data
{id: "10", col1: "11", col2: "12", details: [
// data for subgrid for the id=10
{id: "10", c1: "aa", c2: "ab", c3: "ac"},
{id: "20", c1: "ba", c2: "bb", c3: "bc"},
{id: "30", c1: "ca", c2: "cb", c3: "cc"}
]},
{id: "20", col1: "21", col2: "22", details: [
// data for subgrid for the id=20
{id: "10", c1: "xx", c2: "xy", c3: "xz"}
]}
];
The expression $(this).jqGrid("getLocalRow", rowid) get the item of the data and $(this).jqGrid("getLocalRow", rowid).details is the subgrid data of the row. As the result we can rewrite the original example like on the demo.
To have the column with the fixed text Details we can use simple formatter
formatter: function () {
return details;
}
where details is defined for example like
var details = "<span class='fa fa-fw fa-plus'></span> " +
"<span class='mylink'>Details</span>";
(I used Font Awesome icon) and class mylink defined like
.mylink { text-decoration: underline; }
Now we can hide the "subgrid" column and to open/close the subgrid by simulation of click event on the hidden cell with + or - icon. We receive the following full code
var myGridData = [
// main grid data
{id: "10", col1: "11", col2: "12", details: [
// data for subgrid for the id=10
{id: "10", c1: "aa", c2: "ab", c3: "ac"},
{id: "20", c1: "ba", c2: "bb", c3: "bc"},
{id: "30", c1: "ca", c2: "cb", c3: "cc"}
]},
{id: "20", col1: "21", col2: "22", details: [
// data for subgrid for the id=20
{id: "10", c1: "xx", c2: "xy", c3: "xz"}
]}
],
$grid = $("#list"),
details = "<span class='fa fa-fw fa-plus'></span> " +
"<span class='mylink'>Details</span>";
$grid.jqGrid({
data: myGridData,
colModel: [
{ name: "col1", label: "Column 1" },
{ name: "col2", label: "Column 2" },
{ name: "details", label: "Details",
align: "center", width: 70,
formatter: function () {
return details;
} }
],
cmTemplate: { width: 200 },
iconSet: "fontAwesome",
autoencode: true,
sortname: "col1",
sortorder: "desc",
pager: true,
caption: "Demonstrate how to create subgrid from local data",
beforeSelectRow: function (rowid, e) {
var $self = $(this),
p = $self.jqGrid("getGridParam"),
$td = $(e.target).closest("tr.jqgrow>td"),
cm = $td.length > 0 ? p.colModel[$td[0].cellIndex] : null,
cmName = cm != null ? cm.name : null;
if (cmName === "details") {
// simulate opening the subgrid
$($td.parent()[0].cells[p.iColByName.subgrid]).click();
// inverse +/-
var $plusMinus = $td.find("span.fa");
if ($plusMinus.hasClass("fa-minus")) {
$plusMinus.removeClass("fa-minus").addClass("fa-plus");
} else {
$plusMinus.removeClass("fa-plus").addClass("fa-minus");
}
}
return true;
},
subGrid: true,
subGridRowExpanded: function (subgridDivId, rowid) {
var $subgrid = $("<table id='" + subgridDivId + "_t'></table>"),
$subgridDiv = $("#" + subgridDivId),
subgridData = $(this).jqGrid("getLocalRow", rowid).details;
$subgridDiv.closest(".subgrid-data").prev(".subgrid-cell").remove();
var colspan = $subgridDiv.closest(".subgrid-data").attr("colspan");
$subgridDiv.closest(".subgrid-data").attr("colspan", parseInt(colspan, 10) + 1);
$subgridDiv.append($subgrid);
$subgrid.jqGrid({
idPrefix: rowid + "_",
data: subgridData,
colModel: [
{ name: "c1", label: "Col 1" },
{ name: "c2", label: "Col 2" },
{ name: "c3", label: "Col 3" }
],
iconSet: "fontAwesome",
autowidth: true,
autoencode: true,
sortname: "c1"
});
$subgrid.jqGrid("setGridWidth", $subgridDiv.width() - 1);
}
}).jqGrid("hideCol", "subgrid");
The corresponding demo one can see here. After clicking of "+ Detailes" one will see the following:
I've had about 3 goes at trying to learn the jqGrid. Every time has failed. So this time I tried to start with the basics. All I wanted to do was replicate the json data example at http://trirand.com/blog/jqgrid/jqgrid.html .
My best efforts have resulted in a table with rows and columns by every cell has a non-breaking space in it.
With my code, I only departed from the code in that example in the slightest way to account for the fact that I wasn't getting the data from the same data service. But I was getting the exact same data as I was able to extract the json using fiddler.
The code is:
function getData() {
var obj =
{
"page": "1",
"total": 2,
"records": "13",
"rows": [{
"id": "13",
"cell": ["13",
"2007-10-06",
"Client 3",
"1000.00",
"0.00",
"1000.00",
null]
},
{
"id": "12",
"cell": ["12",
"2007-10-06",
"Client 2",
"700.00",
"140.00",
"840.00",
null]
},
{
"id": "11",
"cell": ["11",
"2007-10-06",
"Client 1",
"600.00",
"120.00",
"720.00",
null]
},
{
"id": "10",
"cell": ["10",
"2007-10-06",
"Client 2",
"100.00",
"20.00",
"120.00",
null]
},
{
"id": "9",
"cell": ["9",
"2007-10-06",
"Client 1",
"200.00",
"40.00",
"240.00",
null]
},
{
"id": "8",
"cell": ["8",
"2007-10-06",
"Client 3",
"200.00",
"0.00",
"200.00",
null]
},
{
"id": "7",
"cell": ["7",
"2007-10-05",
"Client 2",
"120.00",
"12.00",
"134.00",
null]
},
{
"id": "6",
"cell": ["6",
"2007-10-05",
"Client 1",
"50.00",
"10.00",
"60.00",
""]
},
{
"id": "5",
"cell": ["5",
"2007-10-05",
"Client 3",
"100.00",
"0.00",
"100.00",
"no tax at all"]
},
{
"id": "4",
"cell": ["4",
"2007-10-04",
"Client 3",
"150.00",
"0.00",
"150.00",
"no tax"]
}],
"userdata": {
"amount": 3220,
"tax": 342,
"total": 3564,
"name": "Totals:"
}
}
return obj;
}
$(function () {
$("#list2").jqGrid({
data: getData()['rows'],
datatype: "local",
colNames: ['Inv No', 'Date', 'Client', 'Amount', 'Tax', 'Total', 'Notes'],
colModel: [
{ name: 'id', index: 'id', width: 55 },
{ name: 'invdate', index: 'invdate', width: 90 },
{ name: 'name', index: 'name asc, invdate', width: 100 },
{ name: 'amount', index: 'amount', width: 80, align: "right" },
{ name: 'tax', index: 'tax', width: 80, align: "right" },
{ name: 'total', index: 'total', width: 80, align: "right" },
{ name: 'note', index: 'note', width: 150, sortable: false }
],
rowNum: 10,
rowList: [10, 20, 30],
pager: '#pager2',
sortname: 'id',
viewrecords: true,
sortorder: "desc",
caption: "JSON Example"
});
$("#list2").jqGrid('navGrid', '#pager2', { edit: false, add: false, del: false });
});
Can anyone please help me break my really bad run with this popular javascript library?
I don't find anything wrong with your grid. There is something wrong with your data. I hope your data need to be checked. Also if you are using local as your datatype your data should like below,
var mydata = [
{ id: "11", invdate: "2007-10-06", name: "Client 1", amount: "600.00"
, tax:"120.00", total:"720.00", note: null },
{ id: "12", invdate: "2007-10-06", name: "Client 2", amount: "700.00",
tax:"140.00", total:"840.00", note: null },
{ id: "13", invdate: "2007-10-06", name: "Client 3", amount: "1000.00",
tax:"0.00", total:"1000.00", note: null }
];
This Demo will give you the good start with jQgrid. I have used your grid definition. Hope this helps.
i'm working with kendo ui to create rich user interface, but i'm stuck t the following:
I want a Grid with a subgrid, the first one displays customer info, like name, etc the second shows the available shipping-adresses, the customer saved. Now my problem is, that in the subgrid is not data, although firebug shows, that the data was returned. This is my source:
$(function() {
var main = $("#customer-grid").kendoGrid({
dataSource: {
transport:{
read :"data/users.php",
update :{
url :"data/users.php?action=update",
type:"POST",
data: function (data) {
data.birthday = kendo.toString(data.birthday, "yyyy-MM-dd");
return data;
}
},
destroy:{
url :"data/users.php?action=destroy",
type:"POST"
}
},
schema: {
data: "data",
model: {
id: "id",
fields: {
id: {editable: false},
activated: { type: "boolean" },
birthday: {type: "date"},
gender: {defaultValue: "W"}
}
}
}
},
height: 250,
filterable: true,
sortable: true,
pageable: true,
detailInit: detailInit,
dataBound: function() {
this.expandRow(this.tbody.find("tr.k-master-row").first());
},
columns: [{
field: "id",
title: "ID",
width: "50px"
}, {
field: "gender",
title: "Geschlecht",
width: "100px",
values: data
}, {
field: "firstname",
title: "Vorname"
}, {
field: "lastname",
title: "Nachname"
}, {
field: "birthday",
title: "Geburtstag",
width: "100px",
format: "{0:dd.MM.yyyy}"
},{
field: "mail",
title: "E-Mail"
},{
field: "activated",
title: "Aktiviert",
width: "100px",
values: actval
}, {
command: ["edit", "destroy"],
title: " ",
width: "210px"
}],
editable:{
mode: "popup"
}
});
});
function detailInit(e) {
$("<div/>").appendTo(e.detailCell).kendoGrid({
dataSource: {
transport: {
read: "data/adress.php?uid="+e.data.id
},
serverPaging: true,
serverSorting: true,
serverFiltering: true,
pageSize:6
},
scrollable: false,
sortable: true,
pageable: true,
columns: [
{ field: "id", width: 70 },
{ field: "zipcode", title:"Ship Country", width: 100 },
{ field: "city", title:"Ship Address" },
{ field: "street", title: "Ship Name", width: 200 }
]
});
}
The function gets its data from a php page, which does a mysql-query and then gives back the data as application/json. But nothing is shown.
Hopefully you guys can help me.
Regards
I tested your code and it works fine.
Check:
e parameter format. I've used: detailInit({ detailCell : $("#grid"), data : { id : 1}});
JSON returned by data/adress.php. I've returned:
[
{"city":"Madrid", "id":"1", "zipcode":"31000", "street":"my street 1", "number":5},
{"city":"Sofia", "id":"2", "zipcode":"32000", "street":"my street 2", "number":4},
{"city":"London", "id":"3", "zipcode":"33000", "street":"my street 3", "number":3},
{"city":"San Francisco", "id":"4", "zipcode":"34000", "street":"my street 4", "number":2},
{"city":"Berlin", "id":"5", "zipcode":"35000", "street":"my street 5", "number":1}
]
Using the following (hardcoded) php response:
<?php
header('Content-type: application/json');
$named_array = array(
array("city" => "Madrid", "id" => "1", "zipcode" => "31000", "street" => "my street 1", "number" => 5),
array("city" => "Sofia", "id" => "2", "zipcode" => "32000", "street" => "my street 2", "number" => 4),
array("city" => "London", "id" => "3", "zipcode" => "33000", "street" => "my street 3", "number" => 3),
array("city" => "San Francisco", "id" => "4", "zipcode" => "34000", "street" => "my street 4", "number" => 2),
array("city" => "Berlin", "id" => "5", "zipcode" => "35000", "street" => "my street 5", "number" => 1)
);
echo json_encode($named_array);
?>
EDIT: This is the definition of the grid containing the subgrid.
var outer = $("#outer").kendoGrid({
dataSource:{
type:"json",
transport:{
read:"names.php"
},
pageSize:5
},
sortable:true,
columns:[
{ field:"id", width:70 },
{ field:"name", title:"Name", width:100 },
{ field:"lastname", title:"LastName", width:100 },
{ title:"Address", width:300, attributes:{ class:"ob-address"}}
]
}).data("kendoGrid");
and then on a button click, I run:
$(".ob-address", outer.tbody).each(function (idx, elem) {
detailInit({ detailCell:elem, data:{ id:1}});
});
As you can see I marked a column in the outer grid with a CSS class named ob-address and the function selects all the cell in the body of the outer table for inserting the inner table (subgrid).