在 Angular 中显示应用程序根目录之外的托管视图
Display a managed view outside of the application root in Angular
为了与执行 DOM 操作的现有本机 JavaScript 库集成,我希望能够将 Angular 管理的视图附加到任何 [= document
.
中的 56=] 元素
假设 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>
这可能吗?是否有等效的解决方案可以让我从 SomeLibrary 的非托管 DOM 操作逻辑中受益,同时利用 Angular 的功能?
我读过一些显示相似和高级用例的帖子,例如:
- https://medium.com/front-end-hacking/dynamically-add-components-to-the-dom-with-angular-71b0cb535286
- https://www.lucidchart.com/techblog/2017/04/10/using-angular-2-components-in-a-non-angular-app/(很有意思,顺便说一句)
但那些只谈论创建预先知道的组件,并专门为给定视图创建它们,而不是将它们扔到屏幕上的其他地方。
我设法用 <ng-template>
s 做到了,这更好,因为组件内部的视图在本机库显示其 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 模态中显示动态内容。
为了与执行 DOM 操作的现有本机 JavaScript 库集成,我希望能够将 Angular 管理的视图附加到任何 [= document
.
假设 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>
这可能吗?是否有等效的解决方案可以让我从 SomeLibrary 的非托管 DOM 操作逻辑中受益,同时利用 Angular 的功能?
我读过一些显示相似和高级用例的帖子,例如:
- https://medium.com/front-end-hacking/dynamically-add-components-to-the-dom-with-angular-71b0cb535286
- https://www.lucidchart.com/techblog/2017/04/10/using-angular-2-components-in-a-non-angular-app/(很有意思,顺便说一句)
但那些只谈论创建预先知道的组件,并专门为给定视图创建它们,而不是将它们扔到屏幕上的其他地方。
我设法用 <ng-template>
s 做到了,这更好,因为组件内部的视图在本机库显示其 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 模态中显示动态内容。