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.
}
// ...
});
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!
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 yourbootstrap()
call. You will then be able to get any component instance by calling the globalng.probe()
.For example, here is how you get the component instance for the current event target:
Updated Plunker showing this is action
You can see the actual implementation of the ElementProbe API Here.
I just had to do this. I was able to accomplish it by using a combination of @ViewChildren in the "parent" component class and setting a unique identifier on the "child" component itself.
So, it the parent component, you have:
Then, in your child component, you do the following (note that I imported the angular2 uuid package, but you can use any mechanism for generating a unique id):
Now, you can access your children and match them up by identifier like this:
}