I Got Columns are quantity,Totalprice in my kendo grid. Then I want to add calculated column to my datagrid.
for example:
$("#gridcolumnadd").click(function (e) {
//1.add new column code Column Name is "Price For per kg"
//2.Set Column type is number
//3.Set Column aggregate is sum for footerTemplate
//4.add calculated values ex:(Totalprice/quantity) to "Price For per kg" with using for loop row count.
//redraw datagrid
});
Is possible to make it in kendo datagrid?
**
NOTE
I WANT TO CREATE DATAGRID FIRSTLY THEN ADD NEW COLUMN WITH ITS CALCULATION. THATS THE REASON "I WRITE JUST BUTTON CLICK"
**
For example; It is not working
var raw = grid.dataSource.data();
var length = raw.length;//if ı have many data . I can use For Loop
raw[0].new="Test"; //I think one data we have it
grid.columns.push({ field: "new" });
grid.dataSource.data(raw);
Some tips:
Instead of adding a column you should show and hide a column otherwise you will have to destroy current grid and create a new one (pretty expensive).
Have it created from the beginning. You might have fields in your model that are actually not coming from the server or you can have fields that are not in the model. You should decide.
Don't understand what do you mean by Set Column aggregate is sum for footerTemplate. As far as I understand you want to define an aggregate of a column so you should take a look into columns.aggregate.
Is this an editable grid? If not I do recommend to compute it when you receive the data from the server using either dataBound event handler or even using DataSource schema.parse
Lets see how this fits together...
This is my original schema:
schema: {
model: {
id: "ProductID",
fields: {
ProductID: { type: "number" },
ProductName: { type : "text" },
UnitPrice: { type: "number" },
UnitsInStock: { type: "number" }
}
},
...
The first thing is add the Total which equals UnitPrice times UnitsInStock where I'm going to use parse.
schema: {
model: {
id: "ProductID",
fields: {
ProductID: { type: "number" },
ProductName: { type : "text" },
UnitPrice: { type: "number" },
UnitsInStock: { type: "number" },
Total: { type: "total" }
}
},
parse : function (d) {
$.each(d, function(idx, elem) {
elem.Total = elem.UnitPrice * elem.UnitsInStock;
})
return d;
}
},
as you can see I've added an extra field Total and then in parse I iterate to compute the total for each record.
Next is define an aggregate that computes the total for all the data received.
aggregate: [
{ field: "Total", aggregate: "sum" }
]
This simple!
Now lets define the columns of my grid:
columns: [
{ field: "ProductName", title : "Name" },
{ field: "UnitPrice", title: "Price" },
{ field: "UnitsInStock", title:"Units" },
{
field: "Total",
title:"Total",
hidden: true,
aggregates: [ "sum" ],
footerTemplate: "#= sum #"
}
]
Here what is important is Total column where:
* I define as (initially) hidden using hidden: true.
* I also define an aggregate that is the sum.
* And finally I define a template for printing it.
Finally, I don't need to redraw the grid, it is enough invoking columnShow...
$("#gridcolumnadd").click(function (e) {
$("#grid").data("kendoGrid").columnShow(3);
});
All this together here : http://jsfiddle.net/OnaBai/63mg9/
Related
var ColDef = [{
headerName: "colA",
field: 'colA',
rowGroup: true
},
{
headerName: "colB",
field: 'colB',
pivot: true,
enablePivot: true
},
{
headerName: "colC",
field: 'colC',
rowGroup: true
},
{
field: 'colD',
aggFunc: 'first',
valueFormatter: currencyFormatter,
tooltip: function(params) {
return (params.valueFormatted);
},
},
{
field: 'comment'
},
{
field: 'colF'
}
];
function currencyFormatter(params) {
return params.value;
}
above code is from different question. it works but i want to use different 'comment' field as tool tip to current 'colD' . also this is a group and pivot agGrid,if it is normal grid this is not a problem. I would appreciate any ideas for group and pivot agGrid?
Not sure if there is good way for the grid to get the data in your scenario then, as your rows and columns are different than original model after pivot.
Maybe you can consider retrieve this information outside of grid. Assume you also want some aggregated information displays in the tooltip, the tooltip function may eventually look like this:
tooltip: params => {
const country = params.node.key;
const year = params.colDef.pivotKeys[0];
const athletesWithNumbers = this.state.rowData
.filter(d => d.year == year)
.filter(d => d.country === country)
.filter(d => d.gold > 0)
.map(d => d.athlete + ': ' + d.gold);
return athletesWithNumbers.join(', ');
}
See this plunker for what I am talking about - again, not sure if this is what you want but just an FYI.
just use tooltipValueGetter
{
field: 'message',
headerName: 'Message',
headerTooltip: 'Message',
width: 110,
filter: 'agSetColumnFilter',
tooltipValueGetter: (params) => `${params.value} some text`
}
or just use the same method for tooltipValueGetter
UPDATE:
Okay, I understood
but it also easy
Ag-grid has property tooltipField - where you can choose any field from grid
For example here - in the column of 'sport' I am showing tooltip of the previous column
Example: https://plnkr.co/edit/zNbMPT5HOB9yqI08
OR
You can easily manipulate with data for each field by tooltipValueGetter
with next construction:
tooltipValueGetter: function(params) {
return `Country: ${params.data.country}, Athlete: ${params.data.athlete}, Sport: ${params.data.sport}`;
},
Example: https://plnkr.co/edit/zNbMPT5HOB9yqI08
Result:
UPDATE 2
Hey Man! I do not understand was is wrong
I just used your code snippet and my solution
And it works as you want
Example: https://plnkr.co/edit/zNbMPT5HOB9yqI08
UPDATE 3
A little bit of manipulation and I can get the data
{ field: 'gold', aggFunc: 'sum',
tooltipValueGetter: function(params) {
var model = params.api.getDisplayedRowAtIndex(params.rowIndex);
return model.allLeafChildren[0].data.silver;
},
},
The Last:
https://plnkr.co/edit/9qtYjkngKJg6Ihwb?preview
var ColDef = [{
headerName: "colA",
field: 'colA',
rowGroup: true
},
{
headerName: "colB",
field: 'colB',
pivot: true,
enablePivot: true
},
{
headerName: "colC",
field: 'colC',
rowGroup: true
},
{
field: 'colD',
aggFunc: 'last',
tooltipValueGetter: commentTooltipValueGetter
},
{
field: 'comment'
},
{
field: 'colF'
}
];
function commentTooltipValueGetter(params) {
const colB = params.colDef.pivotKeys[0];
var model = params.api.getDisplayedRowAtIndex(params.rowIndex);
for (var i = 0; i < model.allLeafChildren.length ; i++) {
if (model.allLeafChildren[i].data.colB=== colB) {
return model.allLeafChildren[i].data.comments;
}
}
}
This is what i had to do for my question. It is combination of answers from #wctiger and #shuts below. So please also refer them for more context
I have some rows I hide like that:
$("#"+rowid).hide();
My problem is that when the user clicks to sort a colmun, the hidden rows reappeared. There is a way to avoid this?
EDIT
I will try to explain a little bit more what I did with code example.
I start to create my grid with this params (and without datas).
var params = {
datatype: "local",
data: [],
caption: "Grid",
colNames:[ "Column A", "Column B" ],
colModel:[
{ name:"colA", key: true },
{ name:"colB" }
]
};
For some reasons, I reload next the grid with datas, like this:
$("#myGrid").jqGrid("clearGridData")
.jqGrid("setGridParam", { data: myDatas })
.trigger("reloadGrid");
And I have checkboxes with listeners, like this one:
$("#checkbox1").on("change", onCheckbox1Changed);
function onCheckbox1Changed() {
var rowid = ...;
var datas = $("#myGrid").jqGrid("getRowData");
for(var key in datas) {
if(datas[keys].colB === "" && $("#checkbox1").val() === true) {
$("#"+rowid).show();
} else if(datas[keys].colB === "" && $("#checkbox1").val() === false) {
$("#"+rowid).hide();
}
}
}
This code works like I want. Rows are hidden/shown depending on checkboxes. The problem is when I clik on a column to sort it, the hidden columns reappeared.
EDIT 2
I could force the grid to hide the rows after a sort. But I didn't find where I can find an event like "afterSort". There is "onSortCol" but it is called before the sort.
A solution will be to force that using "loadComplete". Like this:
var params = {
// ...
loadComplete: onLoadComplete
}
function onLoadComplete() {
onCheckbox1Changed();
}
I tried it and it works. But I am not very "fan" with this solution.
I find hiding some rows after displaying the page of data not the best choice. The main disadvantage is the number of rows which will be displayed. You can safe use $("#"+rowid).hide(); method inside of loadComplete only if you need to display one page of the data. Even in the case one can see some incorrect information. For example, one can use viewrecords: true option, which place the text like "View 1 - 10 of 12" on right part of the pager.
I personally would recommend you to filter the data. You need to add search: true option to the grid and specify postData.filters, which excludes some rows from displaying:
search: true,
postData: {
filters: {
groupOp: "AND",
rules: [
{ field: "colA", op: "ne", data: "rowid1" },
{ field: "colA", op: "ne", data: "rowid2" }
]
}
}
If you would upgrade from old jqGrid 4.6 to the current version (4.13.6) of free jqGrid, then you can use "ni" (NOT IN) operation:
search: true,
postData: {
filters: {
groupOp: "AND",
rules: [
{ op: "ni", field: "id", data: "rowid1,rowid2" }
]
}
}
In both cases jqGrid will first filter the local data based on the filter rules and then it will display the current page of data. As the result you will have the perfect results.
Sorting of such grid will not not change the filter.
Don't hide columns after the creation of the table, hide them directly when you create the grid using the option hidden, like this:
colNames: ['Id', ...],
colModel: [
{ key: true, hidden: true, name: 'Id', index: 'Id' },
....
]
If you want to hide columns on particular events after the creation of the grid, look at this article.
Hope it was you were looking for.
I need to show an array of objects in the table like representation. Table has columns with the properties, and when clicked on the column it should show more data inside the table. It should be sortable.
Is there a JS library that could do this, so I dont have to write this from scratch?
Please see the attached image with the JSON object.
When the user clicks on Ana, additional row is inserted.
I created the demo https://jsfiddle.net/OlegKi/kc2537ty/1/ which demonstrates the usage of free jqGrid with subgrids. It displays the results like
after the user clicks on the "+" icon in the second line.
The corresponding code you can find below
var mydata = [
{ id: 10, name: "John", lname: "Smith", age: 31, loc: { location: "North America", city: "Seattle", country: "US" } },
{ id: 20, name: "Ana", lname: "Maria", age: 43, loc: { location: "Europe", city: "London", country: "UK" } }
];
$("#grid").jqGrid({
data: mydata,
colModel: [
{ name: "name", label: "Name" },
{ name: "lname", label: "Last name" },
{ name: "age", label: "Age", template: "integer", align: "center" }
],
cmTemplate: { align: "center", width: 150 },
sortname: "age",
iconSet: "fontAwesome",
subGrid: true,
subGridRowExpanded: function (subgridDivId, rowid) {
var $subgrid = $("<table id='" + subgridDivId + "_t'></table>"),
subgridData = [$(this).jqGrid("getLocalRow", rowid).loc];
$("#" + subgridDivId).append($subgrid);
$subgrid.jqGrid({
idPrefix: rowid + "_",
data: subgridData,
colModel: [
{ name: "location", label: "Localtion" },
{ name: "city", label: "City" },
{ name: "country", label: "Country" }
],
cmTemplate: { align: "center" },
iconSet: "fontAwesome",
autowidth: true
});
}
});
Small comments to the code. Free jqGrid saves all properties of input data in data parameter. I added id property to every item of input data. It's not mandatory, but it could be helpful if you would add more functionality to the grid. See the introduction for more details.
The columns are sortable based on the type of the data specified by sorttype property of colModel. To simplify usage some standard types of data free jqGrid provides some standard templates which are shortcurts for some set of settings. I used template: "integer" in the demo, but you could replace it to sorttype: "integer" if only sorting by integer functionality is important.
If the user click on "+" icon to expand the subgrid then jqGrid inserts new row and creates the div for the data part of the subgrid. You can replace subGridRowExpanded from above example to the following
subGridRowExpanded: function (subgridDivId) {
$("#" + subgridDivId).html("<em>simple subgrid data</em>");
}
to understand what I mean. The unique id of the div will be the first parameter of the callback. One can create any common HTML content in the subgrid. Thus one can create empty <table>, append it to the subgrid div and
then convert the table to the subgrid.
To access to the item of data, which corresponds to the expanding row one can use $(this).jqGrid("getLocalRow", rowid). The return data is the item of original data. It has loc property which we need. To be able to use the data as input for jqGrid we create array with the element. I's mostly all, what one have to know to understand how the above code works.
You can add call of .jqGrid("filterToolbar") to be able to filter the data or to add pager: true (or toppager: true, or both) to have the pager and to use rowNum: 5 to specify the number of rows in the page. In the way you can load relatively large set of data in the grid and the user can use local paging, sorting and filtering. See the demo which shows the performance of loading, sorting and filtering of the local grid with 4000 rows and another one with 40000 rows. All works pretty quickly if one uses local paging and not displays all the data at once.
I use datatables.net for all my "more complex than lists"-tables. I It's a very well kept library with loads of features and great flexibility.
In the "con" column I would say that it's so complex that it probably has quite a steep learning curve. Although the documentation is great so there is always hope for most problems.
I am using jquery's DataTables which is really working great. Then only problem I got is, that I am facing (in non-edit-view) the value of the select-field (which is an id). The user of course doesn't want to see the id of course.
Therefore I am looking for a possibility to configure that column in a way to show always the value of label property.
Here a some snippets:
$(document).ready(function() {
var table = $('#overviewTable').DataTable({
dom: "Tfrtip",
ajax: "/Conroller/GetTableData",
columns: [
{ data: "Id", className: "readOnly", visible: false },
{
data: "LoanTransactionId",
className: "readOnly readData clickable",
"fnCreatedCell": function(nTd, sData, oData, iRow, iCol) {
$(nTd).html("<a href='#'>" + oData.LoanTransactionId + "</a>");
}
},
{ data: "Id", className: "readOnly" },
{ data: "property_1", className: "readOnly" },
{ data: "Priority" },
{ data: null, className: "action readOnly", defaultContent: 'Info' }
],
order: [1, 'asc'],
tableTools: {
sRowSelect: "os",
sRowSelector: 'td:first-child',
aButtons: []
}
});
// data reload every 30 seconds
setInterval(function() {
table.ajax.reload();
}, 30000);
editor = new $.fn.dataTable.Editor({
ajax: "PostTable",
table: "#overviewTable",
fields: [
{
label: "Id",
name: "Id"
},
{
label: "Column 1",
name: "property_1"
},
{
label: "Priority",
name: "Priority",
type: "select",
options: [
{ label: "low", value: 0 },
{ label: "mid", id: 1 },
{ text: "high", id: 2 }
]
}
]
});
// Inline Edit - only those who are not readOnly
$('#overviewTable').on('click', 'tbody td:not(:first-child .readOnly)', function(e) {
editor.inline(this, {
submitOnBlur: true
});
});
How it looks in the display mode
How it looks in the edit mode
See the documentation on columns.render
You want to modify your column options for priority
Preferred Option: Your data source has a field with the priority as a string
This is the best option, as you don't want to have two places with this business logic. Keep it out of the client code.
Also, you will want to modify the editor as well so that the options used have been retrieved dynamically from the server to keep this business logic out of the client too. This is left as an exercise for the reader.
Since you don't provide details on what your data structure looks lik, I'm assuming it is an object, and it has an attribute priorityAsString so use the string option type for render.
columns: [
...
{
data: "Priority" ,
render: "priorityAsString",
},
Option 2) You write a function to map priority to string
Do this if you can't get the data from the server. But remember you will need to update many places when the priority list changes.
columns: [
...
{
data: "Priority" ,
render: renderPriorityAsString,
},
...
function renderPriorityAsString(priority) {
const priorityToString = {
0: 'low',
1: 'med',
2: 'high',
};
return priorityToString[priority] || `${priority} does not have a lookup value`;
}
"render": function ( data, type, full ) { return label;}
I am trying to add a new record to a kendo grid (only using client side javascript) and I can only get all the fields represented as text fields.
One of the fields however is actually a boolean and I would like it to be represented as a check box instead. Does anyone know how to do this?
Can anyone please help? Any help would be greatly appreciated.
UPDATED with code below. Also I tried the template suggestion but this is not working when I click on the Add New Record button at the top of the grid. I get a JavaScript error "primary is not defined"
$("#phoneGrid").kendoGrid({
columns: [
{
field: "type",
title: "Type"
},
{
field: "primary",
title: "Primary",
template: "<input type=\"checkbox\" #= primary ? checked='checked' : '' #/>"
},
{
field: "number",
title: "Number"
},
{ command: ['edit'], title: ' ' }
],
editable: "inline",
dataSource: {
data: patientDetailUpdateViewModel.phones,
schema: {
model: { id: "id" }
}
},
toolbar: ['create'],
save: function (e) {
//alert("Save Event Triggered");
if (e.model.isNew()) {
phone = new Phone();
//Give the phone an id to uniquely identify it, but one which would signify a new phone instance (negative phone instance).
phone.id = patientDetailUpdateViewModel.phones.length * -1;
e.model.id = phone.id;//So isNew() will return false on subsequent calls.
phone.type = e.model.type;
phone.primary = e.model.primary;
phone.number = e.model.number;
patientDetailUpdateViewModel.phones.push(phone);
//alert("isNew() = true");
}
}
});
You can use template for column definition:
{
field: "ColumName",
template: '<input type="checkbox" #= Column? checked="checked" : "" # disabled="disabled" ></input>'
}
EDIT:
Try to define data source model (http://docs.telerik.com/kendo-ui/api/javascript/data/datasource#configuration-schema.model) like below, but according to your data types in source:
schema: {
model: {
id: "ProductID",
fields: {
type: {
type: "string"
},
UnitPrice: {
type: "number"
}
}
}
}