本篇參考https://www.salesforcelwc.in/2019/10/lookup-in-lwc.html,感謝前人種樹。css
咱們作lightning的時候常常會遇到Look up 或者MD字段在頁面搜索展現的需求,在標準的頁面很常見,並且很好看。可是很遺憾的是在自定義組件中尚未現成的標準組件去搞定。下面介紹兩種方式去實現展現lookup / MD字段的組件樣式。html
一. record-edit-form搭配 lightning-input-field 曲線救國api
標準功能也不是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).app
testLookUpForLwc.html:使用LDS設置object api name爲Account,這樣下面就能夠經過lightning-input-field針對Account的字段的類型動態展現相關的樣式async
<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。fetch
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。ui
二.自定義組件實現this
上面的方式好是好,可是此種寫法無法更改相關的label信息,國內項目可能新建立個字段進行translation也能夠實現,後臺進行匹配也能夠,可是對日項目可能管理嚴格,因此須要考慮自定義組件實現。自定義組件的實現的原理相對簡單,可貴是UI的構建,好在前輩有畫好的功能直接使用,對上面的連接中的代碼進行簡單的修改便可使用。spa
customLookUpForLwc.html:展現UI,上面是一個lightning-pill / lightning-input,經過isValue來判斷當前是輸入框仍是展現pill,下面是列表。當列表選擇之後觸發事件父進行處理。eslint
<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不易,且開發且珍惜。