sir_thursday
sir_thursday

Reputation: 5409

Get Angular component class from DOM element

I believe the answer to this is "no", but is there a method/service in Angular where I can pass in a component's root DOM node (e.g. <foo-component>) and receive the component instance (e.g. FooComponent)?

I couldn't find an associated SO post on this.

Example:

<foo-component id="foo"></foo-component>

const fooElement: HTMLElement = document.getElementById('foo');
const fooInstance: FooComponent = getInstanceFromElement(fooElement);

Is there a method in Angular like getInstanceFromElement?

Edit:

I can't use ViewChild... I'm looking for a global service I can use. Suppose I am not invoking this method from the component class. I'm well acquainted with ViewChild/ContentChild and they are not what I'm looking for. Suppose I am in a globally injected service and am trying to do something like the following:

class MyService {
  constructor() {}

  getInstanceFromElement(element: HTMLElement): Component<T> {
    // Is there some special helper service I can use here?
  }
}

Upvotes: 10

Views: 4363

Answers (4)

ender
ender

Reputation: 758

This is simple in Angular. @ViewChild/@ViewChildren and @ContentChild/@ContentChildren return the component reference/QueryList<Component> by default during the ngAfterViewInit and ngAfterContentInit lifecycles.

For Example:

@Component({
  template:`<foo-component></foo-component>`
})
export TestComponent implements AfterViewInit {
  @ViewChild(FooComponent, { static: false }) fooComponent: FooComponent;

  ngAfterViewInit() {
    console.log(this.fooComponent)
  }

For directives, you can use a template variable if the directive specifies an exportAs. See https://netbasal.com/angular-2-take-advantage-of-the-exportas-property-81374ce24d26 for a good write up.

Upvotes: -1

Adrita Sharma
Adrita Sharma

Reputation: 22213

Try like this:

Working Demo

Template:

<foo-component #foo></foo-component>

TS:

  @ViewChild('foo', { static: false }) fooComponent: FooComponent;

  ngAfterViewInit() {
    console.log(this.fooComponent)
  }

Upvotes: 1

dave0688
dave0688

Reputation: 5770

Yes, there is. @ViewChild() was the right hint here. Let me give you an example:

@ViewChild('editorStepsDomElements', { static: false, read: ElementRef }) fooComponentDomElement: ElementRef;
@ViewChild('fooComponent', { static: false, read: FooComponent }) fooComponent: FooComponent;

So basically you can define in the ViewChild() what you want to get. Just set the read parameter to either ElementRef (for getting the DOM element), or to the respective component you want to get.

Upvotes: 2

Neda Peyrone
Neda Peyrone

Reputation: 340

Yes, You can do with Dynamic Component Loader to attach a component dynamically to the DOM. Follow this link

Upvotes: -1

Related Questions