如何动态创建引导模式作为 Angular2 组件? [英] How to dynamically create bootstrap modals as Angular2 components?
问题描述
原标题:无法在 Angular 2 中初始化动态附加 (HTML) 组件
我创建了一个指令,在初始化时将模态附加到主体.当一个按钮(注入了指令)被点击时,这个模式会启动.但我希望这个模态的内容是另一个组件(实际上我希望模态是组件).好像不能初始化组件.
这是我所做的工作:
http://plnkr.co/edit/vEFCnVjGvMiJqb2Meprr?p=preview
我正在尝试让 my-comp 成为我组件的模板
''+ '<my-comp></my-comp>'+'</div> 解决方案 2.0.0 最终版的更新
@NgModule({进口:[浏览器模块],声明:[ App, ModalComponent, CompComponent],提供者:[共享服务],entryComponents: [CompComponent],引导程序:[ App, ModalComponent ]})导出类 AppModule{}
export class ModalComponent {@ViewChild('theBody', {read: ViewContainerRef}) theBody;cmp:组件引用;构造函数(共享服务:共享服务,私有 componentFactoryResolver: ComponentFactoryResolver,喷油器:喷油器){sharedService.showModal.subscribe(type => {如果(this.cmp){this.cmp.destroy();}let factory = this.componentFactoryResolver.resolveComponentFactory(type);this.cmpRef = this.theBody.createComponent(工厂)$('#theModal').modal('show');});}关闭() {如果(this.cmp){this.cmp.destroy();}this.cmp = null;}}
提示
如果一个应用程序更改了 SharedService
中的状态或调用了导致 Observable
发出值的方法,并且订阅者位于不同的应用程序中,则发射器、订阅者中的代码在发射器的 NgZone
中执行.
因此在SharedService
中订阅一个observable时使用
class MyComponent {构造函数(私有区域:NgZone,私有共享服务:SharedService){私有 sharedService.subscribe(data => this.zone.run() => {//这里的事件处理代码});}}
有关如何触发更改检测的更多详细信息,请参阅手动触发 Angular2 更改检测
原创
动态添加的 HTML 不会被 Angular 处理,也不会导致组件或指令被实例化或添加.
您不能使用 DynamicComponentLoader
(已弃用)ViewContainerRef.createComponent()
(用户点击选择组件的Angular 2动态标签).
我想最好的方法是在 Angulars 根组件之外创建第二个组件是在每个组件上调用 bootstrap()
并使用共享服务进行通信:
var sharedService = new SharedService();bootstrap(AppComponent, [provide(SharedService, {useValue: sharedService})]);bootstrap(ModalComponent, [provide(SharedService, {useValue: sharedService})]);
Plunker 示例 beta.17
Plunker 示例 beta.14
@Injectable()导出类 SharedService {showModal:Subject = new Subject();}@成分({选择器:'comp-comp',模板:`MyComponent`})导出类 CompComponent { }@成分({选择器:'modal-comp',模板:`<div class="modalfade" id="theModal" tabindex="-1" role="dialog" aria-labelledby="theModalLabel"><div class="modal-dialog largeWidth" role="document"><div class="modal-content"><div class="modal-header"><h4 class="modal-title" id="theModalLabel">标签</h4></div><div class="modal-body" #theBody>
<div class="modal-footer"><button type="button" class="btn btn-default" data-dismiss="modal" (close)="close()">关闭</button></div></div></div></div>`})导出类 ModalComponent {cmp:组件引用;构造函数(共享服务:共享服务,dcl:DynamicComponentLoader,注入器:注入器,元素引用:元素引用){sharedService.showModal.subscribe(type => {如果(this.cmp){this.cmp.dispose();}dcl.loadIntoLocation(type, elementRef, 'theBody').then(cmp => {this.cmp = cmp;$('#theModal').modal('show');});});}关闭() {如果(this.cmp){this.cmp.dispose();}this.cmp = null;}}@成分({选择器:'我的应用',模板:`<h1>我的第一个属性指令</h1><button (click)="showDialog()">显示模态</button><br><br>`,})导出类 AppComponent {构造函数(私有共享服务:共享服务){}显示对话框(){this.sharedService.showModal.next(CompComponent);}}
Original title: Can't initialize dynamically appended (HTML) component in Angular 2
I've created a directive that appends a modal to the body on initialization. When a button (with the directive injected into it) is clicked this modal fires up. But I want the contents of this modal to be another component (In fact I want the modal to be the component). It seems that I can't initialize the component.
Here is a plunker of what I've done:
http://plnkr.co/edit/vEFCnVjGvMiJqb2Meprr?p=preview
I'm trying to make my-comp the template of my component
'<div class="modal-body" #theBody>'
+ '<my-comp></my-comp>' +
'</div>
update for 2.0.0 final
@NgModule({
imports: [ BrowserModule ],
declarations: [ App, ModalComponent, CompComponent],
providers: [SharedService],
entryComponents: [CompComponent],
bootstrap: [ App, ModalComponent ]
})
export class AppModule{}
export class ModalComponent {
@ViewChild('theBody', {read: ViewContainerRef}) theBody;
cmp:ComponentRef;
constructor(
sharedService:SharedService,
private componentFactoryResolver: ComponentFactoryResolver,
injector: Injector) {
sharedService.showModal.subscribe(type => {
if(this.cmp) {
this.cmp.destroy();
}
let factory = this.componentFactoryResolver.resolveComponentFactory(type);
this.cmpRef = this.theBody.createComponent(factory)
$('#theModal').modal('show');
});
}
close() {
if(this.cmp) {
this.cmp.destroy();
}
this.cmp = null;
}
}
Hint
If one application change the state in SharedService
or calls a method that causes an Observable
to emit a value and the subscriber is in a different application then the emitter, the code in the subscriber is executed in the NgZone
of the emitter.
Therefore when subscribing to an observable in SharedService
use
class MyComponent {
constructor(private zone:NgZone, private sharedService:SharedService) {
private sharedService.subscribe(data => this.zone.run() => {
// event handler code here
});
}
}
For more details how to trigger change detection see Triggering Angular2 change detection manually
original
Dynamically added HTML is not processed by Angular and doesn't result in components or directives to be instantiated or added.
You can't add components outside Angulars root component (AppComponent) using (deprecated) DynamicComponentLoader
ViewContainerRef.createComponent()
(Angular 2 dynamic tabs with user-click chosen components).
I guess the best approach is to create a 2nd component outside Angulars root component is to call bootstrap()
on each and use a shared service to communicate:
var sharedService = new SharedService();
bootstrap(AppComponent, [provide(SharedService, {useValue: sharedService})]);
bootstrap(ModalComponent, [provide(SharedService, {useValue: sharedService})]);
Plunker example beta.17
Plunker example beta.14
@Injectable()
export class SharedService {
showModal:Subject = new Subject();
}
@Component({
selector: 'comp-comp',
template: `MyComponent`
})
export class CompComponent { }
@Component({
selector: 'modal-comp',
template: `
<div class="modal fade" id="theModal" tabindex="-1" role="dialog" aria-labelledby="theModalLabel">
<div class="modal-dialog largeWidth" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="theModalLabel">The Label</h4></div>
<div class="modal-body" #theBody>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal" (close)="close()">Close</button>
</div></div></div></div>
`
})
export class ModalComponent {
cmp:ComponentRef;
constructor(sharedService:SharedService, dcl: DynamicComponentLoader, injector: Injector, elementRef: ElementRef) {
sharedService.showModal.subscribe(type => {
if(this.cmp) {
this.cmp.dispose();
}
dcl.loadIntoLocation(type, elementRef, 'theBody')
.then(cmp => {
this.cmp = cmp;
$('#theModal').modal('show');
});
});
}
close() {
if(this.cmp) {
this.cmp.dispose();
}
this.cmp = null;
}
}
@Component({
selector: 'my-app',
template: `
<h1>My First Attribute Directive</h1>
<button (click)="showDialog()">show modal</button>
<br>
<br>`,
})
export class AppComponent {
constructor(private sharedService:SharedService) {}
showDialog() {
this.sharedService.showModal.next(CompComponent);
}
}
这篇关于如何动态创建引导模式作为 Angular2 组件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!