Salesforce LWC学习(二十二) 简单知识总结篇二

时间:2022-07-24
本文章向大家介绍Salesforce LWC学习(二十二) 简单知识总结篇二,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

本篇参看:

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

https://developer.salesforce.com/docs/component-library/bundle/lightning-record-edit-form/documentation

碰到之前接触的记录一下,深化一下印象。

一. 解决 lightning-record-edit-form没有入力时,效果和标准不一样的问题

先看一下标准的创建数据的UI,当有必入力字段的表单,点击Save按钮以后,上部会有DIV提示。

我们使用 lightning-record-edit-form实现时,发现onsubmit这种 handler需要再所有的字段都满足情况下才执行,也就是说页面中有 invalid的字段入力情况下,不会提交表单,也自然无法执行 onsubmit对应的方法。这个时候,我们就需要在submit的这个按钮添加 onclick方法去调用后台从而实现尽管提交不了表单还可以正常做一些UI效果的可能。简单代码如下

accountEditWithEditForm.html: 展示两个字段,save button除了在submit基础上,还有 onclick操作。需要注意的是, onclick会先于 onsubmit执行,所以我们可以在 onclick做一些validation操作,成功的话,让onsubmit正常执行表单提交操作。

<template>
    <lightning-record-edit-form
        record-id={recordId}
        object-api-name="Account"
        onsubmit={handleSubmit}
        >
        <lightning-messages></lightning-messages>
        <c-error-message-modal is-show-error-div={isShowErrorDiv} error-message-list={errorMessageList}></c-error-message-modal>
        
        <lightning-layout multiple-rows="true">
            <lightning-layout-item size="6">
                <lightning-input-field field-name="Name"></lightning-input-field>
            </lightning-layout-item>
            <lightning-layout-item size="6">
                <lightning-input-field field-name="AnnualRevenue"></lightning-input-field>
            </lightning-layout-item>
            
            <lightning-layout-item size="12">
                <div class="slds-m-top_medium">
                    <lightning-button class="slds-m-top_small" label="Cancel" onclick={handleReset}></lightning-button>
                    <lightning-button class="slds-m-top_small" type="submit" label="Save Record"  onclick={handleClick}></lightning-button>
                </div>
            </lightning-layout-item>
        </lightning-layout>
    </lightning-record-edit-form>
</template>

accountEditWithEditForm.js

import { LightningElement,track,api,wire } from 'lwc';
import { updateRecord,getRecord } from 'lightning/uiRecordApi';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import { NavigationMixin } from 'lightning/navigation';
import { navigationWhenErrorOccur } from 'c/navigationUtils';
import {isSystemOrCustomError,getPageCustomErrorMessageList,getFieldCustomErrorMessageList} from 'c/errorCheckUtils';
import ACCOUNT_ID_FIELD from '@salesforce/schema/Account.Id';
import ACCOUNT_NAME_FIELD from '@salesforce/schema/Account.Name';
import ACCOUNT_ANNUALREVENUE_FIELD from '@salesforce/schema/Account.AnnualRevenue';
const fields = [
    ACCOUNT_ID_FIELD,
    ACCOUNT_NAME_FIELD,
    ACCOUNT_ANNUALREVENUE_FIELD
];
export default class AccountEditWithEditForm extends NavigationMixin(LightningElement) {

    @api recordId = '0010I00002U8dBPQAZ';
    @track isShowErrorDiv = false;
    @track errorMessageList = [];

    @track isFormValid = true;

    handleSubmit(event) {
        event.preventDefault();
        if(!this.isShowErrorDiv) {
            const fields = {};
            fields[ACCOUNT_ID_FIELD.fieldApiName] = this.recordId;
            fields[ACCOUNT_NAME_FIELD.fieldApiName] = event.detail.Name;
            fields[ACCOUNT_ANNUALREVENUE_FIELD.fieldApiName] = event.detail.AnnualRevenue;
            const recordInput = { fields };
            this.errorMessageList = [];
            this.isShowErrorDiv = false;
            updateRecord(recordInput)
            .then(() => {
                this.dispatchEvent(
                    new ShowToastEvent({
                        title: 'Success',
                        message: 'Account updated',
                        variant: 'success'
                    })
                );
            }).catch(error => {
                let systemOrCustomError = isSystemOrCustomError(error);
                if(systemOrCustomError) {
                    navigationWhenErrorOccur(this,error);
                } else {
                    this.isShowErrorDiv = true;
                    this.errorMessageList = getPageCustomErrorMessageList(error);
                    console.log(JSON.stringify(this.errorMessageList));
                    let errorList = getFieldCustomErrorMessageList(error);
                    if(errorList && errorList.length > 0) {
                        errorList.forEach(field => {
                            this.reportValidityForField(field.key,field.value);
                        });
                    }
                }
            });
        }   
    }

    handleClick(event) {
        let allInputList = Array.from(this.template.querySelectorAll('lightning-input-field'));
        let invalidFieldLabel = [];
        const allValid = allInputList.forEach(field => {
            if(field.required && field.value === '') {
                invalidFieldLabel.push(field.fieldName);    
                this.isShowErrorDiv = true;
            }
        });

        if(this.isShowErrorDiv) {
            this.errorMessageList.push('These required fields must be completed: ' + invalidFieldLabel.join(','));
        }
    }

    reportValidityForField(fieldName,errorMessage) {
        console.log('fieldname : ' + fieldName);
        if(fieldName === 'Name') {
            this.template.querySelector('.accountName').setCustomValidity(errorMessage);
            this.template.querySelector('.accountName').reportValidity();
        } else if(fieldName === 'AnnualRevenue') {
            this.template.querySelector('.accountRevenue').setCustomValidity(errorMessage);
            this.template.querySelector('.accountRevenue').reportValidity();
        }
    }

    handleReset(event) {
        const inputFields = this.template.querySelectorAll(
            'lightning-input-field'
        );
        if (inputFields) {
            inputFields.forEach(field => {
                field.reset();
            });
        }
    }
}

展示效果:

二. 「`」 的使用

我们在程序中应该很习惯的使用 track / api这种 reactive的变量,改动以后就可以走 rendercallback 然后前端UI会自动渲染和他关联的。除了使用这两个情况,还可以使用getter方式进行 field reactive操作。官方的描述为,如果字段声明不需要使用 track / api这种reactive变量,尽量不用,所以某些case下,我们可以使用 关键字 ``进行操作。这个标签是键盘的哪个呢,看下图?

看一下官方提供的demo

helloExpressions.html:输入框展示两个入力项,下面展示一个拼以后的大写。

<template>
    <lightning-card title="HelloExpressions" icon-name="custom:custom14">
        <div class="slds-m-around_medium">
            <lightning-input
                name="firstName"
                label="First Name"
                onchange={handleChange}
            ></lightning-input>
            <lightning-input
                name="lastName"
                label="Last Name"
                onchange={handleChange}
            ></lightning-input>
            <p class="slds-m-top_medium">
                Uppercased Full Name: {uppercasedFullName}
            </p>
        </div>
    </lightning-card>
</template>

helloExpressions.js:使用 `方式整合两个private的字段,实现reactive的效果。这里需要注意的是,如果使用 `以后必须要使用 ${}将变量套起来,这个是固定的写法。

import { LightningElement } from 'lwc';

export default class HelloExpressions extends LightningElement {
    firstName = '';
    lastName = '';

    handleChange(event) {
        const field = event.target.name;
        if (field === 'firstName') {
            this.firstName = event.target.value;
        } else if (field === 'lastName') {
            this.lastName = event.target.value;
        }
    }

    get uppercasedFullName() {
        return `${this.firstName} ${this.lastName}`.trim().toUpperCase();
    }
}

效果:

总结:篇中主要总结两点。1是 record-edit-form submit前的onclick使用;2是` 搭配 {}实现 reactive的效果。篇中有错误地方欢迎指出,有不懂的欢迎留言。