项目中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实现树形结构模式的更多相关文章

  1. salesforce 零基础学习(十九)Permission sets 讲解及设置

    Permission sets以及Profile是常见的设置访问权限的方式. Profile规则为'who see what'.通过Profile可以将一类的用户设置相同的访问权限.对于有着相同Pro ...

  2. salesforce 零基础学习(十八)WorkFlow介绍及用法

    说起workflow大家肯定都不陌生,这里简单介绍一下salesforce中什么情况下使用workflow. 当你分配许多任务,定期发送电子邮件,记录修改时,可以通过自动配置workflow来完成以上 ...

  3. salesforce 零基础学习(十六)Validation Rules & Date/time

    上一篇介绍的内容为Formula,其中的Date/time部分未指出,此篇主要介绍Date/time部分以及Validation rules. 本篇参考PDF: Date/time:https://r ...

  4. salesforce零基础学习(八十)使用autoComplete 输入内容自动联想结果以及去重实现

    项目中,我们有时候会需要实现自动联想功能,比如我们想输入用户或者联系人名称,去联想出系统中有的相关的用户和联系人,当点击以后获取相关的邮箱或者其他信息等等.这种情况下可以使用jquery ui中的au ...

  5. salesforce零基础学习(八十九)使用 input type=file 以及RemoteAction方式上传附件

    在classic环境中,salesforce提供了<apex:inputFile>标签用来实现附件的上传以及内容获取.salesforce 零基础学习(二十四)解析csv格式内容中有类似的 ...

  6. salesforce 零基础学习(五十二)Trigger使用篇(二)

    第十七篇的Trigger用法为通过Handler方式实现Trigger的封装,此种好处是一个Handler对应一个sObject,使本该在Trigger中写的代码分到Handler中,代码更加清晰. ...

  7. salesforce 零基础学习(六十八)http callout test class写法

    此篇可以参考: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_restfu ...

  8. salesforce零基础学习(八十二)审批邮件获取最终审批人和审批意见

    项目中,审批操作无处不在.配置审批流时,我们有时候会用到queue,related user设置当前步骤的审批人,审批人可以一个或者多个.当审批人有多个时,邮件中获取当前记录的审批人和审批意见就不能随 ...

  9. salesforce零基础学习(一百一十)list button实现的一些有趣事情

    本篇参考: salesforce零基础学习(九十五)lightning out https://developer.salesforce.com/docs/component-library/docu ...

随机推荐

  1. Java安全技术

    分类     Java平台安全,即JRE安全     开发Java程序(普通程序,服务,applet)安全,即提供安全的开发工具和服务.   用法     用签名和安全策略控制远程的资源访问

  2. 51nod 1239 欧拉筛模板

    #include<iostream> #include<cmath> #include<cstring> #include<cstdio> #inclu ...

  3. 去除html页面中GET《 http://localhost:8080/favicon.ico 404 (Not Found)》

    html5页面中经常会遇见以下问题,总是看着碍眼,那么怎么解决呢? GET http://localhost:8080/favicon.ico 404 (Not Found) 解决的方法: <l ...

  4. 状态 ajax

    //html部分 <a href="#" data-status="{$vo.state}" data-urid="{$vo.id}" ...

  5. python学习之高阶函数

    filter函数:filter()为已知的序列的每个元素调用给定的布尔函数,调用中,返回值为非零的元素将被添加至一个列表中 list = filter(调用函数名,可迭代对象)——调用函数名自动传参— ...

  6. Tomcat数据源配置方法总结

    最近接触的数据表管理项目,涉及到了数据源配置,所以整理了一下配置方法: JNDI数据源统一都是在Tomcat下server.xml中配置的,根据应用范围的差别又分为一下几种方式: 第一种:配置单个应用 ...

  7. Flume source 支持的type类型

    Flume是一个分布式的高可用的消费组件.通过修改配置文件,可以启动不同的agent处理不同来源的数据. agent包含source,channel,sink三个组件.今天我们学习下source的ty ...

  8. Spring @Autowired注解用在集合上面,可以保持接口的所有实现类

    CourseService课程接口有2个子类,HistroyCourseServiceImpl和MathsCourseServiceImpl public interface CourseServic ...

  9. ASP.NET Web API 中使用 swagger 来管理 API 文档

    本文以 ASP.NET Web API 为后台框架,利用 EF6 连接 postgreSQL 数据库,使用 swagger 来生成 REST APIs文档.文章分二个部分,第一部分主要讲如何用 EF6 ...

  10. 背水一战 Windows 10 (48) - 控件(集合类): FlipView

    [源码下载] 背水一战 Windows 10 (48) - 控件(集合类): FlipView 作者:webabcd 介绍背水一战 Windows 10 之 控件(集合类) FlipView 示例Fl ...