Skip to content

feat(elements): expose custom element connected-disconnected lifecycle to the Angular component #70905

Description

@MillerSvt

Which @angular/* package(s) are relevant/related to the feature request?

elements

Description

@angular/elements handles the native Custom Elements lifecycle (connectedCallback / disconnectedCallback) internally, but the Angular component used as a custom element has no public API to react to those transitions.

This matters because connection/disconnection is not the same lifecycle as component creation/destruction. A custom element can be removed from the DOM and later inserted again while representing the same logical element.

There are several cases where component code needs to know about this:

  • restore scroll;
  • refresh state after an element is reconnected;
  • reinitialize integrations that depend on the element being present in the document;
  • distinguish a temporary disconnection/reconnection from the component's final destruction.

ngOnInit / ngOnDestroy are not a good abstraction for this because they describe the Angular component lifetime, not the native custom element connection lifetime.

Related issues such as #33490 discussed exposing or extending ComponentNgElementStrategy, while #64229 discusses the broader lifecycle model of Angular Elements. This request is narrower: expose the already-known connection state directly to code inside the Angular component without requiring a custom NgElementStrategy.

A working implementation of this API exists in ng-elementum:

MillerSvt/ng-elementum@f1d2385

Proposed solution

Provide injection-context lifecycle functions for components instantiated as Angular custom elements, for example:

import {
  afterConnected,
  afterDisconnected,
  afterNextConnected,
  afterNextDisconnected,
} from '@angular/elements';

@Component({
  template: `...`,
})
export class MyElementComponent {
  constructor() {
    afterConnected(() => {
      // Runs whenever the custom element is connected to the DOM.
    });

    afterDisconnected(() => {
      // Runs whenever the custom element is disconnected from the DOM.
    });
  }
}

Suggested semantics:

  • afterConnected(callback) runs for every connection, including the initial connection.
  • afterDisconnected(callback) runs for every disconnection.
  • afterNextConnected(callback) and afterNextDisconnected(callback) are optional one-shot variants, consistent with APIs such as afterNextRender.
  • Registration must happen in an Angular injection context and should be scoped to the custom-element host that owns the component.
  • The connected callback should run after the component has been rendered, so initialized inputs and rendered DOM are available.
  • Reconnecting the same custom element should invoke the connection callback again.

The exact API names are not essential; the important part is providing a supported component-level way to observe the custom element connection lifecycle.

Alternatives considered

Implementing a custom NgElementStrategy

This can intercept connect() / disconnect(), but it requires replacing or wrapping Angular Elements infrastructure for something that is fundamentally component lifecycle information. It also tightly couples application code to strategy implementation details.

Observing the host with MutationObserver / Node.isConnected

This duplicates information already available to @angular/elements through connectedCallback and disconnectedCallback, adds browser-specific plumbing, and can introduce ordering problems.

Using ngOnInit / ngOnDestroy

These represent creation/destruction of the Angular component and do not model repeated connection/disconnection of a custom element.

Passing callbacks into createCustomElement()

This exposes the lifecycle to the element factory/host application rather than to the component that needs to manage its own resources.


This issue description was generated with the assistance of artificial intelligence.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: elementsIssues related to Angular Elementsgemini-triagedLabel noting that an issue has been triaged by gemini

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions