ApexSensei

Child to parent

A child dispatches a CustomEvent. The parent listens on the child tag. Add bubbles or composed only when that listener is not enough.

An event moves from a child box up to a parent box.

The direct parent

Dispatch from the child with new CustomEvent('selected', { detail: { id: this.recordId } }). The parent listens on the child tag: <c-row onselected={handleSelected}></c-row>.

The defaults are bubbles: false and composed: false. That listener still hears the event, because it sits on the host element that dispatched it. A direct parent does not need either flag. This is the configuration Salesforce recommends.

When bubbles is needed

Set bubbles: true when the listener is on an ancestor inside the same shadow tree, higher than the component that fired the event. The event walks up the DOM and stops at the shadow boundary.

A wrapper in the parent can then listen once for many children. Leave composed false so the event stays inside that shadow tree.

When composed is needed

Set composed: true together with bubbles: true only when the event must cross the shadow boundary and keep going, up toward the document. The event name becomes part of the public API of every ancestor, and another listener with the same name can run by mistake.

Lightning web components do not use composed: true with bubbles: false. For a component that is not in this parent-child tree, use Lightning Message Service on the next page.

Example

javascript

import { LightningElement, api } from 'lwc';

export default class StageRow extends LightningElement {
  @api recordId;

  choose() {
    this.dispatchEvent(new CustomEvent('selected', {
      detail: { id: this.recordId },
    }));
  }
}