8

I am providing below the snippets of child, parent and grandparent component, where the child is contained inside the parent component, and the parent is contained inside the grandparent component.

Child

<template>
    <a href="#" onclick={handleClick}>
        <lightning-layout vertical-align="center">
            This is some text
        </lightning-layout>
    </a>
</template>

export default class Child extends LightningElement {
    handleClick(event) {
        event.preventDefault();
        this.dispatchEvent(new CustomEvent('notification'), { bubbles: true, composed: true });
    }
}

Parent:

<template>
    <lightning-card title="EventWithData" icon-name="standard:logging">
        <c-child onnotification={handleNotification}></c-child>
    </lightning-card>
</template>

export default class Parent extends LightningElement {
    handleNotification(event) {
        console.log('This is parent');
    }
}

Grandparent:

<template>
    <c-parent onnotification={handleNotification}></c-parent>
</template>

export default class GrandParent extends LightningElement {
    handleNotification(event) {
        console.log('This is grandParent');
    }
}

I am getting the message from the parent component, signifying that the parent component can listen to the child event, but the grandparent can't listen to the event. Is there something which I am missing?

Please note that I have set the bubbles and composed property of the event as true.

2
  • 2
    As per the documentation you should pass like this new CustomEvent('notification', { bubbles: true, composed: true })
    – vignesh
    Commented Mar 6, 2019 at 7:47
  • This is how I am passing. But still its not working.
    – nica
    Commented Mar 12, 2019 at 16:15

6 Answers 6

3

I just spent a while scratching my head on this too.

This will compile, but the event won't be caught by any components other than the immediate parent:

this.dispatchEvent(new CustomEvent('notification'), { bubbles: true, composed: true });

This, however, will work:

this.dispatchEvent(new CustomEvent('notification', { bubbles: true, composed: true }));

Note the moved ) - in the first example the CustomEvent constructor is never given the bubbles and composed options, so they fallback to their default values of false

2

It works with bubble & composed set to true.

    // Event dispatch on Grand Child

    //Method to show selected tab upon user select
    selectTab(event) {
        event.preventDefault();
        this.dispatchEvent(new CustomEvent('selecttab', {bubbles: true, composed: true, detail :{ selectedIndex: this.tabIdVal}}));
    }

    // Event listener on Grand Parent

    constructor() {
        super();
        this.addEventListener('movetab', this.moveTab.bind(this));
        this.addEventListener('selecttab', this.selectTab.bind(this));      
    }
2
  • It's advised in multiple places not to do this. Commented Dec 17, 2021 at 4:49
  • Also, OP clearly shows that he has set bubbles and composed parameters. Commented Jan 6 at 23:37
0

You can only listen to the events fired by the immediate child. That is child's events can be listened by just parent and not a grandparent.

Check an excerpt from SF Docs:

We don’t recommend bubbling events outside of your own template, but it is possible. To bubble an event to the template that contains your component, dispatch the event on the host element. The event is visible only in the template that contains your component.

As your parent contains child, it can listen to the child's event. Your grandparent doesn't and hence cant listen to child's event.

3
  • 1
    This is from the documentation::: If you configure an event with bubbles: true and composed: true, the event type becomes part of the component’s public API. It also forces the consuming component and all of its ancestors to include the event as part of their APIs. It's a big API contract to sign up for. If you do use this configuration, the event type should be globally unique.
    – nica
    Commented Mar 12, 2019 at 16:21
  • @snl were you able to achieve this using bubble and compose attributes?
    – devforce
    Commented May 7, 2019 at 15:08
  • 2
    No. You need to fire another event from parent component.
    – nica
    Commented May 7, 2019 at 15:16
0

I am able to this with 'bubble' and 'composed' to true with inline event handlers too.

this.dispatchEvent(new CustomEvent('alert', { bubbles: true,
                                              composed: true,
                                              detail: element.value }));

Here is the code snippet.

1
  • LWC docs specifically say not to do this Commented Dec 17, 2021 at 4:49
-1

In hierarchy relation of component set the event attributes bubbles = true, and composed = true , this event can propagate up to the DOM root.

-4

I have edited my response to be more helpful. Upon reviewing your code, I noticed a mistake in the event creation.

Your code: this.dispatchEvent(new CustomEvent('notification'), { bubbles: true, composed: true });

Correct code: this.dispatchEvent(new CustomEvent('notification', { bubbles: true, composed: true }));

The mistake was that the options object (bubbles and composed) was mistakenly placed outside the parentheses of the CustomEvent. By moving the options inside the parentheses, the event will be created correctly with the desired behavior. It's important to note that the default values for bubbles and composed are false, which explains the unexpected behavior you experienced.

for more detail, check this implementation:

https://vijayasankarn.wordpress.com/2022/01/07/salesforce-lwc-multi-level-component-communication-using-events/

Derek F, thanks for your feedback

0

You must log in to answer this question.

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