salesforce零基础学习(八十七)Apex 中Picklist类型通过Control 字段值获取Dependent List 值
Posted zero.zhang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了salesforce零基础学习(八十七)Apex 中Picklist类型通过Control 字段值获取Dependent List 值相关的知识,希望对你有一定的参考价值。
注:本篇解决方案内容实现转自: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 || {}; 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方式(正确方式)
此部分内容参考内容:
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 值的主要内容,如果未能解决你的问题,请参考以下文章
Salesforce LWC学习 Dependence Picklist实现
salesforce零基础学习(八十六)Ajax Toolkit (VF页面中使用及javascript action使用)
salesforce零基础学习(七十四)apex:actionRegion以及apex:actionSupport浅谈
salesforce零基础学习(八十四)配置篇: 自定义你的home page layout