-
[LWC] 실습 4) lightning-datatable에 picklist 필드와 lookup 필드 함께 표시하기 - How to display lookup field and picklist field in datatableLWC 2024. 10. 2. 17:53
실습 계획
이번시간은 실습 4) custom lightning-datatable에 lookup 필드와 picklist 필드 함께 표시하기
실습 1) lightning-datatable 생성하기
실습 2) custom lightning-datatable에 picklist field 표시하기
실습 3) custom lightning-datatable에 lookup field 표시하기
실습 4) custom datatable에 lookup 필드와 picklist 필드 함께 표시하기
실습 5) datatable 속성 설정 및 기능 구현
0. 컴포넌트 구조 확인
- 앞선 실습 내용들 참고
1. lookupColumn.cmp
- 조회필드 편집화면처럼 보여줄 컴포넌트
1-1 : lookupColumn.html
<template><div class="lookupcontainer" id="lookup"><div if:true={showLookup} class="lookup-container"><div tabindex="0" class="container" style="position:fixed"><lightning-record-edit-form object-api-name={object}><lightning-input-fieldclass="slds-popover slds-popover_edit slds-popover__body"field-name={fieldName}value={value}variant='label-hidden'onchange={handleChange}data-id="input"></lightning-input-field></lightning-record-edit-form></div></div><div if:false={showLookup} class="slds-table_edit_container slds-is-relative"><span class="slds-grid slds-grid_align-spread slds-cell-edit slds-align_absolute-center"><span class="slds-truncate" title={lookupName}><lightning-formatted-url value={lookupValue} label={lookupName} target={target}></lightning-formatted-url></span><button data-id={context} class="slds-button slds-button_icon slds-cell-edit__button slds-m-left_x-small" tabindex="-1"title="Edit" onclick={handleClick}><svg class="slds-button__icon slds-button__icon_hint slds-button__icon_lock slds-button__icon_small slds-button__icon_edit slds-icon slds-icon-text-default slds-icon_xx-small"aria-hidden="true"><use xlink:href="/_slds/icons/utility-sprite/svg/symbols.svg?cache=9.37.1#edit"></use></svg><span class="slds-assistive-text">Edit</span></button></span></div></div></template>1-2 :lookupColumn.js
- Setup > 정적자원 등록 필요 > 이름 : LWCDatatableLookup
LWCDatatableLookup.css0.00MBimport { LightningElement, api, track, wire } from 'lwc';import { loadStyle } from 'lightning/platformResourceLoader';import LWCDatatableLookup from '@salesforce/resourceUrl/LWCDatatableLookup';import { getRecord } from "lightning/uiRecordApi";export default class LookupColumn extends LightningElement {@api value;@api fieldName;@api object;@api context;@api name;@api fields;@api target;@track showLookup = false;@wire(getRecord, { recordId: '$value', fields: '$fields' })record;getFieldName() {let fieldName = this.fields[0];fieldName = fieldName.substring(fieldName.lastIndexOf('.') + 1, fieldName.length);return fieldName;}get lookupName() {return (this.value != undefined && this.value != '' && this.record.data != null) ? this.record.data.fields[this.getFieldName()].value : '';}get lookupValue() {return (this.value != undefined && this.value != '' && this.record.data != null && this.record.data.fields[this.getFieldName()].value) ? '/' + this.value : '';}renderedCallback() {Promise.all([loadStyle(this, LWCDatatableLookup),]).then(() => { });let container = this.template.querySelector('div.container');container?.focus();window.addEventListener('click', (evt) => {if(container == undefined){this.showLookup = false;}});}handleChange(event) {this.value = event.detail.value[0];if(this.value == undefined){this.record.data = null;}
this.dispatchEvent(new CustomEvent('lookupchanged', {composed: true,bubbles: true,cancelable: true,detail: {data: { context: this.context, value: this.value }}}));
}handleClick(event) {setTimeout(() => {this.showLookup = true;}, 100);}}1-3 : lookupColumn.xml
<?xml version="1.0" encoding="UTF-8"?><apiVersion>61.0</apiVersion><isExposed>false</isExposed></LightningComponentBundle>1-4 : lookupColumn.css
.lookup-section{margin-top: -0.6rem;margin-left: -0.5rem;position: absolute!important;z-index: 9999999999999999999999;}.lookup-section .slds-dropdown{position: fixed !important;max-height: 120px;max-width: fit-content;overflow: auto;}2. customDatatableAll.cmp
- extends Lightning-datatable 컴포넌트로서 custom type으로 조회, 선택목록 필드를 보여주기 위한 custom 컴포넌트
2-1 : customDatatableAll.html
<template></template>2-2 : customDatatableAll.js
import { LightningElement } from 'lwc';import LightningDatatable from 'lightning/datatable';import lookupColumn from './lookupColumn.html';import picklistColumn from './picklistColumn.html';import pickliststatic from './pickliststatic.html';
export default class CustomDatatableTypeAll extends LightningDatatable {
static customTypes = {picklistColumn: {template: pickliststatic,editTemplate: picklistColumn,standardCellLayout: true,typeAttributes: ['label', 'placeholder', 'options', 'value', 'context', 'variant', 'name']},lookupColumn: {template: lookupColumn,standardCellLayout: true,typeAttributes: ['value', 'fieldName', 'object', 'context', 'name', 'fields', 'target' ]}}
}2-3 : customDatatableAll.xml
<?xml version="1.0" encoding="UTF-8"?><apiVersion>61.0</apiVersion><isExposed>false</isExposed></LightningComponentBundle>2-4 : lookupColumn.html
<template><c-lookup-columnname={typeAttributes.name}value={typeAttributes.value}field-name={typeAttributes.fieldName}object={typeAttributes.object}context={typeAttributes.context}fields={typeAttributes.fields}target={typeAttributes.target}></c-lookup-column></template>2-5 : picklistColumn.html
<template><lightning-comboboxname="picklist"data-inputable="true"label={typeAttributes.label}value={editedValue}placeholder={typeAttributes.placeholder}options={typeAttributes.options}variant='label-hidden'dropdown-alignment="auto"></lightning-combobox></template>2-6 : pickliststatic.html
<template><span class="slds-truncate" title={value}>{value}</span></template>3. oppItemManagementEdit.cmp
- custom datatable 및 메인 데요소들이 표시되는 메인 화면 컴포넌트
3-1 : oppItemManagementEdit.html
<template>
<section role="dialog" tabindex="-1" aria-modal="true" aria-labelledby="modal-heading-01" class="slds-modal slds-fade-in-open slds-modal_large"><div class="slds-modal__container">
<lightning-button-icon icon-name="utility:close" onclick={fnCloseModal} alternative-text="close" variant="bare-inverse" class="slds-modal__close" ></lightning-button-icon>
<!-- 모달 헤드 --><div class="slds-modal__header"><h2 id="modal-heading-01" class="slds-modal__title slds-hyphenate">기회제품 편집</h2></div>
<div style="background-color: white; "><div class="datatable-container" onitemregister={handleRegisterItem}>
<c-custom-datatable-type-allkey-field="Id"data={data}columns={columns}draft-values={draftValues}></c-custom-datatable-type-all></div></div>
<!-- 모달 푸터 --><div class="slds-modal__footer"><lightning-button name="close" label="닫기" class="slds-float_right" onclick={fnCloseModal}></lightning-button></div>
</div><!--modal container--></section>
<div class="slds-backdrop slds-backdrop_open" role="presentation"></div>
</template>3-2 : oppItemManagementEdit.js
import { LightningElement, track, wire, api } from 'lwc';import getOppItems from '@salesforce/apex/OppItemManagementController.getOppItems';import { CurrentPageReference, NavigationMixin } from 'lightning/navigation';
import { getPicklistValues } from 'lightning/uiObjectInfoApi';import FIELD_testSelecteList from '@salesforce/schema/OpportunityLineItem.testSelectList__c';
//4-1 : columns에 조회 필드 추가const columns=[{ label: '제품 Id', fieldName : 'Product2Id', type: 'text', hideDefaultActions : "true", editable: true, },{ label: '제품명', fieldName : 'Product2.Name', type: 'text', hideDefaultActions : "true", editable: true, },{ label: '수량', fieldName : 'Quantity', type: 'decimal', hideDefaultActions : "true", editable: true, cellAttributes:{ class: { fieldName: 'quantityCellClass' } }},{ label: '판매가격', fieldName : 'UnitPrice', type: 'currency', hideDefaultActions : "true", editable: true, typeAttributes: { currencyCode: 'KRW', style: 'currency', minimumFractionDigits: 0 } },{ label: '설명', fieldName : 'Description', type: 'text', hideDefaultActions : "true", editable: true, },{label: '고객사',fieldName: 'Account__c',type: 'lookupColumn',typeAttributes: {object: 'OpportunityLineItem',fieldName: 'Account__c',value: { fieldName: 'Account__c' },context: { fieldName: 'Id' },name: 'Account',fields: ['Account.Name'],target: '_self'},editable: false},{label: '제품 등급',fieldName: 'testSelectList__c',type: 'picklistColumn',editable: true,typeAttributes: {placeholder: '== 선택 ==',options: { fieldName: 'pickListOptions' },value: { fieldName: 'testSelectList__c' },context: { fieldName: 'Id' }},hideDefaultActions : "true"}];
export default class OppItemManagementEdit extends NavigationMixin(LightningElement) {columns = columns;@track data = [];@track oppItemList;@track draftValues = [];@api oppId;
//lwc를 호출한 url에서 파라미터 값 가져오기@wire(CurrentPageReference)setCurrentPageReference(currentPageReference) {if (currentPageReference) {const state = currentPageReference.state;const newOppId = state.c__oppId;if (newOppId !== this.oppId) {this.oppId = newOppId;this.fetchOppItems();}}}//매입상태 선택목록 필드 option 값 세팅- ( recordTypeId 전달 값 체크 )@track pickListOptions;@wire(getPicklistValues, { recordTypeId: "012000000000000AAA", fieldApiName: FIELD_testSelecteList })wirePickList({ error, data }) {if (data) {this.pickListOptions = data.values;// oppId가 설정된 경우 기회 항목을 가져옴if (this.oppId) {this.fetchOppItems();}} else if (error) {console.error(error);}}
//기회제품 가져오기fetchOppItems() {if (this.oppId && this.pickListOptions ) {getOppItems({ oppId: this.oppId }).then(result => {this.data = JSON.parse(JSON.stringify(result));if (this.data) {this.data.forEach(ele => {ele.pickListOptions = this.pickListOptions; //제품별(row별)로 선택목록 option값 세팅 해주기});}}).catch(error => {console.error(error);this.data = undefined;});}}
//기본 실행connectedCallback() {}
fnCloseModal(){this[NavigationMixin.Navigate]({type: 'standard__recordPage',attributes: {recordId: this.oppId,objectApiName: 'Opportunity',actionName: 'view'}});}
lookupChanged(event) {console.log('lookupChanged ---- ' + event.detail.data);event.stopPropagation();let dataRecieved = event.detail.data;let accountIdVal = dataRecieved.value != undefined ? dataRecieved.value : null;let updatedItem = { Id: dataRecieved.context, Account__c: accountIdVal };console.log(updatedItem);this.updateDraftValues(updatedItem);}//임시저장 값 최신화updateDraftValues(updateItem) {console.log('draftValue 확인 ===== ' + JSON.stringify(this.draftValues));let draftValueChanged = false;let copyDraftValues = [...this.draftValues];copyDraftValues.forEach(item => {if (item.Id === updateItem.Id) {for (let field in updateItem) {item[field] = updateItem[field];}draftValueChanged = true;}});if (draftValueChanged) {this.draftValues = [...copyDraftValues];} else {this.draftValues = [...copyDraftValues, updateItem];}
}
}3-3 : oppItemManagementEdit.xml
<?xml version="1.0" encoding="UTF-8"?><apiVersion>61.0</apiVersion><isExposed>true</isExposed><targets><target>lightning__RecordAction</target><target>lightning__AppPage</target><target>lightning__RecordPage</target><target>lightning__HomePage</target><target>lightning__UrlAddressable</target></targets></LightningComponentBundle>5. oppItemManagementController.cls
- apex class로 조회필드(Account__c)와 선택목록필드(testSelectList__c) 모두 쿼리해오도록 주의
public with sharing class OppItemManagementController {public OppItemManagementController() {}//기회 제품 리스트 반환@AuraEnabledpublic static List<OpportunityLineItem> getOppItems(String oppId){
List<OpportunityLineItem> oppItems = new List<OpportunityLineItem>();try {//Account__c 조회 필드 추가 함oppItems = [SELECT Id, OpportunityId, Product2Id, Product2.Name, PricebookEntryId, PricebookEntry.Name, Quantity, UnitPrice, Description, testSelectList__c, Account__cFROM OpportunityLineItemWHERE OpportunityId = :oppIdORDER BY Id];
return oppItems;
} catch (Exception e) {throw new AuraHandledException(e.getMessage());}}}6. 화면 확인
실습4번인 지금까지 lightning-datatable에 조회필드와 선택목록필드를 표시해보았다.
실습5번에서는
lighting-datatable의 속성들을 활용하여
datatable의 수정사항들과 표시되는 data를 컨트롤하는 부분을 포스팅할 예정이다.
반응형 - 앞선 실습 내용들 참고