Salesforce LWC学习(十五) Async 以及 Picklist 公用方法的实现
本篇参考:salesforce 零基础学习(六十二)获取sObject中类型为Picklist的field values(含record type)
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,考虑到组件的共用性,所以放弃了那种方式。
public without sharing class CommonUtilsController {
private static Map<String,Schema.SObjectType> globalDescribeMap = Schema.getGlobalDescribe();
@AuraEnabled(cacheable=true)
public static Map<String,Map<String,String>> getPicklistMapByObject(String objectName) {
Map<String,Map<String,String>> resultMap = new Map<String, Map<String,String>>();
Schema.DescribeSObjectResult objectResult = getDescribeObjectResult(objectName);
Map<String,SObjectField> fieldsMap = objectResult.fields.getMap();
Map<String,Schema.DescribeFieldResult> picklistName2DescribeFieldMap = new Map<String,Schema.DescribeFieldResult>();
for(String fieldName : fieldsMap.keySet()) {
SObjectField objField = fieldsMap.get(fieldName);
Schema.DescribeFieldResult fieldResult = objField.getDescribe();
if(fieldResult.getType() == Schema.DisplayType.Picklist) {
picklistName2DescribeFieldMap.put(fieldName,fieldResult);
}
}
if(!picklistName2DescribeFieldMap.isEmpty()) {
for(String fieldName : picklistName2DescribeFieldMap.keySet()) {
Schema.DescribeFieldResult fieldResult = picklistName2DescribeFieldMap.get(fieldName);
List<Schema.PicklistEntry> picklistEntries = fieldResult.getPicklistValues();
Map<String,String> fieldValue2LabelMap = new Map<String,String>();
for(Schema.PicklistEntry picklistEntry : picklistEntries) {
if(picklistEntry.isActive()) {
fieldValue2LabelMap.put(picklistEntry.getValue(),picklistEntry.getLabel());
}
}
resultMap.put(fieldName,fieldValue2LabelMap);
}
}
return resultMap;
}
@AuraEnabled(cacheable=true)
public static Map<String,String> getPicklistMapByObjectAndField(String objectName,String field,String recordTypeDevelopName) {
Map<String,String> resultMap = new Map<String,String>();
Schema.DescribeSObjectResult objectResult = getDescribeObjectResult(objectName);
Map<String,SObjectField> fieldsMap = objectResult.fields.getMap();
if(fieldsMap.containsKey(field)) {
SObjectField objField = fieldsMap.get(field);
Schema.DescribeFieldResult fieldResult = objField.getDescribe();
List<Schema.PicklistEntry> picklistEntries = fieldResult.getPicklistValues();
for(Schema.PicklistEntry picklistEntry : picklistEntries) {
if(picklistEntry.isActive()) {
resultMap.put(picklistEntry.getValue(),picklistEntry.getLabel());
}
}
if(String.isNotBlank(recordTypeDevelopName)) {
List<String> picklistValueWithRecordTypeList = PicklistDescriber.describe(objectName,recordTypeDevelopName,field);
Map<String,String> resultForRecordTypeMap = new Map<String,String>();
for(String picklistValue : picklistValueWithRecordTypeList) {
if(resultMap.containsKey(picklistValue)) {
resultForRecordTypeMap.put(picklistValue,resultMap.get(picklistValue));
}
}
return resultForRecordTypeMap;
}
}
return resultMap;
}
private static Schema.DescribeSObjectResult getDescribeObjectResult(String objectName) {
Schema.SObjectType objectType = globalDescribeMap.get(objectName);
Schema.DescribeSObjectResult objectResult = objectType.getDescribe();
return objectResult;
}
}
后台就这样搭建完成,暴露了两个方法: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]来获取指定字段的结果集。
import getPicklistMapByObject from '@salesforce/apex/CommonUtilsController.getPicklistMapByObject';
import getPicklistMapByObjectAndField from '@salesforce/apex/CommonUtilsController.getPicklistMapByObjectAndField'; const getAllPicklist = (objectAPIName) => {
//let resultMap = new Map();
return getPicklistMapByObject({objectName:objectAPIName})
.then(result => {
return result;
})
.catch(error =>{
console.log(error);
});
}; const getFieldPicklistMap = (objectAPIName, fieldAPIName, recordTypeDevelopName) => {
return getPicklistMapByObjectAndField({objectName:objectAPIName,field:fieldAPIName,recordTypeDevelopName:recordTypeDevelopName})
.then(result => {
return result;
})
.catch(error =>{
console.log(error);
});
} 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去共同使用,从而实现结果集返回时可以正常的接收以及处理。
- 头部需要引入我们需要用到的函数,这里引用的是:import {getAllPicklist} from 'c/picklistUtils';
- 我们将生命周期函数connectedCallback使用async声明成了一个异步函数,因为这里我们需要有调用异步的函数使用await,所以方法声明async;
- 针对异步的函数接受结果集需要使用await,否则获取的结果集变成了同步操作获取的便是null,只有通过await进行标识才可以正常返回;
- 结果集接受操作需要使用临时变量,最后将临时变量赋值给我们需要展示前台的变量,不用临时变量赋值不会进行渲染,因为是异步的操作,没法reactive。
import { LightningElement,track } from 'lwc';
import {getAllPicklist} from 'c/picklistUtils';
export default class AccountPicklistComponent extends LightningElement {
@track industryList = [];
@track typeList = [];
@track accountSourceList = [];
@track ratingList = [];
async connectedCallback() {
const result = await getAllPicklist('Account');
console.log('total result : ' + JSON.stringify(result));
let typeTempList = [];
let industryTempList = [];
let accountSourceTempList = [];
let ratingTempList = [];
for(let key in result) {
if (result.hasOwnProperty(key)) { // Filtering the data in the loop
if(key === 'type') {
let typeResult = result[key];
console.log('type result : ' + JSON.stringify(typeResult));
for(let typeValue in typeResult) {
typeTempList.push({label:typeResult[typeValue],value:typeValue});
}
} else if(key === 'industry') {
let industryResult = result[key];
for(let industryValue in industryResult) {
industryTempList.push({label:industryResult[industryValue],value:industryValue});
}
} else if(key === 'accountsource') {
let accountSourceResult = result[key];
for(let accountSourceValue in accountSourceResult) {
accountSourceTempList.push({label:accountSourceResult[accountSourceValue],value:accountSourceValue});
}
} else if(key === 'rating') {
let ratingResult = result[key];
for(let ratingValue in ratingResult) {
ratingTempList.push({label:ratingResult[ratingValue],value:ratingValue});
}
}
}
}
this.typeList = typeTempList;
this.industryList = industryTempList;
this.accountSourceList = accountSourceTempList;
this.ratingList = ratingTempList;
}
}
accountPicklistComponent.html:用来展示相关字段的select option
<template>
<lightning-card>
<lightning-layout multiple-rows="true">
<lightning-layout-item size="6">
<lightning-combobox
name="industry"
label="industry"
options={industryList}>
</lightning-combobox>
</lightning-layout-item> <lightning-layout-item size="6">
<lightning-combobox
name="type"
label="type"
options={typeList}>
</lightning-combobox>
</lightning-layout-item> <lightning-layout-item size="6">
<lightning-combobox
name="accountSource"
label="Account Source"
options={accountSourceList}>
</lightning-combobox>
</lightning-layout-item> <lightning-layout-item size="6">
<lightning-combobox
name="rating"
label="rating"
options={ratingList}>
</lightning-combobox>
</lightning-layout-item>
</lightning-layout>
</lightning-card>
</template>
结果展示:这个表的相关字段的picklist值便可以动态取出

总结:篇中只是根据某种需求去分析思考并进行代码的编写。代码并没有进行优化以及异常处理。篇中有错误地方还请指出,有不懂欢迎留言。有更好的方式欢迎沟通。
Salesforce LWC学习(十五) Async 以及 Picklist 公用方法的实现的更多相关文章
- Salesforce LWC学习(十六) Validity 在form中的使用浅谈
本篇参考: https://developer.salesforce.com/docs/component-library/bundle/lightning-input/documentation h ...
- Salesforce LWC学习(十) 前端处理之 list 处理
本篇参看:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array list是我们经 ...
- Salesforce LWC学习(十八) datatable展示 image
本篇参看: https://developer.salesforce.com/docs/component-library/bundle/lightning-datatable/documentati ...
- Salesforce LWC学习(十九) 针对 lightning-input-field的label值重写
本篇参考: https://salesforcediaries.com/2020/02/24/how-to-override-lightning-input-field-label-in-lightn ...
- Salesforce LWC学习(十四) Continuation进行异步callout获取数据
本篇参考: https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.apex_continua ...
- Salesforce LWC学习(三十) lwc superbadge项目实现
本篇参考:https://trailhead.salesforce.com/content/learn/superbadges/superbadge_lwc_specialist 我们做lwc的学习时 ...
- Salesforce LWC学习(三十九) lwc下quick action的recordId的问题和解决方案
本篇参考: https://developer.salesforce.com/docs/component-library/bundle/force:hasRecordId/documentation ...
- Salesforce LWC学习(四十) dynamic interaction 浅入浅出
本篇参考: Configure a Component for Dynamic Interactions in the Lightning App Builder - Salesforce Light ...
- Salesforce LWC学习(十七) 前端知识之 onclick & onblur & onmousedown
在Salesforce LWC学习(八) Look Up组件实现篇中,我们实现了公用的lookup组件,使用的过程中,会发现当我们输入内容以后,搜索出来的列表便无法被清空. 针对此种情况我们打算优化一 ...
随机推荐
- vue之initComputed模块源码说明
要想理解原理就得看源码,最近网上也找了好多vue初始化方法(8个init恶魔...) 因为也是循序渐进的理解,对initComputed计算属性的初始化有几处看得不是很明白,网上也都是含糊其辞的(要想 ...
- intel硬件视频加速介绍
目录 硬件视频加速技术 intel 硬件加速技术 intel 的开源媒体栈 VA-API 安装 样例 Intel Quick Sync(QSV) API支持情况 vaapi/mfx比较 安装 样例 硬 ...
- 【S2-053】Struts2远程命令执行漏洞(CVE-2017-12611)
继S2-052之后,Apache Struts 2再次被曝存在远程代码执行漏洞,漏洞编号S2-053,CVE编号CVE-2017-1000112. 当开发人员在Freemarker标签中使用错误的构造 ...
- 鸟哥的Linux私房菜基础学习篇(第三版)——阅读笔记(二)
第一章 Linux是什么 1.Linux是什么 一套操作系统 早期的Linux是针对386开发的 具有可移植性 2.Unix及Linux的发展史 1973年,Unix诞生,Ritchie等人以C语言写 ...
- Ubuntu16.04 desktop 设置共享文件夹 -- 图形界面配置
1. 安装 安装samba 直接采用 Ubuntu16.04 desktop 里面的安装向导来完成: 选中需要共享的文件夹 -> 右键 “local Network Share” -> 安 ...
- js 数组 方法
instanceof 检测一个对象是否是数组;(用来对付复杂数据类型;)// 简单数据类型 typeof ;A instanceof B // A是不是B造出来的;例: var arr = [1,2, ...
- 【Weiss】【第03章】练习3.15:自调整链表
[练习3.15] a.写出自调整表的数组实现.自调整表如同一个规则的表,但是所有的插入都在表头进行. 当一个元素被Find访问时,它就被移到表头而并不改变其余的项的相对顺序. b.写出自调整表的链表实 ...
- ajax上传文件,通过FromData把数据传给后端
前端代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF- ...
- JavaScript零宽字符
什么是零宽字符 一种不可打印的Unicode字符, 在浏览器等环境不可见, 但是真是存在, 获取字符串长度时也会占位置, 表示某一种控制功能的字符. 常见的零宽字符有哪些 零宽空格(zero-widt ...
- Ubuntu的BEEP去哪里了?
一直知道ubuntu的beep不响应了,但是一直都没太关注过它怎么了. 今天关注了一下,发现网上都是在问怎么关掉它的,时间还是在07年左右. 搜索到了一些帖子,有一些是说没有找到恢复的方法,还有一些, ...