Salesforce LWC学习(八) Look Up组件实现

本篇参考https://www.salesforcelwc.in/2019/10/lookup-in-lwc.html,感谢前人种树。

我们做lightning的时候经常会遇到Look up 或者MD字段在页面搜索展示的需求,在标准的页面很常见,而且很好看。但是很遗憾的是在自定义组件中还没有现成的标准组件去搞定。下面介绍两种方式去实现展示lookup / MD字段的组件样式。

 一.  record-edit-form搭配 lightning-input-field 曲线救国

标准功能也不是100%的不近人情,还是给出一个workaround的方案去实现,实现的方式为在后台声明一个Lookup / MD的组件,然后使用lightning-input-field去实现。此组件会根据字段的类型去自动转换成其相应的样式进行展示,效果很像classic中的apex:inputField或者lightning aura中的lightning:inputField。使用lightning-record-edit-form来指定某个表的LDS,使用lightning-input-field进行效果展示,然后提交的操作时阻止默认的submit操作并且在event detail中获取到我们选择的Look up/MD对应的ID即可。demo中在Account上新建一个字段Test_User__c,类型为Look up (User).

testLookUpForLwc.html:使用LDS设置object api name为Account,这样下面就可以通过lightning-input-field针对Account的字段的类型动态展示相关的样式

<template>
    <lightning-record-edit-form
        object-api-name=‘Account‘
        onsubmit={handleSubmit}
    >
        <lightning-input-field field-name="Test_User__c"></lightning-input-field>
        <lightning-button type="submit" label="get test user id" variant="brand">
        </lightning-button>
    </lightning-record-edit-form>
</template>

testLookUpForLwc.js:针对submit事件首先组织提交免得生成不需要的记录,然后通过event.detail.fields.Test_User__c便可以获取到所选择的Test_User__c的ID。

import { LightningElement,track } from ‘lwc‘;

export default class TestLookUpForLwc extends LightningElement {
    handleSubmit(event) {
        event.preventDefault();
        console.log(JSON.stringify(event.detail.fields.Test_User__c));
    }
}

结果展示:选择一个用户以后,点击get test user id便可以获取到当前选择的user的id。

 二.自定义组件实现

上面的方式好是好,但是此种写法没法更改相关的label信息,国内项目可能新创建个字段进行translation也可以实现,后台进行匹配也可以,但是对日项目可能管理严格,所以需要考虑自定义组件实现。自定义组件的实现的原理相对简单,难得是UI的构建,好在前辈有画好的功能直接使用,对上面的链接中的代码进行简单的修改即可使用。

customLookUpForLwc.html:展示UI,上面是一个lightning-pill / lightning-input,通过isValue来判断当前是输入框还是展示pill,下面是列表。当列表选择以后触发事件父进行处理。

<template>
    <div>
        <div class="slds-form-element">
            <div class="slds-form-element__control">
                <div class="slds-combobox_container">
                    <div id="box" class={boxClass} aria-expanded="true" aria-haspopup="listbox" role="combobox">
                        {searchLabel}
                        <div class="slds-combobox__form-element slds-input-has-icon slds-input-has-icon_right" role="none">
                            <template if:true={isValue}>
                                <div id="lookup-pill" class="slds-pill-container">
                                    <lightning-pill class="pillSize" label={valueObj} name={valueObj} onremove={handleRemovePill}>
                                        <lightning-icon icon-name={iconName} alternative-text="acc" ></lightning-icon>
                                    </lightning-pill>
                                </div>
                            </template>
                            <template if:false={isValue}>
                                <div class="slds-p-top_none">
                                    <lightning-input class={inputClass} type="search" id="input" value={searchTerm}
                                        onclick={handleClick}  onchange={onChange}
                                        variant="label-hidden" autocomplete="off" placeholder="Search..." label=‘account search‘>
                                    </lightning-input>
                                </div>
                            </template>
                        </div>
                        <div id="listbox-id-1" class="slds-dropdown slds-dropdown_length-with-icon-7 slds-dropdown_fluid" role="listbox">
                            <ul class="slds-listbox slds-listbox_vertical" role="presentation">
                                <template for:each={options} for:item="item">
                                    <li key={item.Id} onclick={onSelect} data-id={item.Id} role="presentation">
                                        <span class="slds-lookup__item-action slds-lookup__item-action--label" role="option">
                                            <lightning-icon class="slds-icon slds-icon--small slds-icon-text-default" icon-name={iconName} alternative-text={objName} size="small"></lightning-icon>
                                            <span class="slds-truncate">{item.Name}</span>
                                        </span>
                                    </li>
                                </template>
                            </ul>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

</template>

customLookUpForLwc.js

/* eslint-disable no-console */
/* eslint-disable @lwc/lwc/no-async-operation */

import lookUp from ‘@salesforce/apex/CustomLookUpForLwcController.lookUp‘;
import { getObjectInfo } from ‘lightning/uiObjectInfoApi‘;
import { getRecord } from ‘lightning/uiRecordApi‘;
import { api, LightningElement, track, wire } from ‘lwc‘;

export default class CustomLookUpForLwc extends LightningElement {
    //store object record id
    @api valueId;
    //record API name
    @api objName;
    //record icon name,see Lightning Design System to choose
    @api iconName;

    @api filter = ‘‘;
    //unique key used to mark the unique component. several component use this component need to mapping
    @api uniqueKey;
    //used to set the field to fetch.eg: [‘Account.Name‘] means we need to search account name field as filter
    @api fields;

    //search label show in lookup component
    @api searchLabel;

    @track searchTerm;
    //record name value
    @track valueObj;
    //record href
    @track href;
    //fetch result
    @track options;
    //is available value to show in lightning-pill
    @track isValue = false;

    @track blurTimeout;

    //css
    @track boxClass = ‘slds-combobox slds-dropdown-trigger slds-dropdown-trigger_click slds-has-focus‘;
    @track inputClass = ‘‘;

    @wire(lookUp, {searchTerm : ‘$searchTerm‘, myObject : ‘$objName‘, filter : ‘$filter‘})
    wiredRecords({ error, data }) {
        if (data) {
            this.record = data;
            this.error = undefined;
            this.options = this.record;
            console.log("common this.options", JSON.stringify(this.options));
        } else if (error) {
            this.error = error;
            this.record = undefined;
            console.log("wire.error",this.error);
        }
    }

    //To get preselected or selected record
    @wire(getRecord, { recordId: ‘$valueId‘, fields: ‘$fields‘ })
    wiredOptions({ error, data }) {
        if (data) {
            console.log(‘execute1‘);
            this.record = data;
            this.error = undefined;
            this.valueObj = this.record.fields.Name.value;
            this.href = ‘/‘+this.record.id;
            this.isValue = true;
            console.log("this.href", this.href);
            console.log("this.record", JSON.stringify(this.record));
        } else if (error) {
            console.log(‘execute2‘);
            this.error = error;
            this.record = undefined;
            console.log("this.error", this.error);
        }
    }

    handleClick() {
        console.log("In handleClick");

        this.searchTerm = ‘‘;
        this.inputClass = ‘slds-has-focus‘;
        this.boxClass = ‘slds-combobox slds-dropdown-trigger slds-dropdown-trigger_click slds-has-focus slds-is-open‘;
    }

    onSelect(event) {
        console.log("In onSelect");
        let ele = event.currentTarget;
        let selectedId = ele.dataset.id;
        console.log("selectedId", selectedId);
        //As a best practise sending selected value to parent and inreturn parent sends the value to @api valueId
        let key = this.uniqueKey;
        const valueSelectedEvent = new CustomEvent(‘valueselect‘, {
            detail: { selectedId, key },
        });
        this.dispatchEvent(valueSelectedEvent);

        // if(this.blurTimeout) {
        //     clearTimeout(this.blurTimeout);
        // }
        console.log(this.isValue);
        this.boxClass = ‘slds-combobox slds-dropdown-trigger slds-dropdown-trigger_click slds-has-focus‘;
    }

    onChange(event) {
        console.log("In onChange");
        this.searchTerm = event.target.value;
        console.log("searchTerm",this.searchTerm);
    }

    handleRemovePill() {
        console.log("In handleRemovePill");
        this.isValue = false;
        let selectedId = ‘‘;
        let key = this.uniqueKey;
        const valueSelectedEvent = new CustomEvent(‘valueselect‘, {
            detail: { selectedId, key },
        });
        this.dispatchEvent(valueSelectedEvent);
    }

}

testLookUpForLwc.html:引入组件,设置几个必填的参数,其中icon-name赋值可以选择链接中的以下内容进行查找https://lightningdesignsystem.com/icons/。使用accountId用来获取前台组件传递过来的ID。

<template>
    <c-custom-look-up-for-lwc
        unique-key={item.Id}
        value-id={accountId}
        obj-name="Account"
        icon-name="standard:account"
        search-label="Search Account"
        onvalueselect={handleSelection}        search-label
        fields={item.fields}>
    </c-custom-look-up-for-lwc>
</template>

testLookUpForLwc.js:handleSelection用来获取accountId

import { LightningElement,track } from ‘lwc‘;

export default class TestLookUpForLwc extends LightningElement {
    @track item = {
        id:‘xxx‘,
        fields:[‘Account.Name‘]
    };

    @track accountId;

    handleSelection(event) {
        console.log(event.detail.selectedId);
        this.accountId = event.detail.selectedId;
    }

}

效果展示:

总结:篇中通过两种方式实现lookup功能及样式的实现,如果第一种能搞定强烈推荐使用第一种,因为标准的功能稳定性以及效率会好很多,如果第一种搞定不了可以考虑自定义。lwc不易,且开发且珍惜。

原文地址:https://www.cnblogs.com/zero-zyq/p/12076412.html

时间: 2024-10-12 05:34:06

Salesforce LWC学习(八) Look Up组件实现的相关文章

Salesforce LWC学习(十) 前端处理之 list 处理

本篇参看:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array list是我们经常要处理的内容,lwc前端针对list主要有几个函数处理,不同函数针对不同场景有不同的功能.下面就根据几个常用的处理list的方法进行简单的介绍. 一. forEach 我们针对list处理经常需要迭代去处理,通常可能用到for(var index = 0;index < sampleList.le

《Hibernate学习笔记八》:组件映射

<Hibernate学习笔记八>:组件映射 前面介绍了一对一的单向.双向外键关联,例如,学生证和学生是一个一对一的关系.这篇博文主要是介绍下组件映射,即一个是另一个的一部分,例如,学生证的信息也可以作为学生信息的一部分,即在数据库中只存在学生一个表,而不是有学生和学生证两个表,并且这两个表中有一个一对一的关联关系. 如下: 有人或许会说,那我们就将学生和学生证的信息写在一个类中,则就不需要组件映射了,确实可以这样,但是,根据类的设计原则,我们一般都会将其设计为两个类,然后将学生证的信息作为一个

Vue学习笔记入门篇——组件的使用

本文为转载,原文:Vue学习笔记入门篇--组件的使用 组件定义 组件 (Component) 是 Vue.js 最强大的功能之一.组件可以扩展 HTML 元素,封装可重用的代码.在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功能.在有些情况下,组件也可以是原生 HTML 元素的形式,以 is 特性扩展. 组件使用 注册 注册一个全局组件,你可以使用 Vue.component(tagName, options).组件在注册之后,便可以在父实例的模块中以自定义元素 的形式使用.

Vue学习笔记入门篇——组件的内容分发(slot)

本文为转载,原文:Vue学习笔记入门篇--组件的内容分发(slot) 介绍 为了让组件可以组合,我们需要一种方式来混合父组件的内容与子组件自己的模板.这个过程被称为 内容分发 (或 "transclusion" 如果你熟悉 Angular).Vue.js 实现了一个内容分发 API,使用特殊的 'slot' 元素作为原始内容的插槽. 编译作用域 在深入内容分发 API 之前,我们先明确内容在哪个作用域里编译.假定模板为: <child-component> {{ messa

Vue学习笔记入门篇——组件的通讯

本文为转载,原文:Vue学习笔记入门篇--组件的通讯 组件意味着协同工作,通常父子组件会是这样的关系:组件 A 在它的模版中使用了组件 B.它们之间必然需要相互通信:父组件要给子组件传递数据,子组件需要将它内部发生的事情告知给父组件.然而,在一个良好定义的接口中尽可能将父子组件解耦是很重要的.这保证了每个组件可以在相对隔离的环境中书写和理解,也大幅提高了组件的可维护性和可重用性.在 Vue 中,父子组件的关系可以总结为 props down, events up.父组件通过 props 向下传递

JAVA学习Swing章节按钮组件JButton的简单学习

package com.swing; import java.awt.Container; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.net.URL; import javax.swing.Icon; import javax.swing.ImageIcon;

Oracle学习(八):处理数据

1.知识点:能够对比以下的录屏进行阅读 SQL> --SQL语句 SQL> --1. DML语句(Data Manipulation Language 数据操作语言): insert update delete select SQL> --2. DDL语句(Data Definition Language 数据定义语言): create/alter/drop/truncate table SQL> -- create/drop view,create/drop index(sequ

springMVC3学习(八)--全局的异常处理

在springMVC的配置文件中: <bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="defaultErrorView"> <value>/error</value><!-- 表示当抛出异常但没有

EasyUI学习总结(五)——EasyUI组件使用

EasyUI学习总结(五)--EasyUI组件使用 一.EasyUI组件的简单介绍 easyUI提供了很多组件让我们使用,如下图所示: 使用这些组件可以帮助我们快速地进行项目开发,下面以一个用户登录程序为例讲解EasyUI组件的使用 二.EasyUI组件的使用 2.1.创建测试的JavaWeb项目 2.2.编写测试代码 编写一个用户登录页面Login1.html,用于输入用户名和密码进行登录,使用JQuery的ajax方法异步提交表单 Login1.html的代码如下: 1 <!DOCTYPE