ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [LWC] 실습 2) lightning-datatable에 picklist field 표시하기 - How to display picklist field in datatable
    LWC 2024. 9. 11. 10:17

     

     

    실습 계획

    이번시간은 실습 2) custom lightning-datatable에 picklist field 표시하기

     

     

    실습 1) lightning-datatable 생성하기

    실습 2) custom lightning-datatable에 picklist field 표시하기

    실습  3) custom lightning-datatable에 lookup field 표시하기

    실습  4) custom datatable에 lookup 필드와 picklist 필드 함께 표시하기

    실습  5) datatable 설정 Tip 및 issue 공유

     

     

     


     

    0. 기본 Setup 및 개념

    • 기회제품 개체에 선택목록 필드 추가
    • 추가한 선택목록 필드 조회해 오도록 apex 컨트롤러에서 sql문 수정
    • 선택목록 필드를 보여주기 위한 lwc 컴포넌트 생성
      1. 기본으로 제공되는 lightning-datatable에서는 선택목록 필드를 보여줄 수 없어서
        1. 1. datatable을 extends한 lwc 컴포넌트를 생성하고
        2. 2. 해당 컴포넌트(=datatable 컴포넌트)에 custom type 추가하여
        3. 3. 선택목록 필드 편집화면 처럼 보여주도록 구현

     

     

     


     

    1. 추가한 선택목록 필드(=제품 등급) 조회해 오도록 apex 컨트롤러에서 sql문 수정

    • OppItemManagementController.cls
    • oppItems 가져오는 부분에서 testSelectList__c 필드 가져오도록 추가
    public with sharing class OppItemManagementController {
        public OppItemManagementController() {}
       
      
        //기존 기회 제품 리스트 반환
        @AuraEnabled
        public static List<OpportunityLineItem> getOppItems(String oppId){

            List<OpportunityLineItem> oppItems = new List<OpportunityLineItem>();
           
            try {
                //testSelectList__c 선택목록 필드 추가 함
                oppItems = [
                    SELECT Id, OpportunityId, Product2Id, Product2.Name, PricebookEntryId, PricebookEntry.Name,  Quantity, UnitPrice, Description, SortOrder, testSelectList__c
                    FROM OpportunityLineItem
                    WHERE OpportunityId = :oppId
                    ORDER BY SortOrder, Id
                ];

                return oppItems;

            } catch (Exception e) {
                throw new AuraHandledException(e.getMessage());
            }
        }
       
    }

     

     

    2. 선택목록 필드를 보여줄 lwc 컴포넌트 - customDatatableType.cmp 생성

    • Custom Datatable 컴포넌트이다.

     

     

    2-1 : customDatatableType.html

    • 해당 컴포넌트(customDatatableType.cmp)는 extends LightningDatatable한 데이터테이블 컴포넌트이다.  
    • 따라서 html 파일에 코드를 입력하지 않아도 datatable 형식으로 표시된다.
    • 코드를 입력해도 화면에 나타나지 않는다.
    <template>
       
    </template>

     

    2-2 : picklistColumn.html

    <template>
        <lightning-combobox
            name="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-3 : pickliststatic.html

    <template>
        <span class="slds-truncate" title={value}>{value}</span>
    </template>

     

    2-4 : customDatatableType.js

    import { LightningElement } from 'lwc';
    import LightningDatatable from 'lightning/datatable';
    import picklistColumn from './picklistColumn.html';
    import pickliststatic from './pickliststatic.html';

    export default class CustomDatatableType extends LightningDatatable {
        static customTypes = {
            picklistColumn: {
                template: pickliststatic,
                editTemplate: picklistColumn,
                standardCellLayout: true,
                typeAttributes: ['label', 'placeholder', 'options', 'value', 'context', 'variant', 'name']
            }
        }
    }

     

    2-5 : customDatatableType.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
        <apiVersion>61.0</apiVersion>
        <isExposed>false</isExposed>
    </LightningComponentBundle>

     

     

     

    3. custom datatable을 화면에 보여주도록 부모 컴포넌트의 html 파일 수정

    • 부모 컴포넌트(데이터 테이블 및 main화면 보여줄 컴포넌트) : oppItemManagementEdit.cmp
    • 자식 컴포넌트(커스텀 데이터테이블 컴포넌트) : customDatatableType
      • 컴포넌트 호출 시에는 c- 로 시작하며 이름에 대문자가 있는 경우 케밥케이스 형식으로 표시
      • customDatatableType.cmp 호출 시 <c-custom-datatable-type>

     <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
                            key-field="Id"
                            data={data}
                            columns={columns}
                        >
                        </c-custom-datatable-type>
                    </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>

     

     


    4. custom datatable을 호출하도록
    부모 컴포넌트의 js 파일 수정

    • 부모 컴포넌트(데이터 테이블 및 main화면 보여줄 컴포넌트) : oppItemManagementEdit.cmp
    • 자식 컴포넌트(커스텀 데이터테이블 컴포넌트) : customDatatableType

     

    4-1 : 선택목록 필드를 column에 추가

    • label → 필드 레이블
    • fieldName → 필드 api명
    • type → 내가 생성한 커스텀 타입명
    • editable → 수정 가능여부
    • typeAttributes → 해당 필드 타입의 추가적인 정보
    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: '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;
       
       
    }

     

     

    4-2 : 선택목록 필드의 option 값 가져오기

    @wire(getPicklistValues) 호출 시

    • 개체의 recordTypeId가 있다면 recordTypeId를 전달해주어야 하며
    • 개체의 recordTypeId가 없다면 " 012000000000000AAA"를 전달해 주면 된다.
    import { getPicklistValues } from 'lightning/uiObjectInfoApi';
    import FIELD_testSelecteList from '@salesforce/schema/OpportunityLineItem.testSelectList__c';
     
    export default class OppItemManagementEdit extends NavigationMixin(LightningElement) {
     
        //매입상태 선택목록 필드 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);
            }
        }
     
    }
     

     

     

    4-3 : 제품별(row별) 선택목록 option값 세팅 해주기

    • apex controller 메서드를 통해 기회제품 list를 가져오고
    • 이를 데이터테이블에서 활용할 data로 세팅해 줄 때 제품별(row별)로 선택목록 option값 세팅 해주기
     
        import getOppItems from '@salesforce/apex/OppItemManagementController.getOppItems';
     
     
        export default class OppItemManagementEdit extends NavigationMixin(LightningElement) {
     
        //기회제품 가져오기
        fetchOppItems() {
            console.log('save시 fetchOppItems 동작 == ');
           
            if (this.oppId && this.pickListOptions ) {  <------- oppId와 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;    <------- 기회제품 list의 각 제품별로 pickListOption값 세팅
                        });
                    }
                })
                .catch(error => {
                    console.error(error);
                    this.data = undefined;
                });
            }
        }
     
    }

     

     

    4-4 : js파일 전체 코드 확인

    • OppItemManagementEdit.js
    import { LightningElement, track, wire, api } from 'lwc';
    import getOppItems from '@salesforce/apex/OppItemManagementController.getOppItems';
    import { CurrentPageReference, NavigationMixin } from 'lightning/navigation';

    //4-2
    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: '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;
       
        //4-2 : 제품 등급 선택목록 필드 option 값 가져오기
        @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);
            }
        }


        //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();
                }
            }
        }
     
     
        //4-3 : 기회제품 가져오기 및 제품 별 선택목록 option 값 세팅해주기
        fetchOppItems() {
     
           
            if (this.oppId && this.pickListOptions ) {  <- oppId와 pickListOptions값이 세팅되었을때 기회제품 list 가져오기
            getOppItems({ oppId: this.oppId })
                .then(result => {
                    this.data = JSON.parse(JSON.stringify(result));
                    if (this.data) {
                        this.data.forEach(ele => {
                            ele.pickListOptions = this.pickListOptions;
                        });
                    }
                })
                .catch(error => {
                    console.error(error);
                    this.data = undefined;
                });
            }
        }


        //기본 실행
        connectedCallback() {
        }


        fnCloseModal(){
           
            this[NavigationMixin.Navigate]({
                type: 'standard__recordPage',
                attributes: {
                    recordId: this.oppId,
                    objectApiName: 'Opportunity',
                    actionName: 'view'
                }
            });
        }


    }

     

     

    5. 화면 확인

     


     

     

    선택한 값으로 제품의 정보가 실제 저장되도록하려면

    datatable에 draft-values와 oncellchange 속성부여가 필요하다.

    이번 실습에서는 보여주는 것이 목표

    해당 기능은 실습5번에서 포스팅할 예정

     

    반응형
Designed by Tistory.