zoukankan      html  css  js  c++  java
  • Salesforce LWC学习(三十九) lwc下quick action的recordId的问题和解决方案

    本篇参考:

    https://developer.salesforce.com/docs/component-library/bundle/force:hasRecordId/documentation

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

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

    我们在使用lwc的时候,recordId的嵌入以及wire adapter的功能,极大的减轻了我们的开发压力,让我们很爽的使用着。后来随着release的不断增强,lwc也支持quick action。这个我们在之前的篇章也讲过。曾经对recordId的使用不是很深入,随着quick action的一个功能的使用,发现了recordId在lwc下的一个隐藏描述(或者直接说是bug也好)。我们先来一个大家常用并且看上去没有问题的代码

    testLwcQuickAction.html

    <template>
        <lightning-quick-action-panel header="Test LWC Quick Action">
            {name}
        </lightning-quick-action-panel>
    </template>

    testLwcQuickAction.js

    import { LightningElement, track, wire,api } from 'lwc';
    import { CloseActionScreenEvent } from 'lightning/actions';
    import { getRecord, getFieldValue } from 'lightning/uiRecordApi';
    import NAME_FIELD from '@salesforce/schema/Account.Name';
    export default class testLwcQuickAction extends LightningElement {
        @api recordId;
    
        @wire(getRecord, { recordId: '$recordId', fields: [NAME_FIELD]})
        account;
    
        get name() {
            return getFieldValue(this.account.data, NAME_FIELD);
        }
    }

    将这个lwc配置成一个quick action,类型选择lightning web component,找到一条account,我们看一下效果。

    展示正常,没啥问题。那我们有时候会使用quick action做callout或者后台交互,当然可以使用headless的quick action,但是为了UI美观,我们可以使用screen的quick action,运行时展示 spinner,运行结束消失,让用户不会以为页面假死。我们进行下个代码展示。

    TestLwcQuickActionController.cls

    public with sharing class TestLwcQuickActionController {
         
         @AuraEnabled(cacheable=false)
         public static Boolean updateAccount(String accountId) {
             Account accountItem = new Account();
             accountItem.Id = accountId;
             accountItem.Name = 'updated account : ' + String.valueOf(System.now());
             update accountItem;
             return true;    
         }   
    }

    testLwcQuickAction2.html

    <template>
    <lightning-quick-action-panel header="Test LWC Quick Action">
    </lightning-quick-action-panel>
    </template>

    testLwcQuickAction2.js

    import { LightningElement, track, wire,api } from 'lwc';
    import { CloseActionScreenEvent } from 'lightning/actions';
    import { ShowToastEvent } from 'lightning/platformShowToastEvent';
    import updateAccount from '@salesforce/apex/TestLwcQuickActionController.updateAccount';
    export default class testLwcQuickAction2 extends LightningElement {
        @api recordId;
    
        renderedCallback() {
            updateAccount({accountId : this.recordId})
            .then(result => {
                console.log(result);
                let event = new ShowToastEvent({
                        title: 'update success',
                        variant: 'success'
                    });
                    this.dispatchEvent(event);
                    this.dispatchEvent(new CloseActionScreenEvent());
            })
            .catch(error => {
                console.log(JSON.stringify(error));
                let event = new ShowToastEvent({
                        title: 'error occurs',
                        variant: "error"
                    });
                this.dispatchEvent(event);
                this.dispatchEvent(new CloseActionScreenEvent());
            });
        }
    }

    乍一眼看上去是不是一点问题都没有,让我们实际运行一下

    竟然报错了,提示没有recordId,我们将这个不作为 lwc 的quick action,复制这个代码,放在 lightning record page发现代码正常运行,只有作为quick action情况下,recordId为null??? 当然,不止renderedCallback, connectedCallback下,recordId同样为空。我们找到文档,提示只有显示UI的上下文才可以正常的使用 recordId,其他的情况下则不支持。当然,报错原因是 recordId我们没有判断非空,这个主要是为了暴露问题,如果使用非空验证,仍然不会执行后台。

    那么问题来了,什么是 explicit record context?我们哪里可以查到呢? 至少lwc的文档中没有查看到,所以我们需要先找到 aura的文档,因为aura是lightning experience的第一版,我们只需要看一下 force:hasRecordId的文档去碰一下运气看看有没有即可。很幸运地是,我们找到了文档,并且了解了什么算是显示记录的上下文。

     

    通过描述愈发的感觉这是因为 lwc quick action的兼容性导致的问题,或者说是一个bug,因为这个并不符合说的显示记录的上下文的描述,而且同样代码作为组件放在record page即可以生效。当然问题既然发现,找到workaround方案就可以了。解决这个问题,目前想到3种 workaround方案,每个方案都亲测可以解决问题。

    1. 前端展示 recordId,放在 div 设置 style="display:none"即可,这样就满足了显示记录上下文的要求,将js内容前端展示,则会强制嵌入。

    testLwcQuickAction2.html

    <template>
    <lightning-quick-action-panel header="Test LWC Quick Action">
        <div style="display: none;">
            {recordId}
        </div>
    </lightning-quick-action-panel>
    
    </template>

    testLwcQuickAction2.js:renderedCallback先判断recordId非空

    import { LightningElement, track, wire,api } from 'lwc';
    import { CloseActionScreenEvent } from 'lightning/actions';
    import { ShowToastEvent } from 'lightning/platformShowToastEvent';
    import updateAccount from '@salesforce/apex/TestLwcQuickActionController.updateAccount';
    export default class testLwcQuickAction2 extends LightningElement {
        @api recordId;
    
        renderedCallback() {
            if(this.recordId) {
                updateAccount({accountId : this.recordId})
                .then(result => {
                    console.log(result);
                    let event = new ShowToastEvent({
                            title: 'update success',
                            variant: 'success'
                        });
                        this.dispatchEvent(event);
                        this.dispatchEvent(new CloseActionScreenEvent());
                })
                .catch(error => {
                    console.log(JSON.stringify(error));
                    let event = new ShowToastEvent({
                            title: 'error occurs',
                            variant: "error"
                        });
                    this.dispatchEvent(event);
                    this.dispatchEvent(new CloseActionScreenEvent());
                });
            }
            
        }
    }

    2. aura类型quick action,aura搭配lwc的组合YYDS

    testQuickActionForAura.cmp: aura下嵌入 recordId正常

    <aura:component implements="force:hasRecordId,force:lightningQuickActionWithoutHeader">
        <aura:attribute name="recordId" type="String"></aura:attribute>
        <c:testSonLwcQuickAction recordId="{!v.recordId}" onclosemodal="{!c.handleCloseAction}"></c:testSonLwcQuickAction>
    </aura:component>

    testQuickActionForAuraController.js

    ({
        handleCloseAction : function(component, event, helper) {
            $A.get('e.force:refreshView').fire();
            $A.get("e.force:closeQuickAction").fire();
        }
    })

    testSonLwcQuickAction.js

    import { LightningElement, track, wire,api } from 'lwc';
    import { ShowToastEvent } from 'lightning/platformShowToastEvent';
    import updateAccount from '@salesforce/apex/TestLwcQuickActionController.updateAccount';
    export default class testSonLwcQuickAction extends LightningElement {
        @api recordId;
    
        renderedCallback() {
            updateAccount({accountId : this.recordId})
            .then(result => {
                console.log(result);
                let event = new ShowToastEvent({
                        title: 'update success',
                        variant: 'success'
                    });
                    this.dispatchEvent(event);
                    this.dispatchEvent(new CustomEvent('closemodal'));
            })
            .catch(error => {
                console.log(JSON.stringify(error));
                let event = new ShowToastEvent({
                        title: 'error occurs',
                        variant: "error"
                    });
                this.dispatchEvent(event);
                this.dispatchEvent(new CustomEvent('closemodal'));
            });
        }
    }

    lwc的js调用后台,运行以后,event dispatch,aura关闭quick action modal,此种方式亲测有效。

    3. 使用CurrentPageReference获取recordId,获取以后,再去执行后台方法

    testLwcQuickAction.html

    <template>
    <lightning-quick-action-panel header="Test LWC Quick Action">
    </lightning-quick-action-panel>
    </template>

    testLwcQuickAction.js

    import { LightningElement, track, wire,api } from 'lwc';
    import { CloseActionScreenEvent } from 'lightning/actions';
    import { ShowToastEvent } from 'lightning/platformShowToastEvent';
    import { CurrentPageReference } from 'lightning/navigation';
    import updateAccount from '@salesforce/apex/TestLwcQuickActionController.updateAccount';
    export default class testLwcQuickAction3 extends LightningElement {
        @track recordId;
        @wire(CurrentPageReference)
        pageRef;
    
        renderedCallback() {
            if(this.pageRef && this.pageRef.state) {
                this.recordId = this.pageRef.state.recordId;
                updateAccount({accountId : this.recordId})
                .then(result => {
                    console.log('*** result : ' + result);
                    let event = new ShowToastEvent({
                            title: 'update success',
                            variant: 'success'
                        });
                        this.dispatchEvent(event);
                        this.dispatchEvent(new CloseActionScreenEvent());
                })
                .catch(error => {
                    console.log(JSON.stringify(error));
                    let event = new ShowToastEvent({
                            title: 'error occurs',
                            variant: "error"
                        });
                    this.dispatchEvent(event);
                    this.dispatchEvent(new CloseActionScreenEvent());
                });
            }
    
        }
    }

    简单演示:点击按钮以后,可以正常的获取 recordId并且可以正常的运行

    总结: 篇中只是暴露出recordId在lwc quick action下的问题,其他的情况暂时使用正常,以及3种workaround方案。篇中demo中没有考虑缓存,也没有优化代码,感兴趣的小伙伴自行优化。有更好的方法欢迎交流沟通。篇中错误地方欢迎指出,有不懂欢迎留言。

    作者:zero

    博客地址:http://www.cnblogs.com/zero-zyq/

    本文欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接

    个人下载了一些相关学习的PDF文件,如果需要下载请访问百度云 点击此处访问 密码:jhuy

    如果文章的内容对你有帮助,欢迎点赞~

    为方便手机端查看博客,现正在将博客迁移至微信公众号:Salesforce零基础学习,欢迎各位关注。

  • 相关阅读:
    MyEclipse for Spring 10.0: GWT 2.1 and Spring Scaffolding
    redis 协议
    Eclipse项目编译
    urlencode
    Firefox浏览器设置字符编码格式
    怎么从一台电脑的浏览器输入地址访问另一台电脑服务器(WAMP服务器已搭建,PHPSTORM装好了)...
    Tplink路由器怎么设置端口映射 内网端口映射听语音
    5.04 toArray()有一个问题须要解决一下
    WCF服务编程读书笔记(4):实例管理
    maven常用命令介绍
  • 原文地址:https://www.cnblogs.com/zero-zyq/p/15764975.html
Copyright © 2011-2022 走看看