I have a remote data and I am trying to build Kendo UI Chart's DataSource. The remote data represents a generic data model for most charts. The model goes like this,
model: {
fields: {
Title: { field: "Title", type: "string" },
XLabel: { field: "XLabel", type: "string" },
YLabel: { field: "YLabel", type: "string" },
Legend: [
{?????????{ type: "string" }}
]
},
hasChildren: true,
children: "ChartDataSets"
}
}
Sample of remote data:
{
"Chart": [
{
"Title": "1",
"XLabel": "",
"YLabel": "",
"Legend": [ "P1","P2","P3"],
"ChartDataSets": [
{
"GroupName": "Week 0",
"Series": [
{
"Key": "2015",
"Value": 42
},
{
"Key": "2016",
"Value": 42
}
]
},
{
"GroupName": "Week 1",
"Series": [
{
"Key": "2015",
"Value": 52
},
{
"Key": "2016",
"Value": 32
}
]
}
]
}
]
}...
So Legend is an array of strings and ChartDataSets is an array of json objects. How do I represent Legend as an array or that it has children?
Also, would you recommend using Hierarchical DataSource? How is the performance affected if I use Hierarchical DataSource?
__________Never Mind - Found it ____________
Solution:
model: {
fields: {
Title: { field: "Title", type: "string" },
XLabel: { field: "XLabel", type: "string" },
YLabel: { field: "YLabel", type: "string" },
Legend: [{field: "Legend"}]
},
hasChildren: true, ...
Related
I'm trying to code an example that shows two dropdowns: one for countries, and one for related states/provinces. When you choose a country on the first dropdown, the values of the second dropdown should be updated to display only the provinces/states of the selected country. Usually this is accomplished using some sort of Ajax call, but in this case the requirement is to try it purely with react-jsonschema-form. Is this actually possible ? I have seen several examples using dependencies / references, but none solving this particular scenario.
So far I came up with this: https://codesandbox.io/s/fervent-cherry-lokjk?file=/src/App.js
{
"definitions": {
"Countries": {
"title": "Country",
"type": "object",
"properties": {
"country": {
"type": "string",
"enum": [
"CANADA",
"USA",
"MEXICO"
]
}
},
"dependencies": {
"country": {
"oneOf": [
{
"properties": {
"country": {
"enum": [
"CANADA"
]
},
"province": {
"type": "string",
"title": "Province",
"enum": [
"AB",
"BC",
"MB"
]
}
}
},
{
"properties": {
"country": {
"enum": [
"USA"
]
},
"province": {
"type": "string",
"title": "State",
"enum": [
"AL",
"AK",
"AR"
]
}
}
},
{
"properties": {
"country": {
"enum": [
"MEXICO"
]
},
"province": {
"type": "string",
"title": "State",
"enum": [
"AGS",
"BC",
"BCS"
]
}
}
}
]
}
}
}
},
"title": "Demo for countries",
"type": "object",
"properties": {
"currentCountry": {
"$ref": "#/definitions/Countries",
"title": "Select country / province / state"
}
}
}
which basically can render a Country dropdown and a State/Province dropdown. When selecting a country, the corresponding state/province dropdown is updated correctly with the new set of enum values.
However, with this approach, the form will submit a field named "currentCountry" with two properties inside, the country and the province
currentCountry: { country: "USA" , province: "AL" }
but of course the idea is to submit "country" and "province" as two different form fields, without the need to be wrapped.
So, does anyone know how to achieve this typical use case ? Is there any best approach to it using JSON schemas ?
Maybe having to code a custom widget ? (I would like to avoid that if possible)
Thanks in advance !
After playing a bit more, seems I found the solution. A correct schema that does exactly what is needed is this one:
{
title: "Demo for countries",
type: "object",
properties: {
country: {
type: "string",
title: "Country",
enum: ["CANADA", "USA", "MEXICO"]
}
},
dependencies: {
country: {
oneOf: [
{
properties: {
country: {
enum: ["CANADA"]
},
province: {
type: "string",
title: "Province",
enum: ["ALBERTA", "BRITISH COLUMBIA", "MANITOBA"]
}
}
},
{
properties: {
country: {
enum: ["USA"]
},
province: {
type: "string",
title: "State",
enum: ["ALABAMA", "OREGON", "ARKANSAS"]
}
}
},
{
properties: {
country: {
enum: ["MEXICO"]
},
province: {
type: "string",
title: "State",
enum: ["JALISCO", "BAJA CALIFORNIA", "CHIAPAS"]
}
}
}
]
}
}
}
and the above codesandbox example has been updated to reflect this change.
Happy to know this scenario can be achieved with JSON schemas !
I am trying to create a tree from json file. The JSON data is:
[
{
"root": {
"text": "Root Node",
"expanded": true,
"children": [
{
"text": "Invisible",
"leaf": true,
"children": [
{
"text": "Bookmark 2",
"leaf": true
},
{
"text": "Bookmark 3",
"leaf": true
}
]
},
{
"text": "Visible",
"leaf": true,
"children": [
{
"text": "Bookmark 4",
"leaf": true
},
{
"text": "Bookmark 5",
"leaf": true
}
]
}
]
}
}
]
Here is the code I am using for my store:
Ext.define('DHT.store.Categories', {
extend: 'Ext.data.TreeStore',
model: 'DHT.model.Category',
autoLoad: true,
autoSync: true,
proxy: {
type: 'ajax',
url: 'treedata.json',
reader:
{
type: 'json'
}
}
});
and here is the code for tree:
Ext.define('DHT.view.Category.CategoryList', {
extend: 'Ext.tree.Panel',
alias: 'widget.treeList',
width: 200,
height: 400,
store: Ext.create('DHT.store.Categories'),
rootVisible: false
});
The above code is only showing folder image that keep on expanding! Can someone point out the problem?
You have leaf: true and children, this is not possible
{
"text": "Invisible",
"leaf": true,
"children": [
{
"text": "Bookmark 2",
"leaf": true
},
...
]
}
correct:
{
"text": "Invisible",
"leaf": false,
"children": [
{
"text": "Bookmark 2",
"leaf": true
},
...
]
}
You have to define a root property in your treestore
The root property needs to be consistent, in your case it would be 'root', 'children', 'children'
Read this: Treepanel with nested data from JSON
What could I be doing wrong; I only get -1 when I do a search of a store?
My model
Ext.define('app.model.Sections', {
extend: 'Ext.data.Model',
config: {
fields: [{
name: 'id',
type: 'int'
}, {
name: 'title',
type: 'string'
}, {
name: 'content',
type: 'string'
}]
}
});
My Store
Ext.define('app.store.Sections', {
extend: 'Ext.data.TreeStore',
requires: [
'app.model.Sections'
],
config: {
autoLoad: true,
model: 'app.model.Sections',
proxy: {
type: 'ajax',
url: 'resources/data/data.json',
reader: {
type: 'json',
rootProperty: 'items'
}
}
}
});
The json file is like this
{
"items": [{
"id": "27",
"title": "Title 1",
"content": "",
"items": [{
"id": "85",
"title": "Title 2",
"content": "content 2",
"leaf": true
}, {
"id": "78",
"title": "Title 3",
"content": "content 3",
"leaf": true
}]
}, {
"id": "29",
"title": "Title 4",
"content": "",
"items": [{
"id": "97",
"title": "Title 5",
"content": "content 5",
"leaf": true
}, {
"id": "93",
"title": "Title 6",
"content": "content 6",
"leaf": true
}, {
"id": "105",
"title": "Title 7",
"content": "content 7",
"leaf": true
}]
}]
}
I am able to get the store and view the data in the store but the index always comes out -1
var store = Ext.getStore('Sections');
var index = store.findExact('id', 85);
console.log(store);
console.log(index);
I used carcel's suggestion to do the store.on('load', function ());.
I also changed the data type of id to string so there would be no confusion.
initialize: function() {
var sectionID = '85';
var store = Ext.getStore('Sections');
// search once the store is loaded
store.on('load', function() {
// get the node record
var record = store.getNodeById(sectionID);
if (record == null)
console.log('no record found');
else {
var parentPanel = Ext.getCmp('myabouttest');
parentPanel.setHtml(record.data.content);
var titlebar = Ext.getCmp('mytitilebar');
titlebar.setTitle(record.data.title);
}
}
});
}
The initialize function completes before the store can be loaded so to display the data I have to specify IDs for the panel and the title and then get their components to set the items.
I am trying to load some data from the json file hosted on the local server but I am getting an error "XMLHttpRequest cannot load http://localhost:8080/data.json?_dc=1355779280677&page=1&start=0&limit=25. Origin null is not allowed by Access-Control-Allow-Origin. " as soon as the application loads. My list is not populated with the records.
My code is as below.
Ext.define('POC.view.HomePage', {
extend: 'Ext.TabPanel',
requires:['Ext.TitleBar','Ext.dataview.List',
'Ext.Ajax','Ext.data.proxy.Ajax'],
xtype:'homePage',
alias: 'widget.wuHomePageView',
config: {
fullscreen: true,
items: [
{
title: 'Home',
iconCls: 'home',
items: [
{
xtype: 'list',
title: 'Sample',
height: '100%',
onItemDisclosure: true,
store: {
autoLoad: true,
fields: ['name'],
proxy: {
type: 'json',
url: 'http://localhost:8080/data.json',
reader: {
type: 'ajax',
rootProperty: 'stores'
}
}
},
itemTpl: '{name}',
}],
},
{
title: 'Contact',
iconCls: 'user',
html: 'Contact Screen'
}
]
},
});
My Json File is as below.
{
"stores": [
{
"name": "Science Gallery",
"logo": "sciencegallery.jpg",
"desc": "Get some food",
"telephone": "016261234",
"city": "Dublin",
"add1": "Pearse Street",
"post": "2",
"country": "Ireland",
"latitude": "53.34422",
"longitude": "-6.25006",
"menu": [
{
"item": "SC Sandwich"
},
{
"item": "SC Toasted Sandwich"
},
{
"item": "SC Panini"
},
{
"item": "SC Ciabatta"
},
{
"item": "SC Burrito"
}
]
},
{
"name": "Spar",
"logo": "spar.jpg",
"desc": "Get some food",
"telephone": "016261234",
"city": "Dublin",
"add1": "Mayor Street",
"post": "2",
"country": "Ireland",
"latitude": "53.34422",
"longitude": "-6.25006",
"menu": [
{
"item": "Spar Sandwich"
},
{
"item": "Spar Toasted Sandwich"
},
{
"item": "Spar Panini"
},
{
"item": "Spar Ciabatta"
},
{
"item": "Spar Burrito"
}
]
}
]
}
Please help.
Thanks
There is no such a thing like a json proxy! You have to use an ajax proxy:
proxy: {
type: 'ajax',
.....
}
I have a json file and I assume that I do not know anyting about the content. I do not know the model. However it is given in the json file the model, the data, and other information about the grid. How I'll create the columns etc in this way?
Stackoverflow is littered with questions very similar to this one. I worked through them all and did not find a definitive solution. However, most of the provided answers pointed me in the right direction. I'll give me best shot at putting all those suggestions together and making this clear for others:
Model: (Only shows 2 fields that will be in all JSON responses. Will still be overwritten)
Ext.define('RTS.model.TestsModel', {
extend: 'Ext.data.Model',
alias: 'model.TestsModel',
fields: [
{
name: 'poll_date'
},
{
name: 'poller'
}
]
});
Store:
Ext.define('RTS.store.TestsStore', {
extend: 'Ext.data.Store',
alias: 'store.TestsStore',
model: 'RTS.model.TestsModel',
constructor: function(cfg) {
var me = this;
cfg = cfg || {};
me.callParent([Ext.apply({
autoLoad: false,
proxy : {
type : 'ajax',
url : 'tests.php',
reader : {
type : 'json',
root : 'tests',
successProperty : 'success'
}
},
storeId: 'tests-store'
}, cfg)]);
}
});
View: (The columns will be defined in each JSON response)
Ext.define('RTS.view.TestsView', {
extend: 'Ext.grid.Panel',
alias: 'widget.TestsView',
id: 'tests-view',
title: 'Tests',
emptyText: '',
store: 'TestsStore',
initComponent: function() {
var me = this;
Ext.applyIf(me, {
viewConfig: {
},
columns: [
]
});
me.callParent(arguments);
}
});
Controller: (The controller does all the work in forcing the view and model to change based on the JSON response).
Ext.define('RTS.controller.TestsController', {
extend: 'Ext.app.Controller',
alias: 'controller.TestsController',
stores: [
'TestsStore'
],
models: [
'TestsModel'
],
views: [
'TestsView'
],
init: function(application) {
// When store changes, trigger an event on grid
// to be handled in 'this.control'.
// NOTE : Ext JS does not allow control of
// non-component events.
// Ext JS 4.2 beta will allow the controller
// to detect non-component changes and handle them
var testsStore = this.getStore('TestsStore');
testsStore.on("metachange", metaChanged, this);
function metaChanged(store, meta) {
var grid = Ext.ComponentQuery.query('TestsView')[0];
grid.fireEvent('metaChanged', store, meta);
};
this.control({
"TestsView": {
metaChanged: this.handleStoreMetaChange
}
});
},
/**
* Will update the model with the metaData and
* will reconfigure the grid to use the
* new model and columns.
*/
handleStoreMetaChange: function(store, meta) {
var testsGrids = Ext.ComponentQuery.query('TestsView')[0];
testsGrids.reconfigure(store, meta.columns);
}
});
JSON Response:
Your json response must have the "metaData" property included. It should define the fields just as you would on a static model and the view that would normally be defined to show the fields.
{
"success": true,
"msg": "",
"metaData": {
"fields": [
{
"name": "poller"
},
{
"name": "poll_date"
},
{
"name": "PING",
"type": "int"
},
{
"name": "SNMP",
"type": "int"
},
{
"name": "TELNET",
"type": "int"
},
{
"name": "SSH",
"type": "int"
},
{
"name": "all_passed"
}
],
"columns": [
{
"dataIndex": "poller",
"flex": 1,
"sortable": false,
"hideable": false,
"text": "Poller"
},
{
"dataIndex": "poll_date",
"flex": 1,
"sortable": false,
"hideable": false,
"text": "Poll Date"
},
{
"dataIndex": "PING",
"flex": 1,
"sortable": false,
"hideable": false,
"text": "PING",
"renderer": "RenderFailedTests"
},
{
"dataIndex": "SNMP",
"flex": 1,
"sortable": false,
"hideable": false,
"text": "SNMP",
"renderer": "RenderFailedTests"
},
{
"dataIndex": "TELNET",
"flex": 1,
"sortable": false,
"hideable": false,
"text": "TELNET",
"renderer": "RenderFailedTests"
},
{
"dataIndex": "SSH",
"flex": 1,
"sortable": false,
"hideable": false,
"text": "SSH",
"renderer": "RenderFailedTests"
},
{
"dataIndex": "all_passed",
"flex": 1,
"sortable": false,
"hideable": false,
"text": "All Passed",
"renderer": "RenderFailedTests"
}
]
},
"tests": [
{
"poller": "CHI",
"poll_date": "2013-03-06",
"PING": "1",
"SNMP": "0",
"TELNET": "1",
"SSH": "0",
"all_passed": "0"
},
{
"poller": "DAL",
"poll_date": "2013-03-06",
"PING": "1",
"SNMP": "0",
"TELNET": "1",
"SSH": "0",
"all_passed": "0"
},
{
"poller": "CHI",
"poll_date": "2013-03-04",
"PING": "1",
"SNMP": "0",
"TELNET": "1",
"SSH": "0",
"all_passed": "0"
},
{
"poller": "DAL",
"poll_date": "2013-03-04",
"PING": "1",
"SNMP": "0",
"TELNET": "1",
"SSH": "0",
"all_passed": "0"
},
{
"poller": "CHI",
"poll_date": "2013-03-01",
"PING": "1",
"SNMP": "0",
"TELNET": "1",
"SSH": "0",
"all_passed": "0"
}
]
}
http://docs.sencha.com/ext-js/4-1/#!/api/Ext.data.reader.Json -> Response MetaData section
in the grid don't forget to add this one columns: [], then under the store listeners: { 'metachange': function(store, meta) { myGrid.reconfigure(store, meta.columns); } } and the response json file should have metaData with fields and columns. Read Response MetaData section in the documentation for more info.
You can create grid definition in runtime. Look at the reconfigure method: http://docs.sencha.com/ext-js/4-0/#!/api/Ext.grid.Panel-method-reconfigure