Salesforce LWC学习(三十六) Quick Action 支持选择 LWC了

2021-09-10 11:41:50 浏览数 (2)

背景: 我们现在项目越来越多的使用 lwc 进行了前端开发,当然我们知道lwc并不能所有的场景都支持自己玩,比如组件之间的navigation、 quick action等都需要通过aura进行操作,aura套用lwc来实现。好消息是随着salesforce的release对lwc的不断发力,越来越多的功能可以通过lwc来使用。

一. lwc 适配 Quick Action的两个类型

首先我们先想一下我们通过Aura使用到Quick Action的场景,总结起来可以简单的归到2点:

1. 弹出一个popup modal,modal中展示一个UI,不管是一个可以用于修改的表单,还是展示只读内容然后有操作按钮等等,这些都无所谓了,重点是有UI的内容,展示modal;

2. 点击以后执行一个web service或者做一个跳转操作,用户不希望弹出来modal,只是希望进行即可。

当然,不同的甲方不同的需求会有不同的实现方案,但是Quick Action当我们选择 Aura的时候,通常这两个大的类型就可以搞定的。切回到 lwc,同样官方也提供了这两个类似的模式。

  • ScreenAction: 用于声明一个有popup modal的UI的quick action;
  • Action: 无UI的quick action。

这两种配置是配置到js-meta.xml里面。配置信息如下:

ScreenAction: 以下的配置是 ScreenAction的配置,主要有几个点:

  • apiVersion建议选择52.0,如果有后续的release,当然也可以选择这个值即以上,目前来讲,选择52.0,尝试了一下,如果选择50、51也可以保存,但是为了考虑未知的风险,尽量还是按照规矩来;
  • target设置成 lightning__RecordAction:这个是52 release新有的配置项,需要了解的一点是,如果使用 lwc的quick action,只支持 record 的quick action,global action是不支持的;
  • targetConfig中配置的 actionType为 ScreenAction,当然,如果不配置 targetConfig,默认也是 ScreenAction,所以我们在配置时,默认可以不配置targetConfigs部分;
代码语言:javascript复制
<?xml version="1.0" encoding="UTF-8" ?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
   <apiVersion>52.0</apiVersion>
   <isExposed>true</isExposed>
   <targets>
       <target>lightning__RecordAction</target>
   </targets>
    <targetConfigs>
   <targetConfig targets="lightning__RecordAction">
     <actionType>ScreenAction</actionType>
   </targetConfig>
 </targetConfigs>
</LightningComponentBundle>

Action:和上述的区别只是 actionType为 Action,如果想要选择 Action类型,则下述所有的内容都无法省略。

代码语言:javascript复制
<?xml version="1.0" encoding="UTF-8" ?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
   <apiVersion>52.0</apiVersion>
   <isExposed>true</isExposed>
   <targets>
       <target>lightning__RecordAction</target>
   </targets>
    <targetConfigs>
   <targetConfig targets="lightning__RecordAction">
     <actionType>Action</actionType>
   </targetConfig>
 </targetConfigs>
</LightningComponentBundle>

二. ScreenAction的使用

配置篇已经搞定,接下来就搞一下UI,根据官方的demo,我们做一下contact的编辑的一个component quick action。

screenActionSample.js: 主要用于contact的获取数据以及编辑。这里面有两个关键点。

  • CloseActionScreenEvent是salesforce lwc提供的关闭action的事件,类似于aura的e.force:closeQuickAction。同样,如果lwc想要关闭,只需要this.dispatchEvent(new CloseActionScreenEvent());即可,类似于aura的$A.get("e.force:closeQuickAction").fire();
  • 我们无法捕捉到X这个关闭按钮,所以同样也没法在这个操作中监听事件(如果大神们可以监听到,麻烦告知,我这里在修改)。
代码语言:javascript复制
import { LightningElement, api, wire,track } from 'lwc';
import { getRecord, getFieldValue } from 'lightning/uiRecordApi';
import { updateRecord } from 'lightning/uiRecordApi';
import { CloseActionScreenEvent } from 'lightning/actions';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import FNAME_FIELD from '@salesforce/schema/Contact.FirstName';
import LNAME_FIELD from '@salesforce/schema/Contact.LastName';
import PHONE_FIELD from '@salesforce/schema/Contact.Phone';
import ID_FIELD from '@salesforce/schema/Contact.Id';

const FIELDS = [FNAME_FIELD, LNAME_FIELD, PHONE_FIELD];
export default class screenActionSample extends LightningElement {
    disabled = false;
    @api recordId;
    @api objectApiName;

    contact;

    @track firstName;

    @track lastName;

    @track phone;

    @wire(getRecord, { recordId: '$recordId', fields: FIELDS })
    wiredRecord({ error, data }) {
        if (error) {
            //TODO
        }  else if (data) {
            this.contact = data;
            this.firstName = this.contact.fields.FirstName.value;
            this.lastName = this.contact.fields.LastName.value;
            this.phone = this.contact.fields.Phone.value;
        }
    }

    handleCancel(event) {
       // Add your cancel button implementation here
       this.dispatchEvent(new CloseActionScreenEvent());
    }

    handleChange(event) {
       let source = event.target.name;
       if(source === 'firstName') {
               this.firstName = event.target.value;
       } else if(source === 'lastName') {
               this.lastName = event.target.value;
       } else if(source === 'phone') {
               this.phone = event.target.value;
       }
   }

    handleSubmit(e) {
        // Add your updateRecord implementation
        const fields = {};
        fields[ID_FIELD.fieldApiName] = this.recordId;
        fields[FNAME_FIELD.fieldApiName] = this.firstName;
        fields[LNAME_FIELD.fieldApiName] = this.lastName;
        fields[PHONE_FIELD.fieldApiName] = this.phone;
        const recordInput = { fields };
        console.log(JSON.stringify(recordInput));
        updateRecord(recordInput)
                .then(() => {
                    this.dispatchEvent(
                        new ShowToastEvent({
                            title: 'Success',
                            message: 'Contact updated',
                            variant: 'success'
                        })
                    );
                    this.dispatchEvent(new CloseActionScreenEvent());
                })
                .catch(error => {
                    this.dispatchEvent(
                        new ShowToastEvent({
                            title: 'Error creating record',
                            message: error.body.message,
                            variant: 'error'
                        })
                    );
                });
    }
}

screenAction.html:这里我们看到一个新的组件的面孔: lightning-quick-action-panel。我们查阅官方文档以后,发现这个使用起来很简单,就是基于lightning design system中的modal来实现,属性中可以设置 header属性,代表action的头部,slot设置了footer的placeholder。

代码语言:javascript复制
<template>
    <lightning-quick-action-panel header="Quick Contact Edit">

            <lightning-input label="First Name" name="firstName" value={firstName} class="slds-m-bottom_x-small" onchange={handleChange}></lightning-input>
            <lightning-input label="Last Name" name="lastName" value={lastName} onchange={handleChange} class="slds-m-bottom_x-small" required></lightning-input>
            <lightning-input label="Phone" type="tel" name="phone" value={phone} onchange={handleChange} class="slds-m-bottom_x-small"></lightning-input>

        <div slot="footer">
            <lightning-button variant="neutral" label="Cancel" onclick={handleCancel}></lightning-button>
            <lightning-button variant="brand" class="slds-m-left_x-small" label="Save" type="submit" onclick={handleSubmit} disabled={disabled}></lightning-button>
        </div>
</lightning-quick-action-panel>
</template>

整体展示的效果:

我们来看一下解析的html,这个模型和官方的modal模型是不是很像。

当然,官方除了可以使用 lightning-quick-action-panel组件以外,也支持自己使用html去适配。

三. headless的action效果

headless的action是通过调用 invoke方法来执行,invoke方法前面通过 @api 注解来声明。如果需要异步操作或者需要访问后台等在进行操作,可以将方法声明称异步,即:@api async invoke() {}

举一个官方的demo:用来点击quick action跳转到 contact list

代码语言:javascript复制
import { LightningElement, track, wire,api } from 'lwc';
import { NavigationMixin } from 'lightning/navigation';
export default class headlessActionSAmple extends NavigationMixin(LightningElement) {
    @api invoke() {
        this[NavigationMixin.Navigate]({
            type: 'standard__objectPage',
            attributes: {
                objectApiName: 'Contact',
                actionName: 'home',
            },
        });
    }
}

四. 问题思考

优点: 对于优点来说,太显而易见了。 基于modal的设计,支持了lwc,还有什么比这个更好的优点吗

缺点:

1. 和aura弹出modal不同,aura的URL不会改变,lwc会改变URL,两边不统一,针对弹出modal以后的刷新操作,lwc加载数据等可能会有潜在的问题,需要测试和适配。举个例子,上述的ScreenAction的demo,初始化弹出来是正常的,但是当你点击刷新按钮或者点击F5以后,页面将会进入假死状态,这种情况可能要考虑一下优化代码。

2. lwc弹出的modal的宽度是固定的,如果客户希望更改lwc弹出的modal的宽度,则无法实现,这种在aura可以通过 aura:tag注入可以搞定 3. 如果基于screen action的modal,目前 lightning-quick-action-panel 还是beta版,项目要求高的,客户不一定接受。 4. 目前 lwc quick action不支持 salesforce mobile app,有mobile相关的项目,使用前一定要考虑限制,别做完以后电脑端没有问题,手机端是用不了。

总结:篇中主要介绍lwc如何去适配quick action。篇中有错误地方欢迎指出,有不懂欢迎留言。

0 人点赞