1
votes

Tree node with expandable property set to true and no children does not render the expand/collapse icon.

I need to develop tree control which loads sub-nodes on demand only. In other words, children should be loaded on node expand event. I've found that property 'expandable' set to true is supposed to render expand/collapse icon regardless of whether children exist or not. Could you please review my code and point out where I made mistake that 'expand/collapse icon' is rendered only for nodes with children.

Tree with store and model declared as follow:

Ext.define('Entity', {
        extend: 'Ext.data.Model',
        fields: [
            {name: 'name',     type: 'string'},
            {name: 'description',     type: 'string'},
            {name: 'clazz',     type: 'string'},
            {name: 'path;',     type: 'string'},
            {name: 'leaf',      type: 'boolean'},
            {name: 'expandable',type: 'boolean'},
            {name: 'allowChildren',      type: 'boolean'}
        ]
    });

var mpsStore = Ext.create('Ext.data.TreeStore', {
        model: 'Entity',
        proxy: {
            type: 'ajax',
            url: 'companyTree'
        }
    ,root: {
        name: '__ROOT__'
    }
    });

Ext.define('App.view.Navigation', {
    extend: 'Ext.tree.Panel',
    alias : 'widget.Navigation',
    title: '...',
    rootVisible: false,
    lines: false,
    useArrows: true,
    store: mpsStore
    ,columns: [{xtype: 'treecolumn',
                text: 'Business Entity',
                width: 150,
                dataIndex: 'name',
            },{ text: 'Description',
                dataIndex: 'description'
            }
    ]
});

Response json looks like:

{  
   "path":".",
   "id":"__ROOT__",
   "name":"__ROOT__",
   "user":null,
   "description":null,
   "clazz":null,
   "iconCls":null,
   "leaf":false,
   "expanded":true,
   "expandable":true,
   "allowChildren":true,
   "children":[  
      {  
         "path":".\\1",
         "id":"1",
         "name":"Company 1",
         "user":null,
         "description":null,
         "clazz":"companyViewId",
         "iconCls":"icon-organisation",
         "leaf":false,
         "expanded":false,
         "expandable":true,
         "allowChildren":true,
         "children":[  ]
      },
      {  
         "path":".\\2",
         "id":"2",
         "name":"Company 2",
         "user":null,
         "description":null,
         "clazz":"companyViewId",
         "iconCls":"icon-organisation",
         "leaf":false,
         "expanded":false,
         "expandable":true,
         "allowChildren":true,
         "children":[  
            {  
               "path":".\\2\\3",
               "id":"3",
               "name":"billTo 2.1",
               "user":null,
               "description":"2.1. Street Ave, unit 2.1",
               "clazz":"billToViewId",
               "iconCls":"icon-billto",
               "leaf":false,
               "expanded":false,
               "expandable":true,
               "allowChildren":true,
               "children":[  
                  {  
                     "path":".\\2\\3\\4",
                     "id":"4",
                     "name":"shipTo 2.1.1",
                     "user":null,
                     "description":"2.1. Street Ave, unit 2.1",
                     "clazz":"shipToViewId",
                     "iconCls":"icon-shipto",
                     "leaf":false,
                     "expanded":false,
                     "expandable":true,
                     "allowChildren":true,
                     "children":[  
                        {  
                           "path":".\\2\\3\\4\\5",
                           "id":"5",
                           "name":"machine2.1.1.1",
                           "user":null,
                           "description":"manufacturer, model",
                           "clazz":"machineViewId",
                           "iconCls":"icon-machine",
                           "leaf":false,
                           "expanded":false,
                           "expandable":true,
                           "allowChildren":true,
                           "children":[  ]
                        }
                     ]
                  },
                  {  
                     "path":".\\2\\3\\6",
                     "id":"6",
                     "name":"shipTo 2.1.2",
                     "user":null,
                     "description":"2.1. Street Ave, unit 2.1",
                     "clazz":"shipToViewId",
                     "iconCls":"icon-shipto",
                     "leaf":false,
                     "expanded":false,
                     "expandable":true,
                     "allowChildren":true,
                     "children":[  ]
                  }
               ]
            }
         ]
      },
      {  
         "path":".\\7",
         "id":"7",
         "name":"Company 3",
         "user":null,
         "description":null,
         "clazz":"companyViewId",
         "iconCls":"icon-organisation",
         "leaf":false,
         "expanded":false,
         "expandable":true,
         "allowChildren":true,
         "children":[  ]
      }
   ]
}

The result looks like

Tree with no expand/collapse icon for nodes without children

As you can see only one 'company' node has expand/collapse icon.

I've found only one advice for similar question Treepanel expand/collapse on a node without children Extjs which use css to hack the issue, but have no clue where to insert this style.

Thank you in advance.

Just for those who need 'end of story'.

If you rely on spring and jackson to render json in response and want to skip empty children, you can configure MappingJackson2HttpMessageConverter in yourApp-servlet.xml to do so.

<mvc:annotation-driven>
<mvc:message-converters>
<beans:bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<beans:property name="objectMapper" ref="objectMapper"/>
</beans:bean>
</mvc:message-converters>
</mvc:annotation-driven>
<beans:bean name="objectMapper" class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean" autowire="no">
<beans:property name="dateFormat">
<beans:bean class="java.text.SimpleDateFormat">
<beans:constructor-arg type="java.lang.String" value="yyyy-MM-dd HH:mm:ss"/>
</beans:bean>
</beans:property>
<beans:property name="featuresToDisable">
<beans:list>
<beans:value type="com.fasterxml.jackson.databind.SerializationFeature">WRITE_EMPTY_JSON_ARRAYS</beans:value>
</beans:list>
</beans:property>
</beans:bean>

Regards.

1

1 Answers

0
votes

You are providing children data for your nodes, thus ExtJS assume that the node is loaded.

Remove "children":[] for your lazy nodes, and a query will be made to load them on demand.

Then your server must return data for the provided node. For instance if you try to expand node "Company 1", a query should be like : http://localhost/?node=1

Also if your node doesn't have any children, you should set leaf to true.

As a side note, to reduce the amount of data transiting, many of your parameters (expandable, allowChildren, ...) can use or are the default value, and should be skipped.