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零基础学习,欢迎各位关注。

  • 相关阅读:
    Delphi XE5 android 蓝牙通讯传输
    Delphi XE5 android toast
    Delphi XE5 android openurl(转)
    Delphi XE5 如何设计并使用FireMonkeyStyle(转)
    Delphi XE5 android 捕获几个事件
    Delphi XE5 android listview
    Delphi XE5 android 黑屏的临时解决办法
    Delphi XE5 android popumenu
    Delphi XE5 android 获取网络状态
    Delphi XE5 android 获取电池电量
  • 原文地址:https://www.cnblogs.com/zero-zyq/p/15764975.html
Copyright © 2011-2022 走看看