注:本篇解决方案内容实现转自:http://mysalesforceescapade.blogspot.com/2015/03/getting-dependent-picklist-values-from.html

群里面有个小伙伴问了一个关于两个有Dependence关系的Picklist字段如何在Apex中通过control字段的值获取到Dependence字段的值,针对Salesforce配置来说,我们很好配置出两个Dependence字段的关系,通过点击设置一下include关系即可。如下图,我们在Goods__c自定义表中新建了两个Picklist类型字段,并且设置了依赖关系,这个在配置中清晰可见,如何在代码中获取呢?

首先我们最先想到的肯定是通过metadata,查一下Schema命名空间下的类得方法有没有直接可以搞定需求的,针对Picklist值,通常处理的类为Schema.PicklistEntry以及Schema.DescribeFieldResult这两个类,然而这两个类的API中并没有直接可以搞定需求的,只能判断出当前的字段是否为空值字段等信息。既然标准的API没有提供,那么就得想办法搞定了。我的第一次想法是这样的,尽管这种方式最终确认是失败的。

一.将两个依赖字段放置在页面中,Util方法读取页面中指定元素从而获取Control字段的某一个值情况下Dependence的值集合。(此方法已确认失败)

salesforce 零基础学习(六十二)获取sObject中类型为Picklist的field values(含record type) 写过关于读取中间页面获取含Record Type的Picklist field Values,是不是也可以将中间页面写两个apex:inputField设置级联关系,通过参数将需要读取的内容获取出来,从而实现需求?

1.PicklistParserController作为中间页的Controller,获取参数信息,通过参数对数据进行初始化处理。

public without sharing class PicklistParserController {

    public Sobject sobj {get;set;}
public String picklistFieldName {get;set;}
public String dependentPicklistListFieldName { get; set; }
public String picklistFieldValue { get; set; } public PicklistParserController() {
Map<String, String> requestMap = ApexPages.currentPage().getParameters();
String sobjId = requestMap.get('id');
String recordTypeId = requestMap.get('recordTypeId');
String sobjectTypeName = requestMap.get('sobjectType');
this.pickListFieldName = requestMap.get('picklistFieldName');
this.dependentPicklistListFieldName = requestMap.get('dependentPicklistListFieldName');
this.picklistFieldValue = requestMap.get('picklistFieldValue'); Schema.SobjectType sobjectType = null; if (sobjectTypeName != null && sobjectTypeName.trim().length() > 0) {
sobjectType = Schema.getGlobalDescribe().get(sobjectTypeName);
sobj = sobjectType.newSobject();
sobj.put('RecordTypeId', recordTypeid);
if(picklistFieldValue != null) {
sobj.put(pickListFieldName,picklistFieldValue);
}
} else if (sobjId != null && sobjId.trim().length() > 0) {
// find the so
for (SobjectType sobjType : Schema.getGlobalDescribe().values()){
String sobjPrefix = sobjType.getDescribe().getKeyPrefix();
if (sobjPrefix == null) continue;
if (sobjId.toLowerCase().startsWith(sobjPrefix.toLowerCase())) {
sobjectType = sobjType;
break;
}
}
sobj = Database.query ('SELECT ' + pickListFieldName + ',' + dependentPicklistListFieldName + ' FROM ' + sobjectType + ' WHERE ID =:sobjId');
}
System.debug(LoggingLevel.INFO, '*** sobj: ' + JSON.serialize(sobj));
}
}

2.PicklistParser.page 显示两个依赖关系字段

<apex:page controller="PicklistParserController"
contentType="application/xml" showHeader="false" sidebar="false"
standardStylesheets="false" language="en_US">
<apex:form >
<apex:inputField value="{!sobj[pickListFieldName]}" />
<apex:inputField value="{!sobj[dependentPicklistListFieldName]}" id="dependentPicklistListFieldName" required="true"/>
</apex:form>
</apex:page>

3.PicklistParserUtil:此方法用于查看解析中间页面的结果展示

public with sharing class PicklistParserUtil {public static String parseOptions(Map<String, String> params) {
Pagereference pr = Page.PicklistParser;
// to handle development mode, if ON
pr.getParameters().put('core.apexpages.devmode.url', '1');
System.debug(LoggingLevel.INFO, '*** params: ' + JSON.serialize(params));
for (String key : params.keySet()) {
pr.getParameters().put(key, params.get(key));
} String xmlContent = pr.getContent().toString();
return xmlContent;
} }

中间页面效果展示如下: 通过下图可以看到,当控制字段选择了某个以后,级联字段展示了其对应的依赖字段值。

测试代码如下:

Map<string,String> m = new Map<string,String>();
m.put('sobjectType', 'Goods__c');
m.put('picklistFieldName','TestP1__c');
m.put('dependentPicklistListFieldName','TestP2__c');
m.put('picklistFieldValue', '测试1');
System.debug(LoggingLevel.INFO, '*** : ' + PicklistParserUtil.parseOptions(m));

但是当解析这个输出结果时,发现输出的内容和设想的不太一样。原来设想的内容是解析的结果会有两个select option 区域,两个区域分别展示对应的value,后期只需要针对获取指定select下所有的option即可。然而实际的部分结果展示如下:

<select  id="j_id0:j_id1:j_id2" name="j_id0:j_id1:j_id2">
<option value="">--None--</option>
<option value="T1" selected="selected">T1</option>
<option value="T2">T2</option>
<option value="T3">T3</option>
<option value="T4">T4</option>
<option value="测试1">测试1</option>
<option value="测试2">测试2</option>
</select>
<div class="requiredInput"><div class="requiredBlock"></div><span>
<select id="j_id0:j_id1:dependentPicklistListFieldName" name="j_id0:j_id1:dependentPicklistListFieldName">
<option value="" selected="true">--None--</option>
</select></span></div><div id="j_id0:j_id1:j_id3">
<script>window.pl = window.pl &#124;&#124; {};
pl.map_00N0I00000JsNOk_01228000000U1u0={'T4':'DAAA','测试2':'IQAA','测试1':'ggAA','T1':'wAAA','T2':'MAAA','T3':'GAAA'};
pl.vals_00N0I00000JsNOk_01228000000U1u0=['TestS1','TestS1','TestS2','TestS2','TestS3','TestS3','TestS4','TestS4','TestS5','TestS5','TestS6','TestS6','测试S1','测试S1','测试S2','测试S2'];
pl.noneLabel="--None--";
pl.naLabel="\*\*Not Applicable\*\*";
pl.selectedLabel="Chosen";
pl.availableLabel="Available";
new picklist('j_id0:j_id1:dependentPicklistListFieldName','00N0I00000JsNOk_01228000000U1u0','00N0I00000JsNOk_01228000000U1u0','j_id0:j_id1:j_id2',['',''],' id=\"j_id0:j_id1:dependentPicklistListFieldName\" name=\"j_id0:j_id1:dependentPicklistListFieldName\"',false,true);
</script>
</div>

也就是说每次点击父的值情况下,js会动态通过当前的父的值获取子内容,通过解析页面方式无法获取其真实的依赖关系,所以此种方式弃用了。

二.使用PicklistEntry方式(正确方式)

此部分内容参考内容:

https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_calls_describesobjects_describesobjectresult.htm

http://mysalesforceescapade.blogspot.com/2015/03/getting-dependent-picklist-values-from.html

两个Picklist的Dependence肯定是以某种方式存储在MetaData中的,即使官方的API没有提供可以直接调用的方法获取到Dependence关系,肯定某个属性中也存储了这种关系。

通过第一个链接可以发现,PicklistEntry的validFor属性中存储了两者的关系,对于PicklistEntry来说,每一个Denpendence Picklist 的Value代表一个PicklistEntry。

每一个validFor属性存储了一组的Bits,每个bit对应着一个Control Field Picklist Value。官方的描述为 A set of bits where each bit indicates a controlling value for which this PicklistEntry is valid。validFor在java中返回类型为byte[],因为salesforce中没有byte这个基本类型,我们可以通过byte的性质,或者直接看byte在java中的定义,模拟出byte的Wrapper使用,官方给了一个java版的获取方式,下面的链接为国外一个大牛写的demo可以获取到Picklist中的Dependence关系,内容和java版的获取方式相差不大,区别为自己封装了一个Byte类。

代码测试:

System.debug(LoggingLevel.INFO, '*** : ' + JSON.serialize(new PicklistFieldController().getDependentOptionsImpl('Goods__c','TestP1__c','TestP2__c')));

结果展示:

总结:在Apex Class中获取Picklist间的级联关系,主要是通过PicklistEntry中的隐藏属性validFor获取其中的关系,并对返回的byte[]数组进行解析找到其对应的control的关系。篇中有错误地方欢迎指出,不懂的欢迎留言。

salesforce零基础学习(八十七)Apex 中Picklist类型通过Control 字段值获取Dependent List 值的更多相关文章

  1. 【转】【Salesforce】salesforce 零基础学习(十七)Trigger用法

    看本篇之前可以相应阅读以下Trigger相关文章: 1.https://developer.salesforce.com/page/Trigger_Frameworks_and_Apex_Trigge ...

  2. salesforce 零基础学习(十七)Trigger用法

    看本篇之前可以相应阅读以下Trigger相关文章: 1.https://developer.salesforce.com/page/Trigger_Frameworks_and_Apex_Trigge ...

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

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

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

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

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

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

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

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

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

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

  8. salesforce零基础学习(一百一十三)Trigger中获取IP地址的过程

    本篇参考: https://developer.salesforce.com/docs/atlas.en-us.228.0.apexcode.meta/apexcode/apex_class_Auth ...

  9. salesforce零基础学习(九十六)Platform Event浅谈

    本篇参考:https://developer.salesforce.com/blogs/2018/07/which-streaming-event-do-i-use.html https://trai ...

随机推荐

  1. MySQL单表百万数据记录分页性能优化,转载

    背景: 自己的一个网站,由于单表的数据记录高达了一百万条,造成数据访问很慢,Google分析的后台经常报告超时,尤其是页码大的页面更是慢的不行. 测试环境: 先让我们熟悉下基本的sql语句,来查看下我 ...

  2. Java 对IP请求进行限流.

    高并发系统下, 有三把利器 缓存 降级 限流. 缓存: 将常用数据缓存起来, 减少数据库或者磁盘IO 降级: 保护核心系统, 降低非核心业务请求响应 限流: 在某一个时间窗口内对请求进行限速, 保护系 ...

  3. [转]Nginx基本功能极速入门

    原文链接:Nginx基本功能极速入门 | 叉叉哥的BLOG 本文主要介绍一些Nginx的最基本功能以及简单配置,但不包括Nginx的安装部署以及实现原理.废话不多,直接开始. 1.静态HTTP服务器 ...

  4. handsontable 属性汇总

    常规属性: 1.固定行列位置 fixedRowsTop:行数 //固定顶部多少行不能垂直滚动 fixedColumnsLeft:列数 //固定左侧多少列不能水平滚动 2.拖拽行头或列头改变行或列的大小 ...

  5. TestNG的简单使用

    TestNG的简单使用 TestNG(Test Next Generation)是一个测试框架,其灵感来自JUnit和NUnit,但同时引入了一些新的功能,使其功能更强大,使用更方便. TestNG是 ...

  6. PPT分享 | 以太坊钱包分析与介绍

    艾伯特AI人工智能(公众号:aibbtcom)按: (编者按:本文为姗姗来迟的Meetup系列推文.12月3日,林修平在亚太区以太坊社区培训与交流Meetup深圳站上跟我们分享了他对以太坊各种钱包模式 ...

  7. 笔记:I/O流-内存映射文件

    内存映射文件时利用虚拟内存实现来将一个文件或者文件的一部分映射到内存中,然后整个文件就可以当作数组一样的访问,这个比传统的文件操作要快得多,Java 使用内存映射文件首先需要从文件中获取一个chann ...

  8. Redis登录密码设置

    1. 更改Redis.conf配置 # requirepass foobared 去掉注释,foobared改为 自己的password , 我测试的时候用的是默认的 foobared 2.启动red ...

  9. STL --> remove和remove_if()

    remove和remove_if() 一.Remove()函数 remove(beg,end,const T& value) //移除区间{beg,end)中每一个“与value相等”的元素: ...

  10. Algorithm --> 判读是否是子树

    问题 判断一棵树是否是另一棵树的子树,如图 思路 问题分两步: 找值相同的根结点(遍历解决) 判断两结点是否包含(递归:值.左孩子.右孩子分别相同) 树节点定义 struct TreeNode { i ...