Lightning Web Components間で連携する
Lightningアプリケーションビルダーに、Lightning Web Componentsを2つ配置します。
片方の状態が変わったら(例えば、選択した行が切り替わったら)、もう片方の表示を切り替えるということをやってみようとしたら、思ったより苦労しました。(これくらい標準機能でできるものとばかり・・・)
調べて見ますと、pubsub.jsを使うといいということにたどり着きました。
Lightning Web Components間で連携するには、イベントを使います。子コンポーネントから親コンポーネントは、正式なやり方がありますが、コンポーネント間は、自分でやってねってことです。
イベントを管理するソースコードを準備する
自分で管理すると言うことなので、イベントを登録する、イベントを発火させると言った事を担当するソースコードを準備します。インターネット上でみる、pubsub.jsそのものです。
/**
* A basic pub-sub mechanism for sibling component communication
*
* TODO - adopt standard flexipage sibling communication mechanism when it's available.
*/
const events = {};
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
};
イベントを受ける側の実装
イベントを受ける側の実装を行います。
connectedCallbackでイベントを受けるための登録を行います。disconnectedCallbackで登録したイベントを削除します。イベントを受けたときに呼び出すハンドラを実装します。
ここでのポイントは、import { CurrentPageReference } from 'lightning/navigation'; の定義を行う事と、@wire(CurrentPageReference) pageRef; を忘れないことです。
import { LightningElement, track, wire } from 'lwc';
import { CurrentPageReference } from 'lightning/navigation';
import { registerListener, unregisterAllListeners } from 'c/aclPubSub';
export default class AclReceiveOrder extends LightningElement {
/**
* 締めフラグ
*/
@track isClosing = false;
/**
* 現ページ情報
*/
@wire(CurrentPageReference) pageRef;
/**
* 初期化処理
*/
connectedCallback() {
// イベントを受けるための登録を行う
registerListener('changedreceiveorder', this.handleChangedReceiveOrder, this);
}
/**
* 終了処理
*/
disconnectedCallback() {
// 登録したイベントを削除する
unregisterAllListeners(this);
}
/**
* 表示する受注情報の変更
* @param {*} value 受注情報
*/
handleChangedReceiveOrder(value) {
// 締めフラグを設定する
this.isClosing = value;
}
}
イベントを発行する側の実装
次にイベントを発行する側を実装します。
pubsub.jsのfireEventを使います。
こちらでも、import { CurrentPageReference } from 'lightning/navigation'; の定義を行う事と、@wire(CurrentPageReference) pageRef; が必要ですので、お忘れなく。
import { LightningElement, track, wire } from 'lwc';
import { CurrentPageReference } from 'lightning/navigation';
import { fireEvent } from 'c/aclPubSub';
export default class AclReceiveOrderList extends LightningElement {
/**
* 現ページ情報
*/
@wire(CurrentPageReference) pageRef;
/**
* 受注明細がクリックされたら、そのIDをselectedに設定する
* @param {*} event
*/
handleChangedReceiveOrderClick(event) {
// changedreceiveOrderイベントを発行する
fireEvent(this.pageRef, 'changedreceiveorder', event.target.value);
}
}
この記事が気に入ったらサポートをしてみませんか?