如何动态创建引导模式作为 Angular2 组件? [英] How to dynamically create bootstrap modals as Angular2 components?

查看:30
本文介绍了如何动态创建引导模式作为 Angular2 组件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

原标题:无法在 Angular 2 中初始化动态附加 (HTML) 组件

我创建了一个指令,在初始化时将模态附加到主体.当一个按钮(注入了指令)被点击时,这个模式会启动.但我希望这个模态的内容是另一个组件(实际上我希望模态是组件).好像不能初始化组件.

这是我所做的工作:

http://plnkr.co/edit/vEFCnVjGvMiJqb2Meprr?p=preview

我正在尝试让 my-comp 成为我组件的模板

 '

解决方案

2.0.0 最终版的更新

Plunker 示例 >= 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

Plunker example >= 2.0.0

@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 DynamicComponentLoader (deprecated) 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆