KendoUI Grid - Complex JSON with inconsistent keys - javascript

I know this is probably been asked before, but having tried to find an answer - I am guessing either I am not comprehending some of the answers right, or I am looking at the problem all wrong.
I am using a complex SLC loopback query - and the api returns the JSON in the following format:
> [ {"id":"1","name":"John", "type":"commercial",
> "address":{"street1":"1 dalhousie lane", "street2":"some street"}},
> {"id":"2","name":"Jane", "type":"commercial",
> "address":{"street1":"15 dalhousie lane", "postcode":"1283833"}},
> {"id":"3","name":"Jack", "address":{"street1":"12 dalhousie lane",
> "postcode":"9383833", "geo":{"lat":"9393939","long":"99393939"}}}
]
As you can see, following are the problems -
1. Nested JSON - multiple levels
2. Inconsistent / Missing Key values,
e.g.: "id":"2" -> "type" -> missing
e.g.: "id":"3" -> "address" -> "geo"
When I try to use the KendoUI grid to display the above json, i get errors such as - property undefined. I understand, options i can explore and what I am supposed to do -
Define the schema - how? Especially for missing keys.
Parse the data ?
Would be great if someone could kindly let me know, how to move forward with this. Below is the code for the grid -
$("#grid").kendoGrid({
dataSource: {
transport: {
read: {
url: apiurl,
dataType: "json",
}
}
},
columns: [
{
field: "id",
title: "User Id"
},
{
field: "name",
title: "User Name",
},
{
field: "type",
title: "User Type",
},
{
field: "address.street1",
title: "Street 1",
},
{
field: "address.street2",
title: "Street 2",
},
{
field: "address.postcode",
title: "Street 2",
},
{
field: "address.geo.lat",
title: "Latitude",
},
{
field: "address.geo.long",
title: "Longitude",
}
]
});

You can use column templates:
columns: [
{
field: "id",
title: "User Id"
},
{
field: "name",
title: "User Name",
},
{
field: "type",
title: "User Type",
template: function(dataItem) {
return dataItem.type ? kendo.htmlEncode(dataItem.type) : "";
}
},
{
field: "address",
title: "Street 1",
template: function(dataItem) {
return dataItem.address.street1 ? kendo.htmlEncode(dataItem.address.street1) : "";
}
},
{
field: "address",
title: "Street 2",
template: function(dataItem) {
return dataItem.address.street2 ? kendo.htmlEncode(dataItem.address.street2) : "";
}
},
{
field: "address",
title: "Post Code",
template: function(dataItem) {
return dataItem.address.postcode ? kendo.htmlEncode(dataItem.address.postcode) : "";
}
},
{
field: "address",
title: "Latitude",
template: function(dataItem) {
return dataItem.address.geo && dataItem.address.geo.lat ? kendo.htmlEncode(dataItem.address.geo.lat) : "";
}
},
{
field: "address",
title: "Longitude",
template: function(dataItem) {
return dataItem.address.geo && dataItem.address.geo.long ? kendo.htmlEncode(dataItem.address.geo.long) : "";
}
}
]
Each template is a function that checks for the existence of the field and then returns the field value or an empty string.
Working DEMO

Another option is the use the schema.parse method to handle adding a default value for the missing field. Here is a link to the documentation - http://docs.telerik.com/kendo-ui/api/javascript/data/datasource#configuration-schema.parse
<script>
var dataSource = new kendo.data.DataSource({
transport: {
read: {
url: "yoururl",
dataType: "jsonp"
}
},
schema: {
parse: function(response) {
var items = [];
for (var i = 0; i < response.length; i++) {
var item = response[i];
if(!item.address.geo){
if(!item.address.geo.lat){
item.address.geo.lat = 0.0;
}
}
items.push(item);
}
return items;
}
}
});
dataSource.fetch(function(){
var data = dataSource.data();
var product = data[0];
console.log(product.name);
});
</script>
Hope this helps.
Wade

Related

ExtJS Add filtering in Grid for hasMany association

I have a data model that I want to be able to add a generic amount of filters to. I am specifying a name and a value. How can I add these hasMany associated fields as filters to my grid? I have attempted to write custom filtering option, but I can't have filters show up without an attached dataIndex, which is not available for the hasMany association.
Ext.define('AirGon.model.Project', {
extend: 'Ext.data.Model',
fields: [
{ name: 'Link', type: 'string' },
{ name: 'Title', type: 'string' },
{ name: 'Description', type: 'string' },
{ name: 'MappedMetadata', mapping: 'Metadata'},
{ name: 'XMax', type: 'float' },
{ name: 'XMin', type: 'float' },
{ name: 'YMax', type: 'float' },
{ name: 'YMin', type: 'float' }
],
hasMany: { model: 'Metadata', name: 'Metadata', associationKey: 'Metadata' }
});
Ext.define('Metadata', {
extend: 'Ext.data.Model',
fields: ['Name', 'Value']
});
This is my custom filtering attempt. I am getting the DataStore from the main store and then adding custom rendering, but I can't filter or sort this column because of the lack of a dataIndex.
var column = {
header: 'Meta',
//?????????dataIndex: 'MappedMetadata[0]',?????
sortable: true,
filterable: true,
filter: {
type: 'string'
},
renderer: function (value, meta, record) {
console.log(record.MetadataStore.data.items[index].data)
return record.MetadataStore.data.items[index].data.Value;
}
}
Data. The data is modeled so that a variable amount of metadata can be entered and the 'tag' will not be known by the system.
{
"Link": "link.com",
"Title": "project",
"Description": "descript",
"State": "",
"Metadata": [
{
"Name": "County",
"Value": "32"
},
{
"Name": "Info",
"Value": "info"
},
{
"Name": "State",
"Value": "TN"
}
],
"XMin": "-1",
"XMax": "-1",
"YMin": "1",
"YMax": "1"
}
I was able to solve this by dynamically flattening the data model and adding columns once the store has been loaded. Although this breaks the MVC structure this was the best solution I came up with so it might be able to help you.
var defaultColumns = [];
var store = Ext.getStore('store');
store.on('load', function (store) {
var model = store.model;
var fields = model.getFields();
store.getAt(0).MetadataStore.data.items.forEach(function (item, index) {
var header = item.data.Name;
//isField returns a boolean if the field is already part of the data model
if (!isField(fields, header)) {
//Add a new metadata field to the data model
var field = { name: header, mapping: 'Metadata[' + index + '].Value' }
fields.push(field)
//Add a new metadata column
var column = {
header: header,
dataIndex: header,
sortable: true,
filterable: true,
filter: {
type: 'list'
},
flex: 0.2
}
defaultColumns.push(column);
}
});
model.setFields(fields);
//reload the grid after adding columns
var gridView = Ext.ComponentQuery.query('gridpanel')[0];
gridView.reconfigure(store, defaultColumns);
});
//reload the data after creating new fields
store.load();
I then set the columns of the grid to defaultColumns.
{
xtype: 'grid',
store: 'Projects',
overflowX: 'auto',
autoScroll: true,
features: [filters],
columns: defaultColumns
}

Kendo UI Dropdownlist checked

I have a kendo ui function dropdownlist, and it will call at Grid column editor. My question, by default how to display "Yes" when Add New Record in edit function. Currently it display null when Add New Record.
Demo in Dojo
Here I provide a working demo. Thank You
If I understand correctly you only have to add a default value to the Price in the Model?
"Price": {type: "string", defaultValue: "y" },
I include the whole function, just in case:
$(function() {
$("#grid").kendoGrid({
dataSource: {
data: [
{ Name: "Young John", Price: "y" },
{ Name: "John Doe", Price: "n" },
{ Name: "Old John", Price: "y" }
],
schema: {
model: {
id: "id",
fields: {
"id": { type: "number" },
"Price": {type: "string", defaultValue: "y" },
}
}
}
},
editable: "inline",
toolbar: ["create"],
columns: [{ field: "Name"},
{ field: "Price",
template: "#=(data.Price == 'y' ? 'Yes' : 'No')#",
editor: radioPrice
} ],
edit: function(e) {
if (e.model.isNew()) {
e.model.Price = 'y';
}
}
});
});

Why sometimes kendo UI Grid can not show the data?

My problem is: when I change db.Contacts.Where( x => x.Id > 100).Select(...), The KendoUI Grid cannot show the data. However, when x=>x.Id < 100, it can show the data.
If I delete the Where(...), it also can not show the data.
What is the wrong? Thank you very much.
Here is my code.
public class HelloOneController : Controller
{
......
public JsonResult Contacts_Read()
{
var query = db.Contacts.Where(x => x.Id < 100 )
.Select(x => new
{
Id = x.Id,
Email = x.Email,
FirstName = x.FirstName,
LastName = x.LastName
}).ToList();
}
return Json(query, JsonRequestBehavior.AllowGet);
}
......
}
$("#grid").kendoGrid({
dataSource: {
transport: {
read: "/HelloOne/Contacts_Read",
dataType: "json"
},
schema: {
model:{
fields: {
Id: { type: "number" },
Email: { type: "string" },
FirstName: { type: "string" },
LastName: { type: "string" }
}
}
},
pageSize: 20
},
height: 500,
groupable: false,
sortable: true,
pageable: {
refresh: true,
pageSizes: true,
buttonCount: 5
},
columns: [
{ title: "Id", field: "Id", width: 50 },
{ title: "Email", field: "Email" },
{ title: "First Name", field: "FirstName" },
{ title: "Last Name", field: "LastName" }
]
});

Collapse all nodes initially Infragistics IgTree

I am using the following Infragistics component for viewing hierarchical data. http://www.igniteui.com/tree/drag-and-drop-single-tree
I have initialized the tree view like below to see all the nodes of the tree expanded initially. Can someone please suggest me if I am missing any option to display all nodes collapsed initially?
$("#tree").igTree({
checkboxMode: "off",
singleBranchExpand: true,
nodeClick: function (evt, ui) {
if (ui.node.data.Folder == "") {
var agreements = [];
var entry = [];
entry.push(ui.node.data.AgreementNbr);
entry.push(ui.node.data.ExternalDescription);
entry.push(ui.node.data.Description);
entry.push(ui.node.data.EffDate);
entry.push(ui.node.data.ExpDate);
entry.push(ui.node.data.ReleaseStatus);
agreements.push(entry);
$('#example').DataTable({
responsive: true,
columns: [
{ title: "Agreement Number" },
{ title: "External Description" },
{ title: "Description" },
{ title: "Effective Date." },
{ title: "Expiry Date" },
{ title: "Release Status" }
],
data: agreements,
destroy: true,
processing: true,
});
}
else {
var output = ui.node.data.Folder.map(function (obj) {
var a = [obj.AgreementNbr, obj.ExternalDescription, obj.Description, obj.EffDate, obj.ExpDate, obj.ReleaseStatus];
return Object.keys(a).map(function (key) {
return a[key];
});
});
console.log(output);
$('#example').DataTable({
responsive: true,
columns: [
{ title: "Agreement Number" },
{ title: "External Description"},
{ title: "Description"},
{ title: "Effective Date"},
{ title: "Expiry Date"},
{ title: "Release Status"}
],
data : output,
destroy: true
});
}
},
dataSource: files,
dataSourceType: "json",
initialExpandDepth: 0,
pathSeparator: ".",
bindings: {
textKey: "Text",
valueKey: "Value",
imageUrlKey: "ImageUrl",
childDataProperty: "Folder",
Description: "Description"
},
// Enable Drag-and-drop feature
dragAndDrop: false
});
Use the initialExpandDepth option
initialExpandDepth : -1
You have that option set to 0.
If you set the initialExpandDepth to -1, all nodes should display collapsed initially.
You can see infragistics.com for more information.

Can we filter the data from exact data not from filtered data?

In my project had a kendo grid with filtering, filtering is working fine,but data is not clearing dynamically while filter is cleared. filter data is cleared by button click how to clear without "clear" button click.My grid code is
var grid = $("#grid").kendoGrid({
dataSource: {
type : "odata",
transport : {
read: "http://demos.kendoui.com/service/Northwind.svc/Orders"
},
schema : {
model: {
fields: {
OrderID : { type: "number" },
Freight : { type: "number" },
ShipName : { type: "string" },
OrderDate: { type: "date" },
ShipCity : { type: "string" }
}
}
},
pageSize : 10
},
filterable: true,
sortable : true,
pageable : true,
columns : [
{
field : "OrderID",
filterable: false
},
"Freight",
{
field : "OrderDate",
title : "Order Date",
width : 100,
format: "{0:MM/dd/yyyy}"
},
{
field: "ShipName",
title: "Ship Name",
width: 200
},
{
field: "ShipCity",
title: "Ship City"
}
]
}).data("kendoGrid");
The only thing I can think of is to use the parameterMap function (when type is 'read') to get rid of the filters that you do not need and always send only the last item of filters array.

Categories