I am in trouble trying to load a very simple json where nodes are nested inside "data" as showed below. I expect to get two nodes with text AAA and BBB, but I only get a tree with a couple of empty nodes with infinite children (each children with a single sub children).
test_lrymgr.json
{
"data": [
{
"text": ".",
"children": [
{
"nodename": "AAA",
"isvisible": true,
"expanded": false
},
{
"nodename": "BBB",
"isvisible": true,
"expanded": false
}
]
}
],
"metadata": { "success":true, "msg":"", "totalCount":1, "totalPages":1, "prevLink":"", "nextLink":""}
}
test_lrymgr.html
<html>
<head>
<link rel="stylesheet" type="text/css" href="ext/packages/ext-theme-classic/build/resources/ext-theme-classic-all.css" />
<script type="text/javascript" src="ext/ext-all-debug.js"></script>
</head>
<body>
<script type="text/javascript">
Ext.onReady(function () {
try {
//define model
Ext.define('MyDataModel', {
extend: 'Ext.data.Model',
fields: [
{ name: 'nodename', mapping: 'nodename' },
{ name: 'isvisible', mapping: 'isvisible' }
],
});
//define store
Ext.define('MyStore', {
extend: 'Ext.data.TreeStore',
storeId: 'idStoreLryManager',
model: 'MyDataModel',
proxy: {
type: 'ajax',
url: 'test_lrymgr.json',
reader: {
type: 'json',
root: 'data',
metaProperty: 'metadata',
totalProperty: 'metadata.totalCount',
successProperty: 'metadata.success',
messageProperty: 'metadata.msg'
},
}
});
//define tree panel
Ext.define('MyTreePanel', {
extend: 'Ext.tree.Panel',
alias: 'widget.myTreePanel',
store: 'MyStore',
rootVisible: false,
columns: [
{
xtype: 'treecolumn',
dataIndex: 'nodename',
sortable: false,
flex: 2,
header: ''
},
{
xtype: 'checkcolumn',
dataIndex: 'isvisible',
sortable: false,
width: 55,
header: 'Visible'
}
]
});
//create tree view
var storeInstance = Ext.create('MyStore');
Ext.createWidget('window', {
title: 'test',
layout: 'fit',
autoShow: true,
height: 360,
width: 200,
items: {
xtype: 'myTreePanel',
store: storeInstance,
border: false
}
});
//load
storeInstance.load({
scope: storeInstance,
callback: function (records, operation, success) {
try {
}
catch (ex) {
Ext.Msg.alert("", "callback error: " + ex);
}
}
});
}
catch (ex)
{
Ext.Msg.alert("", ex)
}
});
</script>
</body>
</html>
Any idea about what's wrong?...
Your json over here is wrong.Root mentioned in the store is "data".So
your json should be something like this:
{
"data": [{
"nodename": "child1",
"data": [{
"nodename": "subChild1",
"expanded": false,
"leaf": true
}, {
"nodename": "subChild2",
"expanded": false,
"leaf": true
}]
}],
"metadata": {
"success": true,
"msg": "",
"totalCount": 1,
"totalPages": 1,
"prevLink": "",
"nextLink": ""
}
}
For the tree to read nested data, the Ext.data.reader.Reader must be configured with a root property, so the reader can find nested data for each node (if a root is not specified, it will default to 'children'). This will tell the tree to look for any nested tree nodes by the same keyword, i.e., 'children'. If a root is specified in the config make sure that any nested nodes with children have the same name. Note that setting defaultRootProperty accomplishes the same thing.
You can see the simples possible tree configuration here: http://extjs.eu/ext-examples/#tree-simplest
Related
Context
I want to use cytoscape.js for visualizing graphs. While I am capable with a myriad of languages (C++, Mathematica, R, etc), I am new to Javascript, JSON, HTML, and CSS. Thus it would be favorable to learn these languages through this use case (implementing graphs with cytoscape.js). Please keep this in mind in your answer.
I have previously asked how to [remotely load cytoscape.js and how to get graphs display (requires a div). Since then I have created a script that turns a graph as represented in one of the other languages I use, into the JSON format indicated here. While I can just copy-paste all of this directly into my program, for large networks that is clearly a poor way to implement it. An example of my script's output is at the bottom of this.
Question
Given a JSON object/file(?) how can I do the following:
load it into cytoscape.js without copy-pasting the code.
referencing it once loaded. (e.g. basic explanation of how JSON syntax for use in cytoscape.js)
Script Output
cytoscape({
container: document.getElementById('cy'),
elements: [
{// node Node 1
group: 'nodes',
data: {
id: 'Node 1'
},
selected: false,
selectable: true,
locked: false,
grabbable: true,
selectable: true,
},
{// node Node 2
group: 'nodes',
data: {
id: 'Node 2'
},
selected: false,
selectable: true,
locked: false,
grabbable: true,
selectable: true,
},
{// node Node 3
group: 'nodes',
data: {
id: 'Node 3'
},
selected: false,
selectable: true,
locked: false,
grabbable: true,
selectable: true,
},
{// edge 1_2
group: 'edges',
data: {
id: '1_2',
source: '1',
target: '2'
}
},
{// edge 2_3
group: 'edges',
data: {
id: '2_3',
source: '2',
target: '3'
}
},
{// edge 3_1
group: 'edges',
data: {
id: '3_1',
source: '3',
target: '1'
}
}
],
style: [
{
selector: 'node',
style: {
'content': 'data(id)'
}
}
]
});
<head>
<title></title>
<script src="js/vendor/cytoscape.min.js"></script>
<script src="js/vendor/jquery.min.js"></script>
</head>
<style>
#cy {
width: 100%;
height: 100%;
position: absolute;
top: 0px;
left: 0px;
}
</style>
<body>
<div id="cy"></div>
<script>
$.getJSON("cyto.js", function (data) {
//console.log(data);
var cy = cytoscape({
container: document.getElementById('cy'),
elements: data,
style: [
{
selector: 'node',
style: {
'label': 'data(label)',
'width': '60px',
'height': '60px',
'color': 'blue',
'background-fit': 'contain',
'background-clip': 'none'
}
}, {
selector: 'edge',
style: {
'text-background-color': 'yellow',
'text-background-opacity': 0.4,
'width': '6px',
'target-arrow-shape': 'triangle',
'control-point-step-size': '140px'
}
}
],
layout: {
name: 'circle'
}
});
});
</script>
</body>
in cyto.js you can input valid JSON data, for example
{
"nodes": [
{
"data": {"id": "a", "label": "Gene1"}
},
{
"data": {"id": "b", "label": "Gene2"}
},
{
"data": {"id": "c", "label": "Gene3"}
},
{
"data": {"id": "d", "label": "Gene4"}
},
{
"data": {"id": "e", "label": "Gene5"}
},
{
"data": {"id": "f", "label": "Gene6"}
}
],
"edges": [
{
"data": {
"id": "ab",
"source": "a",
"target": "b"
}
},
{
"data": {
"id": "cd",
"source": "c",
"target": "d"
}
},
{
"data": {
"id": "ef",
"source": "e",
"target": "f"
}
},
{
"data": {
"id": "ac",
"source": "a",
"target": "d"
}
},
{
"data": {
"id": "be",
"source": "b",
"target": "e"
}
}]
}
Let's presume you have a json file in the same folder as your 'index.html', and your server is running. First request the json file via a http request (using plain javascript or jquery ).
If your json file has the same format as the elements properties, you can just parse it to a javascript object and set it. E.g.
var myObject = {};
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
myObject = JSON.parse(this.responseText);
initCytoscape();
}
};
xhttp.open("GET", "myJson.json", true);
xhttp.send();
function initCytoscape() {
cytoscape({
container: document.getElementById('cy'),
elements: myObject
});
}
if the json property is different than cytoscape's format, then you have to programatically convert it.
I have a tree, which only loads 3 level at a time.
So when a user click on expand on a node, extjs will call a service and populate with the leaf nodes of that node. How can I acchieve this? For now, i'm only able to load all of the nodes at once, which is a huge performance hit if there is lot of nodes.
Model:
Ext.define("TreePanelResult", {
extend: 'Ext.data.TreeModel',
fields: [
{ name: "orgId", type: "int"},
{ name: "orgName", type: "string"},
{ name: "OrgShortName", type : "string"},
{ name: "iconCls", type: "string"},
{ name: "leaf", type: "bool" }
],
idProperty:'orgId'
});
ViewModel:
Ext.define('SampleViewModel', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.sampleTreeModel',
stores: {
treeStore: {
type: 'tree',
model:TreePanelResult,
root: {
text: 'Org',
id:'src',
expanded: true,
orgId: -1
},
paramNode:'orgId',
proxy: {
type: 'ajax',
url: 'services/admin/getHirerachy',
reader : {
type : 'json',
rootProperty : 'systemChildNodes'
}
},
listeners: {
beforeload: function(store, operation, eOpts) {
operation.params.node = operation.node.get("orgId");
store.getProxy().setExtraParams("orgId", operation.node.get("orgId"));
}
}
}
}
});
JSON Stucture:
{
"status": true,
children:null,
"systemChildNodes": [
{
"orgId": "234334",
"orgParentId": "0",
"OrgShortName": "csdsdsd",
"iconCls": "",
"leaf": false,
"systemChildNodes": [
{
"orgId": "2345446",
"orgParentId": "234334",
"OrgShortName": "sdewew",
"iconCls": "",
"leaf": false,
"systemChildNodes": []
}
{
"orgId": "2345446",
"orgParentId": "234334",
"OrgShortName": "sdewew",
"iconCls": "",
"leaf": false,
"systemChildNodes": []
}
]
}]
}
Any suggestions would be appreciated.
Thanks in Advance,
Sankar.
I have a php-script, which returns the following JSON
[
{
"Code":0,
"Message":"No problem"
},
{
"name":"o016561",
"status":1,
"locks":[
{
"ztn":"155320",
"dtn":"20131111",
"idn":"78"
},
{
"ztn":"155320",
"dtn":"20131111",
"idn":"91"
}
]
},
{
"name":"o011111",
"status":1,
"locks":[
{
"ztn":"155320",
"dtn":"20131111",
"idn":"91"
}
]
},
{
"name":"o019999",
"status":0,
"locks":[
]
},
{
"name":"o020000",
"status":0,
"locks":[
]
},
{
"name":"o020001",
"status":0,
"locks":[
]
}
]
Edit:
The grid should look something like this:
I've been able to load name and status into my grid - so far so good. But the more important part is, that I need the nested data in the locks-array being loaded into my grid, but I just can't get my code working. Any help would be appreciated.
I'm using ExtJS 4.2 if that matters.
Edit 2:
I tried
Ext.define("Locks", {
extend: 'Ext.data.Model',
fields: [
'ztn',
'dtn',
'idn'
]
});
Ext.define("ConnectionModel", {
extend: 'Ext.data.Model',
fields: ['name', 'status'],
hasMany: [{
model: 'Locks',
name: 'locks'
}]
});
var store = Ext.create('Ext.data.Store', {
model: "ConnectionModel",
autoLoad: true,
proxy: {
type: 'ajax',
reader: {
type: 'json',
root: 'name'
}
}
});
but it seemed to be wrong in multiple ways...
and it would be awesome if ztn and dtn could be displayed just seperated with a whitespace in the same column
You can add a renderer to the column. In that renderer you can do anything with the record...
Here's a working fiddle:
http://jsfiddle.net/Vandeplas/MWeGa/3/
Ext.create('Ext.grid.Panel', {
title: 'test',
store: store,
columns: [{
text: 'Name',
dataIndex: 'name'
}, {
text: 'Status',
dataIndex: 'status'
}, {
text: 'idn',
renderer: function (value, metaData, record, rowIdx, colIdx, store, view) {
values = [];
record.locks().each(function(lock){
values.push(lock.get('idn'));
});
return values.join('<br\>');
}
}, {
text: 'ztn + dtn',
renderer: function (value, metaData, record, rowIdx, colIdx, store, view) {
values = [];
record.locks().each(function(lock){
values.push(lock.get('ztn') + ' ' + lock.get('dtn'));
});
return values.join('<br\>');
}
}],
height: 200,
width: 600,
renderTo: Ext.getBody()
});
Note
If you have control over your backend you better change the form of your data more like this:
{
"code": 0,
"message": "No problem",
"success": true,
"data": [
{
"name": "o016561",
"status": 1,
"locks": [
{
"ztn": "155320",
"dtn": "20131111",
"idn": "78"
},
{
"ztn": "155320",
"dtn": "20131111",
"idn": "91"
}
]
},
{
"name": "o011111",
"status": 1,
"locks": [
{
"ztn": "155320",
"dtn": "20131111",
"idn": "91"
}
]
}
]
}
That way you don't mix your control data (success, message, code,...) with your data and the proxy picks it up correctly (it can be a cause of the problems your experiencing). I added a success boolean => Ext picks it up and goes to the failure handler. It helps a lot with your exception handling.
Here is the proxy for it:
proxy: {
type: 'ajax',
api: {
read: ___URL____
},
reader: {
type: 'json',
root: 'data',
messageProperty: 'message'
}
}
I'm trying to load a store from JSON received from webservices. But all the data from the JSON goes under the 'raw' column of the items in the store...
I can't figure out why, my code seems correct.
Any help is welcome.
My Model :
Ext.define('App.model.Node', {
extend: 'Ext.data.Model',
config: {
fields: [
{ name: 'id', type: 'int' },
{ name: 'version', type: 'int' },
{ name: 'user_id', type: 'int' },
{ name: 'tstamp', type: 'date' },
{ name: 'changeset_id', type: 'int' },
{ name: 'tags', type: 'string' },
{ name: 'geom', type: 'string'}
],
idProperty: 'id'
}
});
My Store :
Ext.define('App.store.NodeStore', {
extend: 'Ext.data.Store',
xtype: 'nodestore',
requires: [
'Ext.data.proxy.Rest'
],
config: {
model: 'App.model.Node',
storeId: 'nodeStore',
autoLoad: true,
proxy: {
type:'rest',
url:'http://localhost/server/nodes',
reader: {
type:'json',
rootProperty: 'nodes'
},
noCache: false,
limitParam: false,
headers: {
'Accept' : 'application/json'
}
}
}
});
My JSON :
{
"nodes": [
{
"id": "454467",
"version": 6,
"user_id": 52015,
"tstamp": "2008-12-27 21:38:45",
"changeset_id": "634766",
"tags": "",
"geom": "0101000020E6100000409CD1A0B29321405455682096804740"
},
{
"id": "454468",
"version": 8,
"user_id": 52015,
"tstamp": "2009-12-23 20:47:15",
"changeset_id": "3437205",
"tags": "",
"geom": "0101000020E6100000357C0BEBC69321409EC02ACD9C804740"
},
{
"id": "454469",
"version": 7,
"user_id": 52015,
"tstamp": "2009-12-23 20:47:15",
"changeset_id": "3437205",
"tags": "",
"geom": "0101000020E6100000347914F8D4932140B8BBBD5AA4804740"
}
]
}
And when I do a
var nodeStore = Ext.getStore('nodeStore');
nodeStore.load();
console.log(nodeStore.getData());
we can see the following object, with my data in the raw column under items...
I figured it out, my code is correct and the only thing missing is a callback in the load() function :
nodeStore.load({
callback: function(records, operation, success) {
console.log(records);
console.log(nodeStore.getCount());
nodeStore.each(function(element) {
console.log(element.data.id);
});
},
scope: this,
});
The problem was I was trying to access the store before it loaded the data. Now I'm waiting that all the data is loaded to access it, and it works.
I am new to Sencha touch and need your help to resolve the issue. I am trying to display the list of children text using following JSON and Sencha touch code. I looked thorough the API and found that the Child data can be accessed, but then I am not sure how I can send that back to Panel/Store to display the list as
Child 21
Child 22
I have nested JSON data as follows:
{
"items":[
{
"id":"1",
"text": "Parent 1",
"leaf": false,
"items": [
{
"id":1,
"text": "child 1",
"leaf": true
},
{
"id":2,
"text": "child 2",
"leaf": true
}
]
},
{
"id":"2",
"text": "Parent 2",
"leaf": false,
"items": [
{
"id":3,
"text": "child 21",
"leaf": true
},
{
"id":4,
"text": "Child 22",
"leaf": true
}
]
}
]
}
Now my sencha touch code is as follows:
Ext.ns('MyApp');
MyApp.Child= Ext.regModel(Child, {
fields: ['id','text','day','date'],
belongsTo: 'Parent',
idProperty:'id',
proxy: {
type: 'rest',
url: 'test.json'
}
});
MyApp.Parent = Ext.regModel('Parent', {
fields: [
{name: 'id', type: 'int'},
{name: 'text', type: 'string'}
] ,
associations: [
{ type: 'hasMany', model: 'Child', name: 'items'}
],
proxy: {
type: 'ajax',
url: 'test.json'
}
});
MyApp.parentStore = new Ext.data.Store({
model : 'Parent',
proxy: {
type: 'rest',
url: 'test.json',
reader: {
type: 'json',
root : 'items'
}
},
autoLoad:true
});
MyApp.parentStore.filter('id','2');
// Do something here to get the list of child items.
// MyApp.childStore = ?
MyApp.appList = new Ext.Panel ({
fullscreen : true,
dockedItems : [
{
xtype : 'toolbar',
title : 'Applications',
dock : 'top'
}
],
items: [{
xtype: 'list',
store: MyApp.childStore, // ??????
itemTpl: '<div class="contact"><strong>{text}</strong></div>'
}]
});
From what I understand what you need to do is a NestedList
Have a look at these links:
http://www.sencha.com/learn/intro-to-the-nested-list-component/
https://github.com/nelstrom/Sencha-Touch-nested-list-demo