Results 1 to 10 of 10

Thread: TreeGrid showing hierarchical json data

  1. #1
    Sencha User
    Join Date
    Aug 2011
    Posts
    5
    Vote Rating
    0
      0  

    Red face TreeGrid showing hierarchical json data

    I'm really struggling with this one. I've google-searched everything I can find, as well as read many articles on the forums about how to do so. I've tried all of the Sencha examples, and still haven't had any luck. I've hit my 8 hours trying with it, and figured I'd ask for help.


    I'm trying to take an existing set of JSON and build a TreeGrid (or even just a tree) with it, but can't seem to get the nodes to show the correct titles. I'm using ExtJS 4.0.2.


    I verified all of the obvious things - I can view the json through firebug/chrome, I can see that the treegrid object is being called, I have a number of other widgets on the page that are all working, etc.


    Here's one of my tries. Ideally, I'd like to have a treegrid that shows each Room (the higher-level objects), and have each conversation as a treenode under them, then a count of users in a column to the right. I'd settle for just a list of the rooms/conversations. Bonus points if you can show me how to also add a "+" icon to add a conversation to a room.


    Thanks much for any help in advance, I'm at laptop-flinging stage here.


    Source JSON:


    Code:
        [
          {
            "links": "[{\"title\":\"Google\",\"url\":\"http://google.com\",\"refreshes\":\"false\"}]",
            "visibility": "on",
            "description": "Fun",
            "name": "Glee",
            "_id": "4e793d957270340000000003",
            "conversations": [
              {
                "title": "Intro",
                "body": "",
                "blips": [          
                ],
                "created_at": "2011-09-21T01:27:49.942Z"
              }
            ],
            "users": [
              "4e72c4433aad74c628000005"
            ]
          },
          {
            "links": "[]",
            "visibility": "on",
            "description": "Fun2",
            "name": "Test",
            "_id": "4e793da07270340000000006",
            "conversations": [
              {
                "title": "Intro",
                "body": "",
                "blips": [          
                ],
                "created_at": "2011-09-21T01:28:00.307Z"
              }
            ],
            "users": [
              "4e72c4433aad74c628000005"
            ]
          }
        ]


    Treeview code:
    Code:
        		Ext.define('app.convStore', {
        		    extend: 'Ext.data.Model',
        		    fields: ['name', 'title']
        		});
        		
        		var roomStore = Ext.create('Ext.data.TreeStore', {
        		        model: 'app.convStore',
        				proxy: {
        		            type: 'ajax', //TODO: Move to Rest? Or maybe it can't support
        		            url: 'http://localhost:3000/test.json',
        					reader: {
        		                type: 'json'
        		            }
        		        },
        				id: 'roomStore'
        		    });
        
        //Created Object (hosting code removed):
        			        {
        			            xtype: 'treepanel',
        			            height: 504,
        			            title: 'Rooms',
        						id: 'treegrid_rooms_item',
        				        useArrows: true,
        			            store: roomStore,
        						rootVisible: false,
        						columns: [{
        							header: 'Room',
        							sortable: true,
        							dataIndex: ['name']
        						},{
        							header: 'Conversations',
        							sortable: true,
        							dataIndex: ['title'],
        							flex: 1
        						}],
        			            displayField: 'name'
        			        }

  2. #2
    Sencha User mberrie's Avatar
    Join Date
    Feb 2011
    Location
    Bangkok, Thailand
    Posts
    506
    Answers
    26
    Vote Rating
    19
      0  

    Default

    I have a question for you

    When reading your input JSON, how does the tree component know that you consider 'conversations' as the child items of your room nodes?

    When I compare the code from the TreeGrid example to your code, I can spot quite a view differences:


    Code:
        Ext.define('Task', {
            extend: 'Ext.data.Model',
            fields: [
                {name: 'task',     type: 'string'},
                {name: 'user',     type: 'string'},
                {name: 'duration', type: 'string'}
            ]
        });
    
        var store = Ext.create('Ext.data.TreeStore', {
            model: 'Task',
            proxy: {
                type: 'ajax',
                //the store will get the content from the .json file
                url: 'treegrid.json'
            },
            folderSort: true
        });
    
        //Ext.ux.tree.TreeGrid is no longer a Ux. You can simply use a tree.TreePanel
        var tree = Ext.create('Ext.tree.Panel', {
            title: 'Core Team Projects',
            width: 500,
            height: 300,
            renderTo: Ext.getBody(),
            collapsible: true,
            useArrows: true,
            rootVisible: false,
            store: store,
            multiSelect: true,
            singleExpand: true,
            //the 'columns' property is now 'headers'
            columns: [{
                xtype: 'treecolumn', //this is so we know which column will show the tree
                text: 'Task',
                flex: 2,
                sortable: true,
                dataIndex: 'task'
            },{
                //we must use the templateheader component so we can use a custom tpl
                xtype: 'templatecolumn',
                text: 'Duration',
                flex: 1,
                sortable: true,
                dataIndex: 'duration',
                align: 'center',
                //add in the custom tpl for the rows
                tpl: ..
            },{
                text: 'Assigned To',
                flex: 1,
                dataIndex: 'user',
                sortable: true
            }]
        });
    And the JSON:
    Code:
    {"text":".","children": [
        {
            task:'Project: Shopping',
            duration:13.25,
            user:'Tommy Maintz',
            iconCls:'task-folder',
            expanded: true,
            children:[{
                task:'Housewares',
                duration:1.25,
                user:'Tommy Maintz',
                iconCls:'task-folder',
                children:[{
                    task:'Kitchen supplies',
                    duration:0.25,
                    user:'Tommy Maintz',
                    leaf:true,
                    iconCls:'task'
                },{
                    task:'Groceries',
                    duration:.4,
                    user:'Tommy Maintz',
                    leaf:true,
                    iconCls:'task'
                },{
                    task:'Cleaning supplies',
                    duration:.4,
                    user:'Tommy Maintz',
                    leaf:true,
                    iconCls:'task'
                },{
                    task: 'Office supplies',
                    duration: .2,
                    user: 'Tommy Maintz',
                    leaf: true,
                    iconCls: 'task'
                }]
            }, {
                task:'Remodeling',
                duration:12,
                user:'Tommy Maintz',
                iconCls:'task-folder',
                expanded: true,
                children:[{
                    task:'Retile kitchen',
                    duration:6.5,
                    user:'Tommy Maintz',
                    leaf:true,
                    iconCls:'task'
                },{
                    task:'Paint bedroom',
                    duration: 2.75,
                    user:'Tommy Maintz',
                    iconCls:'task-folder',
                    children: [{
                        task: 'Ceiling',
                        duration: 1.25,
                        user: 'Tommy Maintz',
                        iconCls: 'task',
                        leaf: true
                    }, {
                        task: 'Walls',
                        duration: 1.5,
                        user: 'Tommy Maintz',
                        iconCls: 'task',
                        leaf: true
                    }]
                },{
                    task:'Decorate living room',
                    duration:2.75,
                    user:'Tommy Maintz',
                    leaf:true,
                    iconCls:'task'
                },{
                    task: 'Fix lights',
                    duration: .75,
                    user: 'Tommy Maintz',
                    leaf: true,
                    iconCls: 'task'
                }, {
                    task: 'Reattach screen door',
                    duration: 2,
                    user: 'Tommy Maintz',
                    leaf: true,
                    iconCls: 'task'
                }]
            }]
        },{
            task:'Project: Testing',
            duration:2,
            user:'Core Team',
            iconCls:'task-folder',
            children:[{
                task: 'Mac OSX',
                duration: 0.75,
                user: 'Tommy Maintz',
                iconCls: 'task-folder',
                children: [{
                    task: 'FireFox',
                    duration: 0.25,
                    user: 'Tommy Maintz',
                    iconCls: 'task',
                    leaf: true
                }, {
                    task: 'Safari',
                    duration: 0.25,
                    user: 'Tommy Maintz',
                    iconCls: 'task',
                    leaf: true
                }, {
                    task: 'Chrome',
                    duration: 0.25,
                    user: 'Tommy Maintz',
                    iconCls: 'task',
                    leaf: true
                }]
            },{
                task: 'Windows',
                duration: 3.75,
                user: 'Darrell Meyer',
                iconCls: 'task-folder',
                children: [{
                    task: 'FireFox',
                    duration: 0.25,
                    user: 'Darrell Meyer',
                    iconCls: 'task',
                    leaf: true
                }, {
                    task: 'Safari',
                    duration: 0.25,
                    user: 'Darrell Meyer',
                    iconCls: 'task',
                    leaf: true
                }, {
                    task: 'Chrome',
                    duration: 0.25,
                    user: 'Darrell Meyer',
                    iconCls: 'task',
                    leaf: true
                },{
                    task: 'Internet Exploder',
                    duration: 3,
                    user: 'Darrell Meyer',
                    iconCls: 'task',
                    leaf: true
                }]
            },{
                task: 'Linux',
                duration: 0.5,
                user: 'Aaron Conran',
                iconCls: 'task-folder',
                children: [{
                    task: 'FireFox',
                    duration: 0.25,
                    user: 'Aaron Conran',
                    iconCls: 'task',
                    leaf: true
                }, {
                    task: 'Chrome',
                    duration: 0.25,
                    user: 'Aaron Conran',
                    iconCls: 'task',
                    leaf: true
                }]
            }]
        }
    ]}

  3. #3
    Sencha User
    Join Date
    Aug 2011
    Posts
    5
    Vote Rating
    0
      0  

    Default Thanks

    You make a good point - I haven't told the component how to know what the children object is, or how to show it.

    Is there a way to have different names in the model for the treegrid to show both the parent or the child? Or, is my best option to go in and change the source json so that it follows that structure closer, with the same names for parents and children?

  4. #4
    Ext JS Premium Member tvanzoelen's Avatar
    Join Date
    Apr 2008
    Location
    Groningen - Netherlands
    Posts
    1,199
    Answers
    87
    Vote Rating
    44
      0  

    Default

    A node is a node. In the docs is written
    "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'."
    . In http://docs.sencha.com/ext-js/4-0/#!...data.TreeStore.

    So always return the same JSON structure.

    specify the root in the reader and your children are under the same root

    Code:
    {success: true, 
    data: [{id: '1', text: 'text', 
              data:[{id: '2', text: 'text'}]
              },
              { id: '3', text: 'text' }
             ]}
    
    or if you define children as root
    
    {success: true, 
    children: [{id: '1', text: 'text', 
             children:[{id: '2', text: 'text'}]
              },
              { id: '3', text: 'text' }
             ]}

  5. #5
    Sencha User mberrie's Avatar
    Join Date
    Feb 2011
    Location
    Bangkok, Thailand
    Posts
    506
    Answers
    26
    Vote Rating
    19
      0  

    Default

    Exactly!

    And Jay, your other misunderstanding is the column configuration. You cannot specify 'conversations' as a column like in the code you posted.

    When you look at the TreeGrid example above, you can see that they actually have a hierarchy of nodes that all are of the same 'type', that is they match the structure of the model!

    They specify one column as the 'treecolumn' and additional columns that will show up in the grid.

    I am no expert on the TreePanel and TreeGrid. But it seems that there is no official support for Tree nodes of mixed type. You can specify one Model, and if your nodes have different columns you most likely have to specify a model with a superset of ALL fields - if the incoming data has no value for this field it will just stay blank.

    Maybe tvanzoelen knows more about this!

  6. #6
    Ext JS Premium Member tvanzoelen's Avatar
    Join Date
    Apr 2008
    Location
    Groningen - Netherlands
    Posts
    1,199
    Answers
    87
    Vote Rating
    44
      0  

    Default

    I am sorry...mberry .. I did not use tree grids yet. I am migrating this moment, but I am interested in the solution.

  7. #7
    Sencha User
    Join Date
    Mar 2009
    Location
    South Africa
    Posts
    23
    Answers
    1
    Vote Rating
    0
      0  

    Default

    Hi,

    I am currently in the exact same situation, only I am trying to build it up using an aspx handler, but I am struggling getting it to write the JSON out in the right format.

    Any help would be much appreciated.

    Regards
    Remeez

  8. #8
    Sencha User
    Join Date
    Jul 2011
    Posts
    29
    Vote Rating
    0
      0  

    Question Indeed, how do you do?

    Quote Originally Posted by mberrie View Post
    I have a question for you

    When reading your input JSON, how does the tree component know that you consider 'conversations' as the child items of your room nodes?
    I need to solve the same issue.
    How did you do eventually?
    thks so much
    mario

  9. #9
    Sencha User
    Join Date
    Aug 2011
    Posts
    5
    Vote Rating
    0
      0  

    Default

    I eventually just crafted the JSON on the server so that it fir the way I wanted to show it in the tree. Works great.

    Here's example JSON:
    Code:
    [{"text":"Room: Lobby","_id":"424242424242424242424242","cls":"folder","expanded":true,"children":[{"text":"Conv: Lobby Chat","_id":"4e87ceb18b8ca50ffb000005","room_id":"424242424242424242424242","leaf":true,"checked":false},{"text":"*Add new Conversation","_id":"424242424242424242424242","leaf":true,"checked":false}]},{"text":"Room: Snores","_id":"4e86be0867960172c700000c","cls":"folder","expanded":true,"children":[{"text":"Conv: Yee Ha!","_id":"4e86be0867960172c700000e","room_id":"4e86be0867960172c700000c","leaf":true,"checked":false},{"text":"*Add new Conversation","_id":"4e86be0867960172c700000c","leaf":true,"checked":false}]},{"text":"Room: Pug Farts","_id":"4e8713cb7aac6cd6d1000004","cls":"folder","expanded":true,"children":[{"text":"Conv: 1111","_id":"4e8713cb7aac6cd6d1000006","room_id":"4e8713cb7aac6cd6d1000004","leaf":true,"checked":false},{"text":"Conv: 2","_id":"4e8713e57aac6cd6d1000012","room_id":"4e8713cb7aac6cd6d1000004","leaf":true,"checked":false},{"text":"Conv: 3333","_id":"4e8724d09a8b9077e4000005","room_id":"4e8713cb7aac6cd6d1000004","leaf":true,"checked":false},{"text":"*Add new Conversation","_id":"4e8713cb7aac6cd6d1000004","leaf":true,"checked":false}]},{"text":"*Add new Room","_id":"42","cls":"folder","expanded":false,"children":[]}]
    And the code for viewing it, along with event handlers (I'm still working on it to get the style just right, but it functions for now):
    Code:
    Ext.define("MyDesktop.roomsConversations", {
        extend: "Ext.ux.desktop.Module",
        requires: ['Ext.tree.*','Ext.data.*','Ext.window.MessageBox'],
    
    
        id: "roomsConversations",
    
    
        init: function () {
            this.launcher = {
                text: "Rooms & Conversations",
                iconCls: "cpu-shortcut",
                handler: this.createWindow,
                scope: this
            }
        },
        createWindow: function () {
            var store = Ext.create('Ext.data.TreeStore', {
                proxy: {
                    type: 'ajax',
                    url: '/desktop/userPrefs.json'
                },
                fields: ['_id','leaf','text'],
                autoSync: true
            });
    
    
            var b = this.app.getDesktop();
            var tree = b.createWindow({
                xtype: 'autoload-win',
                height: 272,
                width: 277,
                id: 'treegrid_rooms_window',
                autoScroll:true,
                title:'My Rooms and Conversations',
                items:[{
                    xtype:'treepanel',
                    rootVisible: false,
                    title: 'Check a conversation to show it',
                    id: 'treegrid_rooms_tree',
                    listeners:{
                        itemclick : function(view, rec, item, index, eventObj) {
    
    
                            if (eventObj && eventObj.target && eventObj.target.className && eventObj.target.className.indexOf("x-tree-checkbox") > -1) {
                                //Clicked on the check box
                                return;
                            }
                            var clickedon = {
                                "type": rec.raw.cls == 'folder' ? 'room' : 'conv',
                                "_id":rec.raw._id,
                                "room_id":rec.raw.room_id || 0,
                                "name": item.innerText,
                                "checked": rec.data.checked};
    
    
                            if (clickedon.name.indexOf('Add new Conversation') > -1) {
                                //And new conversation to room _id
                                appLaunchWidget('convSetup', clickedon._id);
    
    
                            } else if (clickedon.name.indexOf('Add new Room') > -1) {
                                //Show New Room Form
                                appLaunchWidget('roomSetup');
                            } else {
                               //Edit room or conv
                                if (clickedon.type == "room") {
                                    appLaunchWidget('roomSetup', clickedon._id);
                                } else {
                                    appLaunchWidget('convSetup', clickedon.room_id, clickedon._id);
                                }
                            }
    
    
                        },
                        'checkchange': function(node, checked) {
                            var type = node.raw.cls == 'folder' ? 'room' : 'conv';
                            var _ID = node.raw._id;
                            if (checked) {
                                if (type == 'conv') {
    //                                var roomName = roomNameFromConvID(_ID);
                                    var convTitle = convNameFromConvID(_ID);
                                    createConversationWindow(_ID, convTitle);
                                    //Show this conversation
                                }
                            } else {
                                //Hide this conv
                                if (type == 'conv') {
                                    closeConversationWindow(_ID);
                                }
                            }
                        }
                    },
    
    
                    height: 230,
                    width: 260,
                    useArrows: true,
                    autoScroll:true,
                    animate:true,
                    containerScroll: true,
                    store: store
                }]
            });
            tree.show();
    
    
    
    
        }
    });

  10. #10
    Sencha User
    Join Date
    Jul 2011
    Posts
    29
    Vote Rating
    0
      0  

    Default is "children" required?

    Hi JayCrossler, All,
    i see, and thks a lot for your reply.

    I still miss something very basic (I suspect)

    Consider the json example at ext-4.0.2a/docs/index.html#/api/Ext.data.reader.Reader

    Code:
    {
        "users": [
            {
                "id": 123,
                "name": "Ed",
                "orders": [
                    {
                        "id": 50,
                        "total": 100,
                        "order_items": [
                            {
                                "id"      : 20,
                                "price"   : 40,
                                "quantity": 2,
                                "product" : {
                                    "id": 1000,
                                    "name": "MacBook Pro"
                                }
                            },
                            {
                                "id"      : 21,
                                "price"   : 20,
                                "quantity": 3,
                                "product" : {
                                    "id": 1001,
                                    "name": "iPhone"
                                }
                            }
                        ]
                    }
                ]
            }
        ]
    }

    How do you show it as a tree whose first level nodes are users, second level are orders, and so on? I am unable to instruct extJS to consider 'orders' as children of a user.

    thanks cheers
    mario

    ps the point is: why do you give up to use
    "conversations": [
    Last edited by mario60; 2 Oct 2011 at 9:03 AM. Reason: better

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •