从 DOM 元素获取 ComponentRef

Get ComponentRef from DOM element

已经回答了如何从 Angular 2 组件中获取 DOM 元素:ComponentRef.location.nativeElement(ComponentRef.location 给出了直接访问的 ElementRef DOM).

但是如何做相反的事情,即当我只有本机 DOM 对象时获取对 ComponentRef 的引用?

当我尝试使用 interact.js drag/drop Angular 2 个组件时,我遇到了这种情况。该库使用回调函数来通知哪个元素被拖动,以及我们试图放置在哪个元素上。提供了一个 event 对象,我找到的唯一有用信息是 DOM 元素(target 属性)。

示例:

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

您可以查看 src/Interactjs.ts 中的处理程序。打开控制台以查看关联的日志并将一个组件拖放到另一个上。我有关于 DOM 元素的信息,但我想要 Angular 组件,假设访问 count 属性。

发现和尝试:

我找到了一个solution for the jquery-ui-draggable plugin,但是这个技巧在这里不起作用,至少对于目标落在哪里是这样。

也有topics关于如何在DOM中插入,说的是DomAdapter,但是我还没找到任何方法似乎可以帮助从DOM到Angular组件参考。

我只是想手动搜索我的组件:在DOM个节点中循环,计数找到位置,并从组件列表中找到相同位置的组件,但是太丑了...

欢迎就此提出任何建议。感谢阅读!

这可以使用 ElementProbe API 来实现。主要用于调试/量角器集成,类似于Angular中的element.scope() 1.

为了使用此 API,您需要在 bootstrap() 调用中包含 ELEMENT_PROBE_PROVIDERS。然后,您将能够通过调用全局 ng.probe() 来获取任何组件实例。

例如,这是获取当前事件目标的组件实例的方法:

ng.probe(event.target).componentInstance

Updated Plunker showing this is action

您可以看到 ElementProbe 的实际实现 API Here.

我不得不这样做。我能够通过在 "parent" 组件 class 中使用 @ViewChildren 的组合并在 "child" 组件本身上设置唯一标识符来完成它。

因此,对于 parent 组件,您有:

@ViewChildren(YourChildComponent)
elements: QueryList<YourChildComponent>;

然后,在您的 child 组件中,执行以下操作(请注意,我导入了 angular2 uuid 包,但您可以使用任何机制来生成唯一 ID):

constructor(private elementRef:ElementRef) {    
    this.UniqueID = UUID.UUID();
    this.elementRef.nativeElement.setAttribute('unique-id', this.UniqueID);
}

 //and we define a public property here
UniqueID: string;

现在,您可以访问您的 children 并按如下标识符匹配它们:

private findElementByNativeDOMObject(el: any) : YourChildComponent{


let uniqueId = el.attributes.getNamedItem('unique-id').value;
if ( ! uniqueId)
  return null;

// ok, let's go through our children
return this.elements.find( x=> x.UniqueID == uniqueId);

}