salesforce 零基础学习(七十)使用jquery tree实现树形结构模式
项目中UI需要用到树形结构显示内容,后来尽管不需要做了,不过还是自己做着玩玩,mark一下,免得以后项目中用到。
实现树形结构在此使用的是jquery的dynatree.js。关于dynatree的使用可以参考:http://wwwendt.de/tech/dynatree/doc/dynatree-doc.html#h4.2
对于树形结构,这里不做太多介绍,树一般需要一个根节点,根节点下面可以有很多子节点或者叶子节点,子结点也可以包含叶子结点或者子节点。我们在设计表结构的时候可以考虑自连接操作,实现节点之间的关联,表结构如下:

我们想要实现的数据结构如下。

对应的数据如下:

在设计树形结构的前台展示时,应该有如下信息:
- 节点名称
- 节点编号
- 当前节点对应的父节点
- 当前节点是否为叶子节点
- 当前节点是否有子节点
- 当前节点如果包含子节点情况下子节点的列表
对于程序设计,主要分成两个步骤:
- 递归将数据存储到自定义结构中;
- 对结构进行json处理,json串应该满足相关的结构,即类似JSONObject{JSONArray[...]}相关模式,可以查看上方链接了解详情。
代码如下:
1.TreeUtil:实现递归对节点关系获取以及json转换;
public without sharing class TreeUtil {
// map to hold roles with Id as the key
private static Map <Id, Tree__c> treeMap;
// map to hold child roles with parentRoleId as the key
private static Map <Id, List<Tree__c>> parentNodeToChildNodeMap;
private static List<NodeWrapper> nodes{get;set;}
private static JSONGenerator gen {get; set;}
private static Tree__c rootNode{get;set;}
static {
initTreeDatas();
}
public static void initTreeDatas() {
treeMap = new Map<Id,Tree__c>([SELECT IsLeafNode__c, ParentNode__c, Id, Name FROM Tree__c order by ParentNode__c]);
parentNodeToChildNodeMap = new Map<Id,List<Tree__c>>();
for(Tree__c tree : treeMap.values()) {
List<Tree__c> tempList;
if(parentNodeToChildNodeMap.containsKey(tree.ParentNode__c)) {
tempList = parentNodeToChildNodeMap.get(tree.ParentNode__c);
tempList.add(tree);
parentNodeToChildNodeMap.put(tree.ParentNode__c,tempList);
} else {
tempList = new List<Tree__c>();
tempList.add(tree);
if(tree.ParentNode__c != null) {
parentNodeToChildNodeMap.put(tree.ParentNode__c,tempList);
} else {
rootNode = tree;
}
}
}
}
private static void convertNodeToJSON(NodeWrapper nw){
gen.writeStartObject();
if(!nw.isLeafNode) {
gen.writeStringField('title', nw.nodeName);
gen.writeStringField('key', nw.nodeId);
gen.writeBooleanField('unselectable', false);
gen.writeBooleanField('expand', true);
gen.writeBooleanField('isFolder', true);
if (nw.hasChildNodes) {
gen.writeFieldName('children');
gen.writeStartArray();
for (NodeWrapper r : nw.childNodes) {
convertNodeToJSON(r);
}
gen.writeEndArray();
}
} else {
gen.writeStringField('title', nw.nodeName);
gen.writeStringField('key', nw.nodeId);
}
gen.writeEndObject();
}
public static NodeWrapper createNode(Tree__c tree) {
NodeWrapper n = new NodeWrapper();
n.nodeName = tree.Name;
n.nodeId = tree.Id;
n.parentNodeId = tree.ParentNode__c;
if(tree.IsLeafNode__c) {
n.isLeafNode = true;
n.hasChildNodes = false;
} else {
List<NodeWrapper> nwList = new List<NodeWrapper>();
if(parentNodeToChildNodeMap.get(tree.Id) != null) {
n.hasChildNodes = true;
n.isLeafNode = false;
for(Tree__c tempTree : parentNodeToChildNodeMap.get(tree.Id)) {
nwList.add(createNode(tempTree));
}
n.childNodes = nwList;
}
}
return n;
}
public static String getTreeAndSubTrees() {
gen = JSON.createGenerator(true);
NodeWrapper node = createNode(rootNode);
gen.writeStartArray();
convertNodeToJSON(node);
gen.writeEndArray();
return gen.getAsString();
}
public class NodeWrapper {
//current node name
public String nodeName{get;set;}
//current node id
public String nodeId{get;set;}
//if current node isn't root,set it's parent parentNodeId
public String parentNodeId{get;set;}
//if this node set as a parent node,does it has child node
public Boolean hasChildNodes{get;set;}
//if current node is leaf node,set to true
public Boolean isLeafNode{get;set;}
//all of child nodes of current node
public List<NodeWrapper> childNodes{get;set;}
public NodeWrapper() {
hasChildNodes = false;
}
}
}
2.TreeController:调用TreeUtil实现数据获取
public class TreeController {
public Boolean selectable {get; set;}
public String selectNodeKeys {get; set;}
public TreeViewController(){
selectable = false;
selectNodeKeys = 'No value selected';
}
public String JsonData {get; set;}
public String getJsonString() {
if (JsonData == null){
JsonData = TreeUtil.getTreeAndSubTrees();
}
return JsonData;
}
}
3.TreeComponent:通过jquery的dyna tree 库实现树形结构实现
<apex:component controller="TreeController">
<apex:attribute name="selectable" type="Boolean" assignTo="{!selectable}" description=""/>
<apex:attribute name="value" type="String" description=""/>
<apex:attribute name="JsonData" type="String" assignTo="{!JsonData}" description=""/>
<apex:inputHidden id="selectedKeys" value="{!value}" />
<apex:includeScript value="{!URLFOR($Resource.DynaTree, 'jquery/jquery.js' )}" />
<apex:includeScript value="{!URLFOR($Resource.DynaTree, 'jquery/jquery-ui.custom.js' )}" />
<apex:includeScript value="{!URLFOR($Resource.DynaTree, 'jquery/jquery.cookie.js' )}" />
<apex:includeScript value="{!URLFOR($Resource.DynaTree, 'src/jquery.dynatree.js' )}" /> <apex:stylesheet value="{!URLFOR($Resource.DynaTree, 'src/skin/ui.dynatree.css')}" />
<script type="text/javascript">
$(function(){ $("#tree").dynatree({
onActivate: function(node) { },
persist: false,
checkbox: {!selectable},
generateIds: false,
classNames: {
checkbox: "dynatree-checkbox",
expanded: "dynatree-expanded"
},
selectMode: 3,
children: {!JsonString},
onSelect: function(select, node) {
var selKeys = $.map(node.tree.getSelectedNodes(), function(node){
return node.data.key;
});
jQuery(document.getElementById("{!$Component.selectedKeys}")).val(selKeys.join(", "));
var selRootNodes = node.tree.getSelectedNodes(true);
var selRootKeys = $.map(selRootNodes, function(node){
return node.data.key;
});
},
});
});
</script> <div id="tree"> </div> </apex:component>
4.TreeView.page:调用component实现显示
<apex:page controller="TreeController">
<apex:form >
<c:TreeView selectable="true"value="{!selectedValues}" />
<br/>
Value:<apex:outputText value="{!selectedValues}" />
<br/>
<apex:commandButton value="Get Value" />
</apex:form>
</apex:page>
效果展示:

总结:实现树形结构可以有多种js库选择,后台大部分需要做的就是拼json串,通过指定的要求实现前台的展示,了解树形结构如何设计更加重要。本篇只是抛砖引玉,有对树形结构感兴趣的可以将此作为参考并进行优化。内容有错误的地方欢迎指出,篇中有不懂得欢迎留言。
salesforce 零基础学习(七十)使用jquery tree实现树形结构模式的更多相关文章
- salesforce 零基础学习(十九)Permission sets 讲解及设置
Permission sets以及Profile是常见的设置访问权限的方式. Profile规则为'who see what'.通过Profile可以将一类的用户设置相同的访问权限.对于有着相同Pro ...
- salesforce 零基础学习(十八)WorkFlow介绍及用法
说起workflow大家肯定都不陌生,这里简单介绍一下salesforce中什么情况下使用workflow. 当你分配许多任务,定期发送电子邮件,记录修改时,可以通过自动配置workflow来完成以上 ...
- salesforce 零基础学习(十六)Validation Rules & Date/time
上一篇介绍的内容为Formula,其中的Date/time部分未指出,此篇主要介绍Date/time部分以及Validation rules. 本篇参考PDF: Date/time:https://r ...
- salesforce零基础学习(八十)使用autoComplete 输入内容自动联想结果以及去重实现
项目中,我们有时候会需要实现自动联想功能,比如我们想输入用户或者联系人名称,去联想出系统中有的相关的用户和联系人,当点击以后获取相关的邮箱或者其他信息等等.这种情况下可以使用jquery ui中的au ...
- salesforce零基础学习(八十九)使用 input type=file 以及RemoteAction方式上传附件
在classic环境中,salesforce提供了<apex:inputFile>标签用来实现附件的上传以及内容获取.salesforce 零基础学习(二十四)解析csv格式内容中有类似的 ...
- salesforce 零基础学习(五十二)Trigger使用篇(二)
第十七篇的Trigger用法为通过Handler方式实现Trigger的封装,此种好处是一个Handler对应一个sObject,使本该在Trigger中写的代码分到Handler中,代码更加清晰. ...
- salesforce 零基础学习(六十八)http callout test class写法
此篇可以参考: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_restfu ...
- salesforce零基础学习(八十二)审批邮件获取最终审批人和审批意见
项目中,审批操作无处不在.配置审批流时,我们有时候会用到queue,related user设置当前步骤的审批人,审批人可以一个或者多个.当审批人有多个时,邮件中获取当前记录的审批人和审批意见就不能随 ...
- salesforce零基础学习(一百一十)list button实现的一些有趣事情
本篇参考: salesforce零基础学习(九十五)lightning out https://developer.salesforce.com/docs/component-library/docu ...
随机推荐
- ueditor+word粘贴上传
公司做的项目要用到文本上传功能. 网上找了很久,大部分都有一些不成熟的问题,终于让我找到了一个成熟的项目. 下面就来看看: 1.打开工程: 对于文档的上传我们需要知道这个项目是否符合我们的初衷. 运行 ...
- 树形控件(CTreeCtrl和CTreeView)
如何插入数据项目? 如何添加鼠标右击事件? 插入数据项 通过InsertItem()方法,有四种重载样式: HTREEITEM InsertItem(LPTVINSERTSTRUCT lpInsert ...
- PHP后台评论 接口
/** * 添加评论 * content 评论内容 * addtime 评论时间 * uid 评论作品 */ public function padd(){ $param=input('param.' ...
- Scala_关键字
关键字 Lazy Scala中用lazy定义的变量叫惰性变量,会实现延迟加载:惰性变量只能是不可变变量,而且只有在调用惰性变量时,才会去实列化这个变量 object ScalaLazyDemo1{ ...
- Vue的配置
一.build:打包的配置文件的文件夹 1.build.js 生产版本的配置文件,一般这个文件我们是不改的 'use strict' //调用检查版本的文件,check-versions的导出直接是 ...
- Elasticsearch 系列3 --- Elasticsearch配置
一. 位置 ES的配置文件位于安装目录\config下面,主要有 (1) elasticsearch.yml ES系统的配置: (2) jvm.options Java虚拟机配置: (3) log4j ...
- 机器学习实战-ch3-决策树
决策树是一种新算法: 优点:计算复杂度不高,输出结果易于理解,对中间值的缺失不敏感,可以处理不相关特征数据.缺点:可能会产生过度匹配问题. 决策树算法可用于数据类型:数值型和标称型. 决策树的核心在于 ...
- DotNetCore依赖注入实现批量注入
文章转载自平娃子(QQ:273206491):http://os.pingwazi.cn/resource/batchinjectservice 一.依赖注入 通过依赖注入,可以实现接口与实现类的松耦 ...
- WPF学习笔记(5):两个DataGrid的滚动条实现同步滚动
效果:两个DataGrid的滚动条实现同步滚动. 代码参考了博客园chuncn的文章<.net中同步多个ScrollViewer滚动的四种方法>,原文是针对ListBox的.现改为针对Da ...
- WPF 嵌入Winform GDI 、 开启AllowsTransparenc问题
此文章可以解决2至少2个问题: 1.开启AllowsTransparenc造成的GDI+组件不显示问题 2.WPF 组件无法覆盖嵌入WPF窗口的任何第三方GDI+组件上层 方案1:自制双层 原理:用一 ...