I recently needed to build an “admin” screen for a webapp using ExtJS 4. The wireframe called for a tree to navigate the various admin settings, including settings for individual users (something like what you see at right). To build a tree like this with ExtJS, you usually use the Ext.tree.Panel class (a.k.a., a TreePanel). Unfortunately I couldn’t find any examples of how to make a TreePanel with a mixture of both static and dynamic nodes, so figuring it out took longer than it should have. With that in mind, I thought I’d share what I learned.
A working example of the solution I came up with is shown below (if the embedded version doesn’t appear for some reason, you can open it here). Note that you can actually run the code in your browser and see the results–just click the play button. Or if you’d like to modify it, click the “+” button to copy the code into your own project on JSFiddle.
The first thing the code does is define a basic model class for user data, called UserModel:
- Ext.define('demo.UserModel', {
- extend: 'Ext.data.Model',
- fields: ['id', 'name', 'profile_image_url']
- });
The next thing it does is set up a TreeStore to load the UserModel instances:
- var userTreeStore = Ext.create('Ext.data.TreeStore', {
- model: 'demo.UserModel',
- proxy: {
- type: 'jsonp', // Because it's a cross-domain request
- url : 'https://api.twitter.com/1/lists/members.json?owner_screen_name=Sencha&slug=sencha-team&skip_status=true',
- reader: {
- type: 'json',
- root: 'users' // The returned JSON will have array
- // of users under a "users" property
- },
- // Don't want proxy to include these params in request
- pageParam: undefined,
- startParam: undefined,
- pageParam: undefined,
- pageParam: undefined
- },
- ...
- });
Note that for this example we’ll be using Twitter as our data source for faux “users”; the UserModel fields are set up to match JSON from the Twitter API (specifically, people who are a member of the “Sencha Team” Twitter list) and we need to use a JSONP proxy to make cross-domain requests (i.e., the demo is hosted at jsfiddle.net but it’s connecting to api.twitter.com). Here’s an easy-to-read sample of what the data looks like:
The next part requires a little more explanation. First, let’s look at the code:
- var userTreeStore = Ext.create('Ext.data.TreeStore', {
- model: 'demo.UserModel',
- ...
- listeners: {
- // Each demo.UserModel instance will be automatically
- // decorated with methods/properties of Ext.data.NodeInterface
- // (i.e., a "node"). Whenever a UserModel node is appended
- // to the tree, this TreeStore will fire an "append" event.
- append: function( thisNode, newChildNode, index, eOpts ) {
- // If the node that's being appended isn't a root node, then we can
- // assume it's one of our UserModel instances that's been "dressed
- // up" as a node
- if( !newChildNode.isRoot() ) {
- // The node is a UserModel instance with NodeInterface
- // properties and methods added. We want to customize those
- // node properties to control how it appears in the TreePanel.
- // A user "item" shouldn't be expandable in the tree
- newChildNode.set('leaf', true);
- // Use the model's "name" value as the text for each tree item
- newChildNode.set('text', newChildNode.get('name'));
- // Use the model's profile url as the icon for each tree item
- newChildNode.set('icon', newChildNode.get('profile_image_url'));
- newChildNode.set('cls', 'demo-userNode');
- newChildNode.set('iconCls', 'demo-userNodeIcon');
- }
- }
- }
- });
- userTreeStore.setRootNode({
- text: 'Users',
- leaf: false,
- expanded: false // If this were true, the store would load itself
- // immediately; we do NOT want that to happen
- });
This doesn’t look like a “normal” Ext.data.Store. For one thing, it has an “append” event handler that receives “nodes”–objects that have methods and properties from the Ext.data.NodeInterface class. Secondly, the store has a setRootNode()
method that we’re calling with a config object for NodeInterface. What’s going on?
The important thing to understand here is that a TreeStore manages Ext.data.Model instances–just like any other Store–but it copies NodeInterface methods/properties into every model so that they can be linked together into a hierarchy (i.e., a tree). In this case, every instance of demo.UserModel
now has NodeInterface properties like “leaf” and “text” (which indicate if the item should be expandable when it’s displayed in a TreePanel, and what text should be shown).
Next, understand that when we call setRootNode({...})
, the TreeStore implicitly creates a generic Ext.data.Model instance for us, adds the NodeInterface method/properties, and then makes it the root node; when the UserModels are loaded, they will be added as “children” to this node. What we end up with is a TreeStore with models organized into a hierarchy, each one having properties that a TreePanel can use for displaying it:
The next thing the code does is create a separate TreeStore with some “static” nodes (again, using NodeInterface config properties).
- var settingsTreeStore = Ext.create('Ext.data.TreeStore', {
- root: {
- expanded: true,
- children: [
- {
- text: 'Settings',
- leaf: false,
- expanded: true,
- children: [
- {
- text: 'System Settings',
- leaf: true
- },
- {
- text: 'Appearance',
- leaf: true
- }
- ]
- }
- ]
- }
- });
Finally, we get the root of our userTreeStore and append it as a child to the “static” TreeStore. Then it’s just a matter of creating the TreePanel.
- // Graft our userTreeStore into the settingsTreeStore. Note that the call
- // to .expand() is what triggers the userTreeStore to load its data.
- settingsTreeStore.getRootNode().appendChild(userTreeStore.getRootNode()).expand();
- Ext.create('Ext.tree.Panel', {
- id: 'usersTreePanel',
- title: 'Admin Control Panel',
- renderTo: Ext.getBody(),
- height: 300,
- width: 300,
- store: settingsTreeStore,
- rootVisible: false
- });
In other words, you can “graft” TreeStores onto other TreeStores–this is the key to creating tree panels with a mixture of different data sources and underlying Models. The prerequisite, however, is understanding the NodeInterface. Hopefully this post will help others learn how to get started with TreePanels and TreeStores more quickly.
相关推荐
ExtJs4 Checkbox tree
针对数据库数据量大做的报表, 采用晚上执行存储过程按权限来生成不同的json文件, 按登陆用户读取不同的json文件。 不是完整的项目,只有java代码。
Extjs的tree Extjs的tree Extjs的tree Extjs的tree Extjs的tree
extjs的tree的使用.doc
Ext_Tree 树形菜单
ExtJs 2.2.1 tree实例,内附mysql数据文件 1. 数据节点一次性加载 2. 节点分为两个类(项目和设备) 3. 右键菜单 4. 节点增、删、改操作 ....... 后台是java struts1。 本例旨在说明extjs的tree操作,后台操作很简陋...
Extjs的Tree和Pane配合使用使用json做tree数据交互,感谢csdn,所以我也得做些贡献,获得一些积分
ExtJs Tree
Extjs Tree + JSON + Struts2 示例源代码
将文件拷贝到extjs根目录下。运行即可。实现了选中之类。父类联动选中
NULL 博文链接:https://esayjava.iteye.com/blog/499176
extjs spring tree ajax树的事项,希望对大家有帮助,从别的地方下的
最近在学习extjs tree,有两个不错的例子,希望对需要的朋友有所帮助!
利用extjs框架实现的后台经典显示, tree框架,动态加载。
extjs tree 学习资料extjs tree 学习资料extjs tree 学习资料extjs tree 学习资料
java写的Extjs异步树形控件示例,可直接部署
extjs tree 异步加载树型完整的一个web工程,自已已经试过,可用。
Ext各种组件的使用实例,Extjs tree+grid+form+panel 使用实例
区别在于,远程脚本调用方式加载树节点信息使用的是WebInvokeTreeLoader,需要通过fn属性来指定用于加载数据的远程方法,并在...而传统的树节点加载器是Ext.tree.TreeLoader,需要指定一个url来获得json数据。
extjs开发树效果,tree,菜单效果。所用语言java。很不错的,可以运行的。