为了与执行DOM操作的原生本地JavaScript库集成,我希望能够将Angular管理的视图附加到document
中的任何DOM元素。
让我们说 SomeLibrary 在DOM中的某个地方创建一个容器(我们给它一个可以注入HTML的目标节点):
<body>
<angular-app-root>
<!-- here... -->
<div id="some-library-created-this"></div>
</angular-app-root>
<!-- or more likely, here... -->
<div id="some-library-created-this"></div>
</body>
我引用了div#some-library-created-this
DOM节点。
现在,我有一个可以像这样使用的Angular组件:
<angular-component [angularInput]="value">
<!-- what follows isn't the `template`, but what would get set in a ng-content inside of AngularComponent's template -->
<h1>Embedded Content Children</h1>
<hr>
<another-angular-component></another-angular-component>
</angular-component>
此AngularComponent
现在应该获取其中设置的内容,并将其显示在我们已获得的div#some-library-created-this
节点内。
也就是说,组件的内容不会显示在已声明组件的位置,而是显示在任何给定本机元素中的其他位置。
类似的东西:
<body>
<angular-app-root></angular-app-root>
<div id="some-library-created-this">
<some-kind-of-wrapper> <!-- ? -->
<h1>Embedded Content Children</h1>
<hr>
<another-angular-component></another-angular-component>
</some-kind-of-wrapper>
</div>
</body>
这甚至可能吗?是否有同等的解决方案可以让我从利用Angular的功能中受益于 SomeLibrary 的非托管DOM操作逻辑?
我已经阅读了一些显示类似和高级用例的帖子,如下所示:
但那些只谈论创建事先已知的组件,并专门为给定的视图创建它们,而不仅仅是把它们扔到屏幕上的其他地方。
答案 0 :(得分:1)
我设法用<ng-template>
来做,这更好,因为在本机库显示其DOM元素之前,组件内部的视图未实例化。此外,这使我可以在同一组件体内定位本机库的不同DOM节点,如下所示:
<angular-component [angularInput]="value">
<form *angularComponentPartial [formControl]="myForm">
...
</form>
<ng-container *angularComponentPartial="angularComponentTargets.otherKnownDomNode">
Send ({{ secondsLeft }} seconds left)
</ng-container>
</angular-component>
自定义*angularComponentPartial
结构指令用于获取用户定义内容的TemplateRef。然后,它在ComponentFactoryResolver
的帮助下创建一个特殊组件并将其安装在库DOM节点上。
它将TemplateRef传递给该组件,该组件的唯一作用是显示模板,这要归功于一个简单的模板插座:
<ng-container *ngTemplateOutlet="template"></ng-container>
AngularComponent甚至不必处理伪造的转换逻辑。只涉及结构指令和微小的模板支架组件。
如果您对详细信息的实现感兴趣,那就是开源的!我在toverux/ngsweetalert2中使用它(在写作时,它仍然在next
分支中)。它用于在SweetAlert2模式中显示动态内容。