• 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不易,且开发且珍惜。

  • 相关阅读:
    Cronolog切割tomcat日志
    使用TortoiseGit+码云管理项目代码
    POI使用 (4.0) 常用改动
    MySQL-with rollup函数运用
    CentOS7使用yum安装MySQL8.0
    java 8 新特性之Stream的排序/分类
    java阳历转农历
    MyBatis SQL xml处理小于号与大于号
    mysql update不能直接使用select的结果
    Java面试中遇到的坑【填坑篇】
  • 原文地址:https://www.cnblogs.com/zero-zyq/p/12076412.html
Copyright © 2020-2023  润新知