在Angular 2中,通过ComponentFactory创建Component似乎没有完全
我正在尝试在Angular 2应用程序中使用ag-grid.因为我使用无限滚动和服务器端过滤,我基本上希望网格中的所有列都有自定义过滤器,然后我可以将其传递到实际执行过滤的服务器.虽然ag-grid有一个相对简单的界面来设置这些自定义过滤器,但在ag-grid文档的Angular 2页面上注意到ag-grid使用了Angular 1编译,并且因为Angular 2不支持编译应用程序启动后,网格中的任何自定义组件(自定义过滤器,单元格,行等)都不支持任何Angular 2功能(如双向数据绑定等).
所以我一直在寻找一种Angular 2方法来动态地将组件加载到ag-grid插入其过滤器弹出窗口的DOM元素中.我已经查看了DynamicComponentLoader(已弃用)以及使用ComponentResolver的几种变体.一旦我获得了ComponentResolver,我可以调用resolveComponent来获取ComponentFactory然后我可以使用@ViewChild来获取ViewContainerRef并在该ViewContainerRef上调用createComponent来创建我的新组件.但是,这对网格没有帮助,因为@ViewChild不会像ag-grid那样直接找到动态添加到DOM的元素. 或者,一旦我获得了ComponentResolver并调用resolveComponent来获取ComponentFactory,我就可以在componentFactory上调用create并从我的ViewContainerRef传递它的注入器和我想要组件插入的元素的字符串标签,并且“似乎“工作,但组件未正确呈现.如果我使用DynamicComponentLoader(即组件未按预期呈现),我会得到类似的行为. 是否有一些可接受的方法在DOM中的特定元素中加载Angular 2 Component? 下面是一些代码来说明问题,我基于Angular 2快速入门: app.component.ts: import { Component,ViewChild } from '@angular/core'; import { ComponentResolver,ViewContainerRef } from '@angular/core'; import { DynComponent } from './dyn.component'; @Component({ selector: 'my-app',template: ` <h1>My test Angular 2 App</h1> <input type="text" class="form-control" required [(ngModel)]="name" > TODO: remove this: {{name}} <p> </p> <div #insertPoint> <button (click)="createDynamicComponent()">Create The Dynamic Component</button> Inserting a new component below this. </div>` }) export class AppComponent { name: string; @ViewChild('insertPoint',{read: ViewContainerRef}) compInsertPoint: ViewContainerRef; constructor(private componentResolver: ComponentResolver){} createDynamicComponent(){ console.log("Creating new Component."); //You're not supposed to manipulate the DOM like this in Angular 2,//but this is what ag-grid is doing var newTextSpan = document.createElement('span'); newTextSpan.innerHTML = `<div id='dynCompDiv'> </div>`; this.compInsertPoint.element.nativeElement.appendChild(newTextSpan); this.componentResolver.resolveComponent(DynComponent) .then(cmpFactory => { const ctxInjector = this.compInsertPoint.injector; //The below commented out createComponent call will create the //component successfully,but I can't figure out how to do the //same thing and have the component created within the above //<div id='dynCompDiv'> // this.compInsertPoint.createComponent(cmpFactory,ctxInjector); //This appears to try to create the component,but the component //is not expanded correctly (missing text,no two-way data //binding) cmpFactory.create(ctxInjector,null,'#dynCompDiv'); }) } } dyn.component.ts import { Component } from '@angular/core'; @Component({ selector: 'dyn-app',template: ` <h1>My test Angular 2 App</h1> <input type="text" class="form-control" required [(ngModel)]="name" > TODO: remove this: {{name}}` }) export class DynComponent { name: string; } 单击app.component中的按钮后得到的HTML(请注意输入类型=“text”中的不匹配以及从“TODO:”开始的以下纯文本) <my-app> <h1>My test Angular 2 App</h1> <input class="form-control ng-untouched ng-pristine ng-invalid" required="" type="text"> TODO: remove this: <p> </p> <div> <button>Create The Dynamic Component</button> Inserting a new component below this. <span> <div id="dynCompDiv"> <h1>My test Angular 2 App</h1> <input class="form-control" required="" type="text"> </div> </span> </div> </my-app> 更新:这是一个使用此示例的Plunker:Angular2 Dynamic Component 更新2:关于上述评论的更多信息,我使用DynamicComponentLoader获得了类似的行为.如果我正确读取Angular代码,那么DynamicComponentLoader基本上就是在做我上面做的事情.它正在解析组件以获取ComponentFactory,然后在该工厂上使用create方法.所以类似的行为很有意义. 更新3:更新了Plunker以使其再次运行: 解决方法
我有一个解决这个问题的办法,足以让我再次活动.如上面注释掉的代码中所述,对ViewContainerRef的createComponent调用确实正确地创建了一个组件.唯一的缺点是你只能将它创建为另一个元素的兄弟,而不是另一个元素.由于ag-grid的getGui调用需要返回DOM元素的html,因此我可以将该组件创建为兄弟,然后在getGui调用中返回该元素.这对我来说似乎不是理想的解决方案,我仍然怀疑ComponentFactory上的create调用是否正常工作,但Angular人员并不认为这是一个错误:
Angular 2 Issue 10523
所以,除了遵循这个解决方法之外,我没有看到任何可口的替代方案. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |