0

There are 3 data providers,

OrderDataProvider (available at Page level),

OrderDeliveryGroupsDataProvider (dependent on OrderDataProvider property -> DeliveryGroups),

OrderLineItemsDataProvider (dependent on OrderDeliveryGroupsDataProvider property -> lineItems)

Now I am dispatching the event from OrderLineItemsDataProvider and receiving it in OrderDataProvider

This is the code for OrderDataProvider Side

const ORDER_LINE_ITEMS_FIELDS_UPDATED = 'orderLineItemsFieldsUpdated';
private _handleOrderLineItemsFields: (event: Event) => void = this.handleOrderLineItemsFields.bind(this);
connectedCallback(): void {
    this.addEventListener(ORDER_DG_FIELDS_UPDATED, this._handleOrderDeliveryGroupsFields);
    console.log("Add event listener in Order DataProvider");
    this.addEventListener(ORDER_LINE_ITEMS_FIELDS_UPDATED, this._handleOrderLineItemsFields);
}

disconnectedCallback(): void {
    this.removeEventListener(ORDER_DG_FIELDS_UPDATED, this._handleOrderDeliveryGroupsFields);
    console.log("Remove event listener in Order DataProvider");
    this.removeEventListener(ORDER_LINE_ITEMS_FIELDS_UPDATED, this._handleOrderLineItemsFields);
}
    handleOrderLineItemsFields(event: Event): void {
    event.stopPropagation();
    const fieldsToFetch = [...this._fields, ...((event as CustomEvent).detail?.fields || [])];
    console.log('Inside Order Data Provider Event HANDLER OLI ', JSON.stringify(fieldsToFetch));
    if (fieldsToFetch.length > 0 && !deepEqual(this._fields, fieldsToFetch).value) {
        console.log('updating fields');
        this._requiredFields = fieldsToFetch;
    }
}

This is the code for OrderLineItemsDataProvider

@track _fields: string[] = [];
@api
// @ts-ignore : 'sfdcFields' is defined as a property in class 'DataProvider', but is overridden here in 'OrderLineItemsDataProvider' as an accessor.
// ToDo - Remove ts-ignore once TypeScript supports overridding property with an accessor.
get sfdcFields(): string[] {
    return this._fields;
}
set sfdcFields(builderExpression: string[]) {
    // console.log('Order Line Item sfdcFields ', JSON.stringify(builderExpression));
    // Map and filter the builder expression to format and set the SFDC fields
    this._fields = builderExpression
        .map((field: string) => {
            if (!field.includes('.') && !field.includes('_data')) {
                field = `OrderItemSummary.${field}`;
            }
            field = field
            .replace(/^(fields\.)/, 'OrderItemSummary.')
            .replace('product.fields', 'Product2')
            .replace('product', 'Product2')
            .replace('.text', '');
            return field;
        })
        .filter((field: string) => field !== '_data' && field !== '');

    if (!import.meta.env.SSR) {
        console.log("Firing Event");
        console.log('Order Line Item sfdcFields ', JSON.stringify(this._fields));
        this.dispatchEvent(
            new CustomEvent(ORDER_LINE_ITEMS_FIELDS_UPDATED, {
                bubbles: true,
                composed: true,
                detail: {
                    fields: this._fields,
                },
            })
        );
        console.log("Event Fired");
    }
}

I have verified using console.log() statements that it is working absolutely correct in Experience Builder Console Logs, but during Runtime (Buyer Site) its seems that the event is not propagating to the OrderDataProvider,

PS: I have already tried with composed: true, but that also didn't work,

Below is the SS for runtime logs,

enter image description here

Below is the SS from Experience Builder

enter image description here

7
  • Can you add code that registers this event? Commented May 18, 2024 at 13:12
  • @SachinHooda didn't get that, i am dispatching the event from OrderLineItemsDataProvider and for same added listeners in OrderDataProvider , please let me know if something is missed! Commented May 18, 2024 at 14:07
  • Why are you programmatically adding listeners instead of using oneventname handler mappings in the parent component markup?
    – Phil W
    Commented May 18, 2024 at 15:39
  • there is no html involved as these are data providers so need to do it programatically only Commented May 18, 2024 at 16:21
  • 1
    Uh, I think events propagate up the DOM hierarchy, which is probably your problem. You likely need to communicate directly by passing the parent reference down to the child so the child can call an API function on it with the details...
    – Phil W
    Commented May 18, 2024 at 18:05

1 Answer 1

0

Since the components are directly placed on the pages and does not share any direct relation. The event propagates up in the dom hierarchy which appears to be the issue here.

When you do this.addEventListener, the listener gets attached to the component element and if you see DOM hierarchy for the publisher, the subscriber will not be there at all. Because they acts as sibiling components.

Instead this, if you attach listener to window element. You would be able to listen to those event ( considering they propagates up to the root of the DOM ). For simple use cases, if you replace with,

connectedCallback(): void {
    window.addEventListener(ORDER_DG_FIELDS_UPDATED, this._handleOrderDeliveryGroupsFields);
    console.log("Add event listener in Order DataProvider");
    window.addEventListener(ORDER_LINE_ITEMS_FIELDS_UPDATED, this._handleOrderLineItemsFields);
}
disconnectedCallback(): void {
    window.removeEventListener(ORDER_DG_FIELDS_UPDATED, this._handleOrderDeliveryGroupsFields);
    console.log("Remove event listener in Order DataProvider");
    window.removeEventListener(ORDER_LINE_ITEMS_FIELDS_UPDATED, this._handleOrderLineItemsFields);
}

but i would recommend using some state management store like Redux to handle these data communications for complex scenarios. Try example from this SE answer to understand how event propagates.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .