Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get ComponentRef from DOM element

It has already been answered how to get the DOM element from an Angular 2 component: ComponentRef.location.nativeElement (ComponentRef.location gives the ElementRef that gives a direct access to DOM).

But how to do the opposite, i.e. get the reference to the ComponentRef when I only have the native DOM object?

I am in the case when I try to drag/drop Angular 2 components using interact.js. The library uses callback functions to notify which element is dragged, and on which element we are trying to drop. An event object is provided, and the only useful information I found was the DOM element (target attribute).

Example:

interact('my-component-tag').draggable({
    // ...
    onstart: function (event:any) {
        var dom = event.target; // ref to the <my-component-tag> tag
        // How to find the Angular ComponentRef object here?
    }
    // ...
}).dropzone({
    // ...
    ondragenter: function (event:any) {
        var targetDom = event.relatedTarget; // targeted <my-component-tag> tag
        // Same question here,
        // to identify where we want to insert the dragged element.
    }
    // ...
});

Plunker here

You can check the handlers in src/Interactjs.ts. Open the console to see associated logs and drop a component on another. I have information about elements by the DOM, but I want Angular components instead, let's say access the count attribute.

Findings and tries:

I found a solution for the jquery-ui-draggable plugin, but this trick does not work here, at least for the target where to drop.

There are also topics about how to insert in the DOM, talking about the DomAdapter, but I haven't found any method that seems to help from DOM to Angular component reference.

I just thought about a manual search over my components: looping in the DOM nodes, count to find the position, and reach the component from the component list at the same position, but it is so ugly...

Any advice on that is welcome. Thanks for reading!

like image 826
Antoine OL Avatar asked Nov 19 '15 13:11

Antoine OL


1 Answers

This could be achieved using the ElementProbe API. It is mainly intended for debugging / protractor integration, similar to element.scope() in Angular 1.

In order to use this API, you would need to include ELEMENT_PROBE_PROVIDERS in your bootstrap() call. You will then be able to get any component instance by calling the global ng.probe().

For example, here is how you get the component instance for the current event target:

ng.probe(event.target).componentInstance

Updated Plunker showing this is action

You can see the actual implementation of the ElementProbe API Here.

like image 83
urish Avatar answered Sep 22 '22 15:09

urish