Store calculated data in Column of Kendo Grid - javascript

What I'm trying to do is store some data in a specific column that is calculated by using the data from another column.
I currently have a function that returns the number of available licenses for the given Id in JSON
function getAvailableLicenses(id) {
var url = "/Host/Organization/AvailableLicenses/" + id;
$.get(url, function (data) {
return data.AvailableLicenses;
});
}
How do I go about storing this number in a column named "AvailableLicenses"?
Here is my current Grid:
$("#OrganizationGrid").kendoGrid({
dataSource: viewModel.get("orgDataSource"),
filterable: {
extra: false
},
sortable: true,
pageable: true,
columns: [
{ field: "Id", hidden: true },
{ field: "Name", template: "<a href='/Host/Organization/Detail/#:Id#'>#:Name#</a>" },
{ field: "LicenseNumber", title: "Number of Licenses" },
{ field: null, title: "Available Licenses", template: "#= getAvailableLicenses(Id) #" },
{ field: "LicenseExpiration", title: "License Expiration", format: "{0:MM/dd/yyyy}" },
{ field: "State" },
{ field: "Active" }
],
editable: false
});
As you can see, I tried to create a null column with a template that calls the function for the given Id.
By using Fiddler I can see that the function is indeed being called for all of the rows, but the AvailableLicenses column just displays Undefined for every row.
Is there something I'm missing here to get this to work?

I think the better way to do this is on dataSource parse() function
First: you column configuration must change like this:
{ field: "AvalableLicenses", title: "Available Licenses" },
You alaways can use you template .
And second, inside your dataSource() you can add:
schema: {
parse: function(response) {
for (var i = 0; i < response.length; i++) {
response[i].AvalableLicenses= null;
response[i].AvalableLicenses = getAvailableLicenses(response[i].Id)
}
return response;
}
}
EDIT:
If you prefer using you way, I dont see any problem in your configuration, probably your $.get is returning undefined, or something you don't expect.
For conviniance I did an example working.
http://jsfiddle.net/jwocf897/
Hope this help

Related

VueGoodTable filter dropdown options vue2

I'm trying to populate possible dropdown options on vue good table. The idea is that I conduct an API call to the server to bring back what values can possibly go into the drop down and I'm trying to assign it to the column filter. However, I can't seem to get it to work.
<vue-good-table
:paginationOptions="paginationOptions"
:sort-options="sortOptions"
:isLoading.sync="isTableLoading"
:rows="rows"
:columns="columns"
:lineNumbers="true"
mode="remote"
:totalRows="totalRecords"
#on-row-click="onRowClick"
#on-page-change="onPageChange"
#on-sort-change="onSortChange"
#on-column-filter="onColumnFilter"
#on-per-page-change="onPerPageChange"
#on-search="onSearch"
:search-options="{
enabled: true
}"
styleClass="vgt-table striped bordered"
ref="table"
>
Fairly standard vgt set up.
columns: [
{
label: 'some column',
field: 'column1'
},
{
label: 'Customer',
field: 'customerName',
filterOptions: {
enabled: true,
placeholder: 'All',
filterDropdownItems: Object.values(this.customers)
}
},
{
label: 'other columns',
field: 'column234'
}
]
and the API call
methods: {
async load () {
await this.getTableOptions()
},
async getTableOptions () {
try {
var response = await axios.get(APICallUrl)
this.customers= []
for (var i = 0; i < response.data.customers.length; i++) {
this.customers.push({ value: response.data.customers[i].customerId, text: response.data.customers[i].customerName})
}
} catch (e) {
console.log('e', e)
}
}
The only thing that I thought of is that the table has finished rendering before the load method is complete. However just creating a static object in my data and assigning it to a filterDropDownItems yielded no better results. The result whenever I try to set it to an object is that the box is a type-in box rather than a dropdown.
You can make the table update after it's rendered by making columns a computed property. The other problem you have is this.customers is an Array but Object.values() expects an Object. You could use the Array.map function instead
this.customers.map(c => c.value)
Although according to the VueGoodTable docs an array of objects like you have should work just fine
computed: {
columns() {
return [
{
label: 'some column',
field: 'column1'
},
{
label: 'Customer',
field: 'customerName',
filterOptions: {
enabled: true,
placeholder: 'All',
filterDropdownItems: this.customers
}
},
{
label: 'other columns',
field: 'column234'
}
];
}
}

Why Kendo dataSouce.transport.update method do not send data to the server?

I have a Kendo UI TreeList where every row has a checkbox displayed. If the user clicks on the checkbox then a request goes to the server and save the data. Unfortunately, I did something wrong because:
the update method does not send data to the server
and the sync method is not called automatically
What I did wrong?
I think the problem around how I set up that which item has changed. As you can see I iterate over the dataset coming from dataSource.data() and the item.checked and item.dirty properties are updated. If I understand correctly the documentation then this changes should trigger the sync method. It does not trigger the sync method and this it the reason I call it in the method.
My other question is related to the data structure should be sent to the server. It is based on the schema, right? So, once I can achieve that the request sends an object to the server I should create a similar C# POCO as model and I can read the data in the webapi controller.
In the documentation there is a saveRow() method, but I cannot translate that code to angular. Can somebody help me in this case?
//this row is my problem
var treeList = $("#treeList").data("kendoTreeList");
var dataSource = new kendo.data.TreeListDataSource({
transport: {
read: {
url: configurationService.goNoGoWebApiRootUrl + 'AreaPathDependencies/Get/ChildrenMarked/' + selectedAreaPathIdFromModalService,
dataType: "json",
type: "get"
},
update:
{
url: configurationService.goNoGoWebApiRootUrl + 'AreaPathDependencies/Update/AreaPathDependencies',
dataType: "json",
type: "post"
},
parameterMap: function (options, operation) {
if (operation !== "read" && options.models) {
return { models: kendo.stringify(options.models) };
}
}
},
schema: {
model: {
id: "id",
parentId: "parentId",
fields: {
Id: { type: "number", editable: false, nullable: true },
ParentId: { type: "number", editable: false, nullable: true },
Name: { type: "string", editable: false, nullable: true },
Checked: { type: "boolean", editable: true, nullable: false }
}
}
}
});
vm.treeListOptions = {
dataSource: dataSource,
sortable: false,
editable: false,
columns: [
{
field: "checked",
title: "Selected",
template: checkBoxTemplate,
width: 32
},
{ field: "name", title: "Area Path", width: "200px", expandable: true },
{ field: "fullPath", title: "FullPath", width: "500px" },
],
save: onSave,
change: onChange,
sync: sync,
autoSync: true,
};
}
function checkboxOnclick(selectedId) {
console.log('checkboxOnclick', selectedId);
var data = vm.treeListOptions.dataSource.data();
for (var i = 0; i < data.length; i++) {
if (selectedId == data[i].id) {
data[i].set("checked", true);
//data[i].dirty = true;
}
}
vm.treeListOptions.dataSource.sync();
//console.log('flush', vm.treeListOptions.dataSource.data());
}
Well batch: true has to be set to get parameterMap working, because models parameters will be available only when the batch option is enabled. (parameterMap docs)
And to second question - I am not so sure but as noted in sync docs,
The sync method will request the remote service if:
the transport.create option is set and the data source contains new data items
the transport.destroy option is set and data items have been removed from the data source
the transport.update option is set and the data source contains updated data items
How I understand to that - to get sync method working you need to return updated records. Please check, if your server method for update/delete returns that.

How to calculate row sum on user entry in free jqgrid

Row sum should calculated if price or quantity is changed.
Formatter is created according to How to access other row data from a cell's custom formatter in JqGrid
In inline and row editing modes row sum doesnt change.
Row sum column is read only and does not have id assigned. So it is difficult to create script to change it.
How to fix this so that row sum is calculated on edit ?
Testcase is in http://jsfiddle.net/ex6158L1/4/ containing
javascript
var serverResponse = {
"page": "1",
"records": "3",
"rows": [
{ "Id": "1", Quantity:4, Price : 23.33 },
{ "Id": "2", Quantity:4.55, Price : 76.66 }
]
},
$grid = $("#categorysummary");
function sumFmatter (cellvalue, options, rowObject) {
return options.rowData.Quantity *
options.rowData.Price;
}
$grid.jqGrid({
url: "/echo/json/", // use JSFiddle echo service
datatype: "json",
mtype: "POST", // needed for JSFiddle echo service
pager: '#pager',
postData: {
json: JSON.stringify(serverResponse) // needed for JSFiddle echo service
},
//colNames: ["Quantity", "Price"],
colModel: [
{ name: 'Id', hidden: true },
{ name: 'Quantity', editable: true},
{ name: 'Price', editable: true },
{ name: "Sum", formatter: sumFmatter, editable: "readonly" }
],
jsonReader: {
id: 'Id',
repeatitems: false
},
sortname: 'Id',
viewrecords: true
})
.jqGrid("navGrid",'#pager')
.jqGrid("inlineNav",'#pager');
and css
<div class="container">
<div id="pager"></div>
<table id="categorysummary"></table>
</div>
The first problem, which you have, is the bug in free jqGrid, which follows that options.rowData was not filled inside of setRowData. I posted the corresponding fix to GitHub to eliminate the problem.
The next problem is the requirement to reformat the data of editable: "readonly". Form editing do this, but not inline editing. One can use either editable: "hidden" or to add the option
inlineEditing: {
extraparam: { Sum: "" }
}
which extend the results of inline editing with the dummy value "" for Sum column. It force reformatting of the value in the Sum column.
I would recommend you additionally to change the formatter sumFmatter which you use to
function sumFmatter (cellvalue, options, rowObject) {
var quantity = parseFloat(options.rowData.Quantity || 0),
price = parseFloat(options.rowData.Price || 0);
return (quantity * price).toFixed(2);
}
see the demo http://jsfiddle.net/OlegKi/ex6158L1/7/ or to
function sumFmatter (cellvalue, options, rowObject, action) {
var quantity = parseFloat(options.rowData.Quantity || 0),
price = parseFloat(options.rowData.Price || 0);
return $.fn.fmatter.call(this, "number", quantity * price,
options, rowObject, action);
}
where I called formatter: "number" to format the results of the multiplication (quantity * price).
See the resulting demo http://jsfiddle.net/OlegKi/ex6158L1/10/

DGrid Editor - Changing the Displayed Value when Trying to Edit a Text Cell

I'm using a DGrid editor column to edit the contents of a store. Of the fields that I want to be able to edit, one is an object. When I click on the field to edit it, what I want is for the value displayed in the editor to match the value displayed by the grid when not editing. The cell formatting just shows the value of the object, but when I click on the field to edit it, instead of the object's value, I instead the field is populated with '[object Object]'. I can still edit it (though the results of doing so is that the field will display 'undefined' until I refresh the page, but I could just force a refresh after the change), but can't seem to get it to show what I want.
Here's the set up code:
// build the store
this.postStore = Observable(Memory({
data: posts
}));
var formatCategory = function(object, data, cell) {
cell.innerHTML = object.category.value;
};
var formatAuthor = function(object, data, cell) {
cell.innerHTML = object.author.value;
};
var formatDate = function(object, data, cell) {
cell.innerHTML = new Date(object.dateCreated).toISOString();
};
// the columns displayed in the grid
var columns = [
selector({
field: 'checkbox',
label: ' ',
selectorType: 'radio',
width:33
}),
{
label: "Author",
field: "author",
width: 120,
renderCell: formatAuthor
},
editor({
label: "Title",
field: "title",
editor: "text",
editOn: "click",
width: 200
}),
editor({
label: "Text",
field: "text",
editor: "text",
editOn: "click",
width:500
}, Textarea),
editor({
label: "Category",
field: "category",
editor: "text",
editOn: "click",
width: 150,
renderCell: formatCategory
}),
{
label: "Date",
field: "date",
renderCell: formatDate,
width: 120
}
];
if (this.postGrid) {
this.postGrid.set("store", this.postStore);
} else {
var SelectionGrid = new declare([OnDemandGrid, Selection, Keyboard, editor, selector, DijitRegistry, ColumnResizer]);
this.postGrid = new SelectionGrid({
store: this.postStore,
columns: columns,
selectionMode: 'none',
sort: [{attribute: "date", descending: false}]
}, this.postGridDiv);
this.postGrid.startup();
this.postGrid.on("dgrid-select, dgrid-deselect", lang.hitch(this, this._postSelected));
this.postGrid.on("dgrid-datachange", lang.hitch(this, function(evt){
var cell = this.postGrid.cell(evt);
var post = cell.row.data;
if (cell.column.field === "title") {
post.title = evt.value;
} else if (cell.column.field === "text") {
post.text = evt.value;
} else if (cell.column.field === "category") {
post.category.value = evt.value;
}
this._updatePost(post);
}));
Instead of defining a renderCell function, define a get function (which is used to transform the value before it is even sent to renderCell) and a set function (which is used to transform data back before it's sent to a store when saving edits).
Something like:
get: function (object) {
return object.category.value;
},
set: function (object) {
return { value: object.category };
}
See also the documentation.

data not displaying in JQgrid when using datatype:function?

Edit:
Okay I think it's because when I assign sumColumnModel to colModel sumColumnModel is empty because sumColumnModel is only non-empty within the success function. So is there any way I can get that variable out of the success function and use it in colModel?
I am using a function to get my data and I am getting the data out just fine. I get this JSON from data.d:
"{"Page":1,
"TotalPages":5.0,
"TotalRecords":122,
"ColumnModel": [
{"name":"Description","sorttype":"string","align":"center"},
{"name":"Matrix","sorttype":"string","align":"center"},
{"name":"AvailableReports","sorttype":"string","align":"center","hidden":true},
{"name":"Classification","sorttype":"string","align":"center","hidden":true}
],
"Submissions":[
{"DateSubmitted":"4/23/2014","DateSampled":null,"Matrix":"Sometype","Status":"Completed","SubmissionId":"001","Description":"description","Company":null,"Classification":null,"AvailableReports":7},
{"DateSubmitted":"4/23/2014","DateSampled":null,"Matrix":"sometype","Status":"Completed","SubmissionId":"002","Description":"description","Company":null,"Classification":null,"AvailableReports":6}
]}"
I am currently using this jsonreader:
jsonReader: {
repeatitems: false,
root: function(obj) { return obj.Submissions; },
page: function(obj) { return obj.Page; },
total: function(obj) { return obj.TotalPages; },
records:function(obj) { return obj.TotalRecords; },
}
I tired putting in just 'Submissions' for the value of root in jsonreader but that didnt do the trick.
My column model is being edited in the success part of my ajax function call to correctly display certain columns that is done like this.
myData.ColumnModel.splice(0, 0,
{ name: "DateSubmitted", label: "Date Submitted", sorttype: "date", align: "center"});
myData.ColumnModel.push(
{ name: "Status", sorttype: "string", align: "center" },
{ name: "SubmissionId", label:"Submission Id", sorttype: "string", align: "center" });
sumColumnModel = myData.ColumnModel;
then I pass sumColumn as the Column model for the grid.
colModel: sumColumnModel,
Any idea why the grid isn't being populated?
So I wound up just initializing the colModel and then adding/subtracting things from it based on a couple drop down menus. It would be nice to know if I could actually get the col model out of the datatype:function but at this point I've just worked around it.

Categories

Resources