本篇参考:salesforce 零基础学习(六十二)获取sObject中类型为Picklist的field values(含record type)

https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.reference_wire_adapters_picklist_values

https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.reference_wire_adapters_picklist_values_record

Salesforce lwc中给我们提供了很多优秀的wire adapter使我们的开发更加便捷,比如getPicklistValues以及getPicklistValuesByRecordType 

可以实现获取某个字段或者某个record type所有picklist类型字段的 picklist values。这个组件在便捷的同时又让我们心生哀怨,因为他不是所有的对象都支持,针对常用对象 Account / Opportunity / Contact 或者自定义对象等可以直接使用,方便快捷,但是针对一些对象则不支持,比如 Event & Task。 所以当项目中使用到 Event & Task 进行自定义开发需要获取某个或者某些字段的 picklist values的值时,如果需求不变,我们进行 hard code,将所有的 label-value键值对使用 {label,value}的map进行封装,此种需求只是针对不经常修改的场景。如果需求不明确,或者需要指定的record type显示指定的picklist values,而 record type配置的 picklist values又可以实时变动的场景来说简直是灾难的,所以有了这篇的针对 LwC公用的方法的实现思路。代码并不完善,思路仅供参考。

思路分析:

1. 后台如何构建,需要满足哪些场景;

2. 前台如何搭建,如何做成公用组件使大部分的场景都可以简单引用便可以使用。

伴随着这两个问题进行了考虑。

1) 针对后台搭建,暂时满足两个场景

  • 针对一个表可以获取到所有的 Picklist类型字段的所有的 Picklist值;
  • 针对一个表的某个字段(可包含 record type)获取对应的Picklist值。

2)针对前台的搭建,因为需要从后台获取数据,需要保证数据获取支持异步处理,即数据处理完进行picklist 数据赋值。

思路分析以后进行功能的构建,本篇参考以前写过的一篇文章,这里 PicklistDescriber代码便不在放出,直接引用。

一. 后台搭建

CommonUtilsController:因为Salesforce目前没有针对 包含 record type对应的 Picklist values的特别好的获取方法,所以我们根据以前的XML解析模式进行获取包含record type的场景。 很多人可能会说Salesforce支持了通过user interface方式获取,只需要一个callout就可以获取到包含record type对应的picklist字段对应的values。这种方式其实和wire adapter原理一样,只是针对一部分object,而不是针对所有的object,考虑到组件的共用性,所以放弃了那种方式。

  1. public without sharing class CommonUtilsController {
  2.  
  3. private static Map<String,Schema.SObjectType> globalDescribeMap = Schema.getGlobalDescribe();
  4.  
  5. @AuraEnabled(cacheable=true)
  6. public static Map<String,Map<String,String>> getPicklistMapByObject(String objectName) {
  7. Map<String,Map<String,String>> resultMap = new Map<String, Map<String,String>>();
  8. Schema.DescribeSObjectResult objectResult = getDescribeObjectResult(objectName);
  9. Map<String,SObjectField> fieldsMap = objectResult.fields.getMap();
  10. Map<String,Schema.DescribeFieldResult> picklistName2DescribeFieldMap = new Map<String,Schema.DescribeFieldResult>();
  11. for(String fieldName : fieldsMap.keySet()) {
  12. SObjectField objField = fieldsMap.get(fieldName);
  13. Schema.DescribeFieldResult fieldResult = objField.getDescribe();
  14. if(fieldResult.getType() == Schema.DisplayType.Picklist) {
  15. picklistName2DescribeFieldMap.put(fieldName,fieldResult);
  16. }
  17. }
  18.  
  19. if(!picklistName2DescribeFieldMap.isEmpty()) {
  20. for(String fieldName : picklistName2DescribeFieldMap.keySet()) {
  21. Schema.DescribeFieldResult fieldResult = picklistName2DescribeFieldMap.get(fieldName);
  22. List<Schema.PicklistEntry> picklistEntries = fieldResult.getPicklistValues();
  23. Map<String,String> fieldValue2LabelMap = new Map<String,String>();
  24. for(Schema.PicklistEntry picklistEntry : picklistEntries) {
  25. if(picklistEntry.isActive()) {
  26. fieldValue2LabelMap.put(picklistEntry.getValue(),picklistEntry.getLabel());
  27. }
  28. }
  29. resultMap.put(fieldName,fieldValue2LabelMap);
  30. }
  31. }
  32. return resultMap;
  33. }
  34.  
  35. @AuraEnabled(cacheable=true)
  36. public static Map<String,String> getPicklistMapByObjectAndField(String objectName,String field,String recordTypeDevelopName) {
  37. Map<String,String> resultMap = new Map<String,String>();
  38. Schema.DescribeSObjectResult objectResult = getDescribeObjectResult(objectName);
  39. Map<String,SObjectField> fieldsMap = objectResult.fields.getMap();
  40. if(fieldsMap.containsKey(field)) {
  41. SObjectField objField = fieldsMap.get(field);
  42. Schema.DescribeFieldResult fieldResult = objField.getDescribe();
  43. List<Schema.PicklistEntry> picklistEntries = fieldResult.getPicklistValues();
  44. for(Schema.PicklistEntry picklistEntry : picklistEntries) {
  45. if(picklistEntry.isActive()) {
  46. resultMap.put(picklistEntry.getValue(),picklistEntry.getLabel());
  47. }
  48. }
  49. if(String.isNotBlank(recordTypeDevelopName)) {
  50. List<String> picklistValueWithRecordTypeList = PicklistDescriber.describe(objectName,recordTypeDevelopName,field);
  51. Map<String,String> resultForRecordTypeMap = new Map<String,String>();
  52. for(String picklistValue : picklistValueWithRecordTypeList) {
  53. if(resultMap.containsKey(picklistValue)) {
  54. resultForRecordTypeMap.put(picklistValue,resultMap.get(picklistValue));
  55. }
  56. }
  57. return resultForRecordTypeMap;
  58. }
  59.  
  60. }
  61. return resultMap;
  62. }
  63.  
  64. private static Schema.DescribeSObjectResult getDescribeObjectResult(String objectName) {
  65. Schema.SObjectType objectType = globalDescribeMap.get(objectName);
  66. Schema.DescribeSObjectResult objectResult = objectType.getDescribe();
  67. return objectResult;
  68. }
  69. }

后台就这样搭建完成,暴露了两个方法:getPicklistMapByObject & getPicklistMapByObjectAndField。第一个方法用来获取一个表的所有 Picklist类型字段的label api name对,key为api name,value为picklist的label。我们以 Account表为例,返回的结构类似如下图所示:

第二个方法用来获取某个指定object指定字段的 picklist values的获取,有record type则传递,如果不需要record type则传递 null或者不传递即可。针对结果集来说则没有外层的field api name,直接就是 picklist 字段的 api value -> label,这里不做截图。

二. 前台搭建

这里需要分成两步, 第一步是做一个公用组件来实现 传递相关参数获取指定的我们想得到的结果集。

picklistUtils.js:封装了两个公用函数,getAllPicklist用于获取object所有的picklist 类型字段的结果集;getFieldPicklistMap用于通过object & field [record type developer name]来获取指定字段的结果集。

  1. import getPicklistMapByObject from '@salesforce/apex/CommonUtilsController.getPicklistMapByObject';
  2. import getPicklistMapByObjectAndField from '@salesforce/apex/CommonUtilsController.getPicklistMapByObjectAndField';
  3.  
  4. const getAllPicklist = (objectAPIName) => {
  5. //let resultMap = new Map();
  6. return getPicklistMapByObject({objectName:objectAPIName})
  7. .then(result => {
  8. return result;
  9. })
  10. .catch(error =>{
  11. console.log(error);
  12. });
  13. };
  14.  
  15. const getFieldPicklistMap = (objectAPIName, fieldAPIName, recordTypeDevelopName) => {
  16. return getPicklistMapByObjectAndField({objectName:objectAPIName,field:fieldAPIName,recordTypeDevelopName:recordTypeDevelopName})
  17. .then(result => {
  18. return result;
  19. })
  20. .catch(error =>{
  21. console.log(error);
  22. });
  23. }
  24.  
  25. export {getAllPicklist,getFieldPicklistMap};

当我们将代码赋值粘贴到vs code里面,我们会发现他有一个提示: This may be converted to an async function.为什么会有这样的提示呢?是因为我们这个从后台进行结果集获取,此步骤不是实时的,而是一个异步的操作,所以他提示了将会将这个转换成了一个异步的函数。

这样的解释可能过于干燥,什么是异步的?异步怎么处理呢?这里放一个链接用来更好的理解:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/async_function。当我们声明了异步函数,调用源调用它时需要使用await去共同使用,从而实现结果集返回时可以正常的接收以及处理。

AccountPicklistComponent.js:公共组件搞定以后我们写一个组件进行测试,下面的组件只试验了获取所有picklist类型字段的测试,其他的方法感兴趣的自行测试。
这里的代码有几个关键点需要注意:
  • 头部需要引入我们需要用到的函数,这里引用的是:import {getAllPicklist} from 'c/picklistUtils';
  • 我们将生命周期函数connectedCallback使用async声明成了一个异步函数,因为这里我们需要有调用异步的函数使用await,所以方法声明async;
  • 针对异步的函数接受结果集需要使用await,否则获取的结果集变成了同步操作获取的便是null,只有通过await进行标识才可以正常返回;
  • 结果集接受操作需要使用临时变量,最后将临时变量赋值给我们需要展示前台的变量,不用临时变量赋值不会进行渲染,因为是异步的操作,没法reactive。
  1. import { LightningElement,track } from 'lwc';
  2. import {getAllPicklist} from 'c/picklistUtils';
  3. export default class AccountPicklistComponent extends LightningElement {
  4. @track industryList = [];
  5.  
  6. @track typeList = [];
  7.  
  8. @track accountSourceList = [];
  9.  
  10. @track ratingList = [];
  11.  
  12. async connectedCallback() {
  13. const result = await getAllPicklist('Account');
  14. console.log('total result : ' + JSON.stringify(result));
  15. let typeTempList = [];
  16. let industryTempList = [];
  17. let accountSourceTempList = [];
  18. let ratingTempList = [];
  19. for(let key in result) {
  20.  
  21. if (result.hasOwnProperty(key)) { // Filtering the data in the loop
  22.  
  23. if(key === 'type') {
  24. let typeResult = result[key];
  25. console.log('type result : ' + JSON.stringify(typeResult));
  26. for(let typeValue in typeResult) {
  27. typeTempList.push({label:typeResult[typeValue],value:typeValue});
  28. }
  29. } else if(key === 'industry') {
  30. let industryResult = result[key];
  31. for(let industryValue in industryResult) {
  32. industryTempList.push({label:industryResult[industryValue],value:industryValue});
  33. }
  34. } else if(key === 'accountsource') {
  35. let accountSourceResult = result[key];
  36. for(let accountSourceValue in accountSourceResult) {
  37. accountSourceTempList.push({label:accountSourceResult[accountSourceValue],value:accountSourceValue});
  38. }
  39. } else if(key === 'rating') {
  40. let ratingResult = result[key];
  41. for(let ratingValue in ratingResult) {
  42. ratingTempList.push({label:ratingResult[ratingValue],value:ratingValue});
  43. }
  44. }
  45. }
  46. }
  47. this.typeList = typeTempList;
  48. this.industryList = industryTempList;
  49. this.accountSourceList = accountSourceTempList;
  50. this.ratingList = ratingTempList;
  51. }
  52. }
  1. accountPicklistComponent.html:用来展示相关字段的select option
  1. <template>
  2. <lightning-card>
  3. <lightning-layout multiple-rows="true">
  4. <lightning-layout-item size="6">
  5. <lightning-combobox
  6. name="industry"
  7. label="industry"
  8. options={industryList}>
  9. </lightning-combobox>
  10. </lightning-layout-item>
  11.  
  12. <lightning-layout-item size="6">
  13. <lightning-combobox
  14. name="type"
  15. label="type"
  16. options={typeList}>
  17. </lightning-combobox>
  18. </lightning-layout-item>
  19.  
  20. <lightning-layout-item size="6">
  21. <lightning-combobox
  22. name="accountSource"
  23. label="Account Source"
  24. options={accountSourceList}>
  25. </lightning-combobox>
  26. </lightning-layout-item>
  27.  
  28. <lightning-layout-item size="6">
  29. <lightning-combobox
  30. name="rating"
  31. label="rating"
  32. options={ratingList}>
  33. </lightning-combobox>
  34. </lightning-layout-item>
  35. </lightning-layout>
  36. </lightning-card>
  37. </template>

结果展示:这个表的相关字段的picklist值便可以动态取出

总结:篇中只是根据某种需求去分析思考并进行代码的编写。代码并没有进行优化以及异常处理。篇中有错误地方还请指出,有不懂欢迎留言。有更好的方式欢迎沟通。

Salesforce LWC学习(十五) Async 以及 Picklist 公用方法的实现的更多相关文章

  1. Salesforce LWC学习(十六) Validity 在form中的使用浅谈

    本篇参考: https://developer.salesforce.com/docs/component-library/bundle/lightning-input/documentation h ...

  2. Salesforce LWC学习(十) 前端处理之 list 处理

    本篇参看:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array list是我们经 ...

  3. Salesforce LWC学习(十八) datatable展示 image

    本篇参看: https://developer.salesforce.com/docs/component-library/bundle/lightning-datatable/documentati ...

  4. Salesforce LWC学习(十九) 针对 lightning-input-field的label值重写

    本篇参考: https://salesforcediaries.com/2020/02/24/how-to-override-lightning-input-field-label-in-lightn ...

  5. Salesforce LWC学习(十四) Continuation进行异步callout获取数据

    本篇参考: https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.apex_continua ...

  6. Salesforce LWC学习(三十) lwc superbadge项目实现

    本篇参考:https://trailhead.salesforce.com/content/learn/superbadges/superbadge_lwc_specialist 我们做lwc的学习时 ...

  7. Salesforce LWC学习(三十九) lwc下quick action的recordId的问题和解决方案

    本篇参考: https://developer.salesforce.com/docs/component-library/bundle/force:hasRecordId/documentation ...

  8. Salesforce LWC学习(四十) dynamic interaction 浅入浅出

    本篇参考: Configure a Component for Dynamic Interactions in the Lightning App Builder - Salesforce Light ...

  9. Salesforce LWC学习(十七) 前端知识之 onclick & onblur & onmousedown

    在Salesforce LWC学习(八) Look Up组件实现篇中,我们实现了公用的lookup组件,使用的过程中,会发现当我们输入内容以后,搜索出来的列表便无法被清空. 针对此种情况我们打算优化一 ...

随机推荐

  1. 我折腾的shell笔记

    目录 Mac一些常用的快捷键记录 iTerm2或者命令行相关 Mac桌面上或者某目录下操作 一些实用脚本示例 代码无提示或者其他抽风症状,清除Xcode缓存 查看当前网络ip地址 日常提交推送git代 ...

  2. Object-Oriented Programming Summary Ⅲ

    目录 JML单元作业博客 1.1 梳理JML语言的理论基础 0. 前言 1. 形式 2. 作用域 3. 前置条件 (requires) 4. 后置条件 (ensures) 5. 模型域 (model) ...

  3. ubuntu16.04安装库、插件报错:

    安装一些插件.库,遇到报错 Could not fetch URL https://pypi.org/simple/pytest-pycodestyle/: There was a problem c ...

  4. python笔记26

    一.今日内容 python中的方法 python中的方法+正则表达式的新内容 #分组 #分组命名 #引用分组 #爬虫的小例子 1.转义符 如:\n--->\\n--->print('\\n ...

  5. 解决layui表单ajax提交回调函数不起作用问题的两种方式

    最近想用layui开发一个论坛模板用的是fly-ui,才接触layui对其还不太熟悉.一个简单的登录就困扰了我很久.登录的form通过ajax提交回调函数老是不起作用.经过浪费了N多时间的调试,发现l ...

  6. LeetCode(239.滑动窗口的最大值

    题目: 给定一个数组nums,有一个大小为k的滑动窗口从数组的最左侧移动到最右侧,你只可以看到滑动窗口内的k个数字.滑动窗口每次只向右移动一位. 返回滑动窗口中的最大值. 示例: 输入: nums = ...

  7. 机器学习 - LSTM应用之情感分析

    1. 概述 在情感分析的应用领域,例如判断某一句话是positive或者是negative的案例中,咱们可以通过传统的standard neuro network来作为解决方案,但是传统的神经网络在应 ...

  8. [BUG]微信小程序生成小程序码"小程序页面路径不存在,请重新输入"

    描述 小程序页面线上能打开. 微信官方 获取小程序页面小程序码 页面 ,输入 小程序页面路径,提示 "小程序页面路径不存在,请重新输入". 使用微信复制小程序路径方法, 也是同样的 ...

  9. created:异步初始化数据都应该放到 created里面

    created:异步初始化数据都应该放到 created里面

  10. 2016 Multi-University Training Contest 4 T9

    http://acm.hdu.edu.cn/showproblem.php?pid=5772 最大权闭合子图. 得到价值w[i][j]的条件是选了i,j这两个位置的字符.选择位置的i字符花费为 第一次 ...