【问题标题】:How to dynamically create bootstrap modals as Angular2 components?如何动态创建引导模式作为 Angular2 组件?
【发布时间】:2016-08-02 16:16:08
【问题描述】:

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

我创建了一个指令,在初始化时将模式附加到正文。当单击按钮(其中注入了指令)时,此模式将启动。但是我希望这个模态的内容成为另一个组件(实际上我希望模态成为组件)。好像无法初始化组件。

这是我所做的一个小插曲:

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

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

 '<div class="modal-body" #theBody>' 
            + '<my-comp></my-comp>' + 
 '</div>

【问题讨论】:

    标签: angular


    【解决方案1】:

    2.0.0 最终版更新

    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;
      }
    }
    

    提示

    如果一个应用程序更改SharedService 中的状态或调用导致Observable 发出一个值的方法,并且订阅者位于与发射器不同的应用程序中,则订阅者中的代码将在@987654331 中执行发射器的@。

    因此,当订阅 SharedService 中的 observable 时,请使用

    class MyComponent {
      constructor(private zone:NgZone, private sharedService:SharedService) {
        private sharedService.subscribe(data => this.zone.run() => {
          // event handler code here
        });
      }
    }
    

    有关如何触发更改检测的更多详细信息,请参阅Triggering Angular2 change detection manually

    原创

    Angular 不会处理动态添加的 HTML,也不会导致组件或指令被实例化或添加。

    您不能使用 DynamicComponentLoader(已弃用)ViewContainerRef.createComponent() (Angular 2 dynamic tabs with user-click chosen components) 在 Angulars 根组件 (AppComponent) 之外添加组件。

    我想最好的方法是在 Angulars 根组件之外创建第二个组件,即在每个组件上调用 bootstrap() 并使用共享服务进行通信:

    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);
      }
    }
    

    【讨论】:

    • 如果您想在第一个实例中调用另一个模态,则会出现问题。它只是替换内容,而不是创建另一个模态实例。此处示例:plnkr.co/edit/5sjn25CV6QLbLIs2FcWp?p=preview
    • 呃,这些组件我看了好久
    • 是的,我知道,但我发现它可能非常有用,因为我陷入了类似的情况:动态创建模态并在其他模态实例中调用模态实例
    猜你喜欢
    • 1970-01-01
    • 2016-12-07
    • 1970-01-01
    • 2017-07-21
    • 1970-01-01
    • 2019-09-11
    • 2019-08-15
    • 2020-12-31
    • 2017-11-01
    相关资源
    最近更新 更多