Skip to content

Custom events do not bubble up #2296

Closed
Closed

Description

@SekibOmazic

Couldn't get custom event (ping) bubble up to the root component. DOM event (click) works just fine:
http://plnkr.co/edit/g6RNv5qMreVFKYcwvtOs?p=preview

Using alpha.25

Activity

  1. PatrickJS commented on Jun 2, 2015

    @PatrickJS
    Contributor

    ^ should be working for the custom event <grand-child (^ping)="onPing($event)" ></grand-child> :/

  2. SekibOmazic commented on Jun 2, 2015

    @SekibOmazic
    ContributorAuthor

    @gdi2290 By design? If so, should I close the issue? And is there a workaround?

  3. PatrickJS commented on Jun 2, 2015

    @PatrickJS
    Contributor

    @SekibOmazic oh no sorry, this seems like a bug since it should be working

  4. vicb commented on Jun 2, 2015

    @vicb
    Contributor

    Dup of #1254 ?

  5. PatrickJS commented on Jun 2, 2015

    @PatrickJS
    Contributor

    ah okay, if it's by design then it means you should create your own ping event to be sent up rather than delegate to a component's event. That makes sense since it's better decoupling but also confusing since it's not enforced with native events like ^click

  6. SekibOmazic commented on Jun 2, 2015

    @SekibOmazic
    ContributorAuthor

    @gdi2290 That seems very verbose. So every component in the chain would need to re-send event?
    Like:
    -parent (listen to ping)
    -- child (listen to ping and resend the ping - even if not interested in)
    ---- grand child (emit ping event)

  7. PatrickJS commented on Jun 2, 2015

    @PatrickJS
    Contributor

    @SekibOmazic I updated the example so it works. It's verbose I agree but it does make each component more loosely coupled but it forces it rather than allowing the developer to take advantage of ^

    http://plnkr.co/edit/MYYuNm?p=preview

  8. SekibOmazic commented on Jun 2, 2015

    @SekibOmazic
    ContributorAuthor

    @gdi2290 OK thanks. This may by so by design but now we have 2 different behaviours:

    • for native DOM events bubbling up works to the root element
    • for custom events bubbling up works to parent only and an event has to be resent if you need it in ancestor

    Not very intuitive IMHO.

  9. 2fdevs commented on Jun 16, 2015

    @2fdevs

    +1 this needs to be reviewed I think.

    @SekibOmazic as a workaround we're using CustomEvent(): https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events

    Maybe a parameter (bubbles=true) when emitting the event could do the trick:

    class TodoCmp {
      complete = new EventEmitter();
    
      onCompletedButton() {
        this.complete.next({bubbles: true});
      }
    }
  10. ericmdantas commented on Jul 27, 2015

    @ericmdantas
    Contributor

    It'd be definetely nice to have the ^ to work with custom events as well.

  11. 61 remaining items

  12. csquillen commented on Nov 1, 2016

    @csquillen

    Will the event bubbling/emission solution be compatible with "routed" components?

    Meaning components placed in the DOM via <router-outlet></router-outlet>. As of now, there is no way to emit events from "routed" components as far as I know.

    IMO, complex applications will make heavy use of the router, not only for "pages", but also for tabs and such. Ideally, these routed components would use the same component model as custom tags in terms of input and output.

  13. zoechi commented on Nov 1, 2016

    @zoechi
    Contributor

    you can dispatch DOM events and they bubble as usual, but as of now there is no way to have bubbling events from outputs

  14. added this to the Backlog milestone on Jan 23, 2018
  15. added
    needs: clarificationThis issue needs additional clarification from the reporter before the team can investigate.
    and removed on Oct 1, 2020
  16. yjaaidi commented on Oct 29, 2020

    @yjaaidi
    Contributor

    I was about to open an issue and stumbled upon this old one so I will try to revive it 😊

    Use Case

    The app loads dynamic markdown content. This markdown is processed with a third party library like Marked where we add a special links handler that replaces links with our custom elements (using Angular Elements). These elements trigger custom events that we want to handle in the parent component (the one that loaded the markdown).

    The general idea is that we can let a 3rd party (non-Angular) library control the DOM and inject our Angular Elements but we want to keep communicating with these elements without having to dispatch bubbling events manually or using an indirection like a provider or state management etc...

    Solutions

    Solution A

    1. Create a new CustomEventEmitter where we can configure bubbles and cancelable:
    new CustomEventEmitter({bubbles: true, cancelable: false})

    We can't use EventEmitter because bubbles and cancelable will be simply ignored and confusing when not using Angular elements

    1. Change ComponentNgElementStrategy in order to handle CustomEventEmitter differently instead of merging all emitters:

      readonly events = this.eventEmitters.pipe(switchMap(emitters => merge(...emitters)));

    2. Change createCustomElement in order to handle bubbles and cancelable:

      this.ngElementEventsSubscription = this.ngElementStrategy.events.subscribe(e => {
      const customEvent = createCustomEvent(this.ownerDocument!, e.name, e.value);
      this.dispatchEvent(customEvent);
      });

    3. Change createCustomEvent to allow the control of bubbles and cancelable:

      export function createCustomEvent(doc: Document, name: string, detail: any): CustomEvent {
      const bubbles = false;
      const cancelable = false;
      // On IE11, `CustomEvent` is not a constructor.
      if (typeof CustomEvent !== 'function') {
      const event = doc.createEvent('CustomEvent');
      event.initCustomEvent(name, bubbles, cancelable, detail);
      return event;
      }
      return new CustomEvent(name, {bubbles, cancelable, detail});
      }

    4. [OPTIONAL] Should we deprecate EventEmitter usage with Angular elements? Allowing both can be confusing?

    Solution B

    Create a new CustomEventEmitter which is an EventEmitter of type EventEmitter<{bubbles?: boolean, cancelable?: boolean, detail?: T}> so every event can have a different bubbling strategy... but that would be a surprising behavior so I am not a big fan of this one.

    Solution C

    @2fdevs idea: adding a bubbles field to the event.
    It's a quick fix but it's a surprising behavior which is hard to document and mixes event data with metadata (e.g. bubbles)

    cc. @jelbourn @IgorMinar @mhevery

  17. gkalpak commented on Oct 29, 2020

    @gkalpak
    Member

    Thx for the detailed write-up, @yjaaidi!

    This issue seems to be about @Outputs of regular components (also called "custom events" back in the day 😃) and not about the CustomEvents emitted from Angular Elements (i.e. Angular components converted to Custom Elements).

    Since your use-case seems to be specific to @angular/elements, I think it would be better to open a separate issue (and potentially link to this one for context).

  18. yjaaidi commented on Oct 29, 2020

    @yjaaidi
    Contributor

    Thanks @gkalpak! In fact, I hesitated between opening a new issue or reusing this vintage one and avoid pollution 😊
    I'm opening a new one right now!

  19. petebacondarwin commented on Sep 16, 2021

    @petebacondarwin
    Contributor

    We discussed this feature in our triage meeting and decided that it is not something we want to support with outputs.
    The semantics of an output are very clear: they provide a way to attach a handler to some action occurring on a component, directive or element that appears in a template. Changing that semantic to cover nested components, directives, or elements makes it much harder to reason about the template.

    If bubbling events are required then it is still possible to use the DOM event system directly.
    Also another common Angular pattern would be to use a service provided on a component that wishes to receive events and for descendant components to inject the service and use it to publish events.

  20. angular-automatic-lock-bot commented on Oct 17, 2021

    @angular-automatic-lock-bot

    This issue has been automatically locked due to inactivity.
    Please file a new issue if you are encountering a similar or related problem.

    Read more about our automatic conversation locking policy.

    This action has been performed automatically by a bot.

  21. locked and limited conversation to collaborators on Oct 17, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

area: coreIssues related to the framework runtimecore: inputs / outputseffort1: hoursfeatureLabel used to distinguish feature request from other issuesfeature: under considerationFeature request for which voting has completed and the request is now under considerationneeds: clarificationThis issue needs additional clarification from the reporter before the team can investigate.state: Needs Design

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions