LWC에서 다른 LWC로 데이터 이동하기2

ahncheer·2022년 9월 7일
0

LWC & LWR

목록 보기
14/52

● Pub/Sub 파일을 사용해 데이터 교환하기

1. pubsub 파일 생성

pubsub.html은 필요 없습니다.

※ pubsub.js

const events = {};

/**
 * Confirm that two page references have the same attributes
 * @param {object} pageRef1 - The first page reference
 * @param {object} pageRef2 - The second page reference
 */
const samePageRef = (pageRef1, pageRef2) => {
    const obj1 = pageRef1.attributes;
    const obj2 = pageRef2.attributes;
    return Object.keys(obj1)
        .concat(Object.keys(obj2))
        .every(key => {
            return obj1[key] === obj2[key];
        });
};

/**
 * Registers a callback for an event
 * @param {string} eventName - Name of the event to listen for.
 * @param {function} callback - Function to invoke when said event is fired.
 * @param {object} thisArg - The value to be passed as the this parameter to the callback function is bound.
 */
const registerListener = (eventName, callback, thisArg) => {
    // Checking that the listener has a pageRef property. We rely on that property for filtering purpose in fireEvent()
    if (!thisArg.pageRef) {
        throw new Error(
            'pubsub listeners need a "@wire(CurrentPageReference) pageRef" property'
        );
    }

    if (!events[eventName]) {
        events[eventName] = [];
    }
    const duplicate = events[eventName].find(listener => {
        return listener.callback === callback && listener.thisArg === thisArg;
    });
    if (!duplicate) {
        events[eventName].push({ callback, thisArg });
    }
};

/**
 * Unregisters a callback for an event
 * @param {string} eventName - Name of the event to unregister from.
 * @param {function} callback - Function to unregister.
 * @param {object} thisArg - The value to be passed as the this parameter to the callback function is bound.
 */
const unregisterListener = (eventName, callback, thisArg) => {
    if (events[eventName]) {
        events[eventName] = events[eventName].filter(
            listener =>
                listener.callback !== callback || listener.thisArg !== thisArg
        );
    }
};

/**
 * Unregisters all event listeners bound to an object.
 * @param {object} thisArg - All the callbacks bound to this object will be removed.
 */
const unregisterAllListeners = thisArg => {
    Object.keys(events).forEach(eventName => {
        events[eventName] = events[eventName].filter(
            listener => listener.thisArg !== thisArg
        );
    });
};

/**
 * Fires an event to listeners.
 * @param {object} pageRef - Reference of the page that represents the event scope.
 * @param {string} eventName - Name of the event to fire.
 * @param {*} payload - Payload of the event to fire.
 */
const fireEvent = (pageRef, eventName, payload) => {
    if (events[eventName]) {
        const listeners = events[eventName];
        listeners.forEach(listener => {
            if (samePageRef(pageRef, listener.thisArg.pageRef)) {
                try {
                    listener.callback.call(listener.thisArg, payload);
                } catch (error) {
                    // fail silently
                }
            }
        });
    }
};

export {
    registerListener,
    unregisterListener,
    unregisterAllListeners,
    fireEvent
};

2. lwc018PubSubSendData 파일 생성

※ lwc018PubSubSendData.html

<template>
    <div class="wrapper">
        <lightning-button variant="brand" label="Send Data" title="Primary action" 
        onclick={sendData} class="slds-m-left_x-small"></lightning-button>
    </div>
</template>

※ lwc018PubSubSendData.js

import { LightningElement,wire,track,api } from 'lwc';
import {CurrentPageReference} from 'lightning/navigation';
import {fireEvent} from 'c/pubsub';


export default class Lwc018PubSubSendData extends LightningElement {
@wire (CurrentPageReference) pageRef;
    sendData(event){
        var eventParam = {name : 'tester01'};
        fireEvent(this.pageRef,'pubsubevent',eventParam);
    }
}

3. lwc019PubSubGetData 파일 생성

※ lwc019PubSubGetData.html

<template>
    <div class="wrapper">
        <p class="sub-t"> 받아온 데이터 : {testMsg}</p>
    </div>
</template>

※ lwc019PubSubGetData.js

import { LightningElement,wire,track } from 'lwc';
import {registerListener,unregisterAllListeners} from 'c/pubsub';
import {CurrentPageReference} from 'lightning/navigation';


export default class Lwc019PubSubGetData extends LightningElement {
    @wire (CurrentPageReference) pageRef;
    @track testMsg;

    handleCallback(detail){
        this.testMsg = detail.name;
    }
    connectedCallback(){
        /* event 등록 */
        registerListener('pubsubevent',this.handleCallback,this);
    }
    /* event 삭제 */
    disconnectedCallback(){
        unregisterAllListeners(this);
    }
}

4. 결과 확인

'c/pubsub'처럼 파일을 제대로 불러온다면 pubsub 파일 이름은 달라도 괜찮습니다.
출처 : communication-between-unrelated-components-using-publisher-subscriber-pattern-lwc

● messageChannels폴더를 생성해 데이터 교환하기

1. 구조 미리보기

→ 부모자식 관계가 아닌 서로 상관없는 LWC 사이의 데이터 교환하기

2. 데이터를 저장할 폴더 생성 + 파일 작성


1. force-app>main>default폴더에 messageChannels폴더 생성
2. 해당 폴더에 Sample_String.messageChannel-meta.xml 파일 생성
3. operator, sampleString, sampleData 필드 생성하는 코드 작성
※ Sample_String.messageChannel-meta.xml

<?xml version="1.0" encoding="UTF-8" ?>
<LightningMessageChannel xmlns="http://soap.sforce.com/2006/04/metadata">
    <masterLabel>CountUpdated</masterLabel>
    <isExposed>true</isExposed>
    <description>Message Channel to pass Count updates</description>

    <lightningMessageFields>
        <fieldName>operator</fieldName>
        <description>This is the operator type of the manipulation</description>
    </lightningMessageFields>

     <lightningMessageFields>
        <fieldName>sampleString</fieldName>
       <description>This is sampleString</description>
    </lightningMessageFields>

    <lightningMessageFields>
        <fieldName>sampleData</fieldName>
       <description>This is sampleData</description>
    </lightningMessageFields>

</LightningMessageChannel>

3. 코드 작성

※ lwc015RemoteControl.html

<template>
    <div class="wrap">
        <h2>lwc015RemoteControl</h2>
        <input onchange={titleChange} class="custom-input" value="Title" />
    </div>
</template>

※ lwc015RemoteControl.js

import { LightningElement, wire } from 'lwc';
import { publish, MessageContext } from 'lightning/messageService';
import String_UPDATED_CHANNEL from '@salesforce/messageChannel/Sample_String__c';

export default class Lwc015RemoteControl extends LightningElement {
    @wire(MessageContext)
    messageContext;
    
    titleChange(event){
        const newString = event.target.value;
        const newObj = ['바나나', '사과', '딸기'];
        const sendDataValue = { 
            operator: 'sampleData',
            sampleString: newString,
            sampleData : newObj
        };
        console.log('sendDataValue : ', sendDataValue);
        publish(this.messageContext, String_UPDATED_CHANNEL, sendDataValue);
    }
}

※ lwc015RemoteControl.css

.wrap{
    width: 100%;
    max-width: 800px;
    margin: 10px auto;
    background-color: #FFFFFF;
    padding: 20px 10px;
    border-radius: 5px;
    box-shadow: rgba(99, 99, 99, 0.2) 0px 2px 8px 0px;
}
.wrap h2{
    font-weight: bold;
    color: #636363;
    font-size: 20px;
}

※ lwc016Count.html

<template>
    <div class="wrap">
        <h2>lwc016Count</h2>
        <p>받아온 String 값 : {receivedString}</p>
        <p>받아온 Obj 값 : </p>
        <template for:each={receivedObj} for:item="item" for:index="index">
            <p key={item}>{index} - {item}</p>
        </template>
    </div>
</template>

※ lwc016Count.js

import { LightningElement, wire, track } from 'lwc';
import { subscribe, MessageContext } from 'lightning/messageService';
import String_UPDATED_CHANNEL from '@salesforce/messageChannel/Sample_String__c';

export default class Lwc016Count extends LightningElement {
    receivedData = null;

    @wire(MessageContext)
    messageContext;
    @track receivedString;
    @track receivedObj;

    connectedCallback() {
        //첫 로딩시 만들었던 MessageChannel 폴더를 확인하는 class로 실행시키기
        this.subscribeToMessageChannel();
    }
    //첫 로딩시 만들었던 MessageChannel 폴더를 확인하는 class
    subscribeToMessageChannel() {
        this.receivedData = subscribe(
        this.messageContext,
        String_UPDATED_CHANNEL,
        (message) => this.handleMessage(message)
        );
    }
    handleMessage(message) {
        //만들었던 필드 불러오기
        console.log('message.operator : ', message.operator);
        console.log('message.sampleString : ', message.sampleString);
        console.log('message.sampleData : ', message.sampleData);

        this.receivedString = message.sampleString;
        this.receivedObj = message.sampleData;
    }
}

※ lwc016Count.css

.wrap{
    width: 100%;
    max-width: 800px;
    margin: 10px auto;
    background-color: #FFFFFF;
    padding: 20px 10px;
    border-radius: 5px;
    box-shadow: rgba(99, 99, 99, 0.2) 0px 2px 8px 0px;
}
.wrap h2{
    font-weight: bold;
    color: #636363;
    font-size: 20px;
}

4.결과 화면 확인

220926 1번 pubsub 추가

profile
개인 공부 기록용.

0개의 댓글