Angular 2将数据从父组件传递到动态模态

时间:2016-12-22 15:15:29

标签: angular data-binding bootstrap-modal

我用过这个例子: How to dynamically create bootstrap modals as Angular2 components?
通过在更多组件之间共享的动态生成不同或相同的模态来开发自己的插件 不幸的是我遇到了一些困难,因为我不知道如何将数据从父组件传递给模态。 在我的plunk(https://plnkr.co/edit/RgI1e9PobC7FloLHpEFD?p=preview)中,要传递的数据称为“dataToPass”。 有什么想法吗?

在我的app.ts下面:

//our root app component
import {
  NgModule, 
  ComponentRef, 
  Injectable, 
  Component, 
  Injector, 
  ViewContainerRef, 
  ViewChild, ComponentFactoryResolver} from "@angular/core";
import {BrowserModule} from '@angular/platform-browser'
import {Subject} from 'rxjs/Subject';

@Injectable()
export class SharedService {
  showModal:Subject<any> = new Subject();
}

@Component({
  selector: 'comp-comp',
  template: `MyComponent`
})
export class CompComponent { }

@Component({
  selector: 'child-component',
  template: `
      <button (click)="showDialog()">show modal from child</button>
  `,
})
export class ChildComponent {
  constructor(private sharedService:SharedService) {}

  showDialog() {
    this.sharedService.showModal.next(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 {
  @ViewChild('theBody', {read: ViewContainerRef}) theBody;

  cmp:ComponentRef;

  constructor(
    sharedService:SharedService, 
    private componentFactoryResolver: ComponentFactoryResolver, 
    injector: Injector) {

    sharedService.showModal.subscribe(type => {
      if(this.cmpRef) {
        this.cmpRef.destroy();
      }
      let factory = this.componentFactoryResolver.resolveComponentFactory(type);
      this.cmpRef = this.theBody.createComponent(factory);
      $('#theModal').modal('show');
    });
  }

  close() {
    if(this.cmpRef) {
      this.cmpRef.destroy();
    }
    this.cmpRef = null;
  }
}

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2>Hello</h2>
      <button (click)="showDialog()">show modal</button>
      <child-component></child-component>
    </div>
  `,
})
export class App {

  private dataToPass: string;
  constructor(private sharedService:SharedService) {
    this.dataToPass = 'data to pass';
  }

  showDialog() {
    this.sharedService.showModal.next(CompComponent);
  }

}

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ App, ModalComponent, CompComponent, ChildComponent],
  providers: [SharedService],
  entryComponents: [CompComponent],
  bootstrap: [ App, ModalComponent ]
})
export class AppModule{}

提前多多感谢。

1 个答案:

答案 0 :(得分:0)

如果有人感兴趣,我就能找到解决方案。

我将我需要的数据作为next函数的参数传递,因为Subject可用于向其订阅者发送值:

showDialog() {
    this.sharedService.showModal.next({'type': CompComponent, 'title': 'titolo1', 'dataToPass': 'dataToPass'});
  }

然后我将数据传递给CompComponent函数内的subscribe(遵循此示例:Angular 2 Passing data to component when dynamically adding the component),这样:

  let factory = this.componentFactoryResolver.resolveComponentFactory(data.type);
  this.cmpRef = this.theBody.createComponent(factory);
  this.cmpRef.instance.dataToPass = data.dataToPass;

在下面的整个代码中,您也可以在plunker上看到here

//our root app component
import {
  NgModule, 
  ComponentRef, 
  Injectable, 
  Component, 
  Injector, 
  ViewContainerRef, 
  ViewChild, ComponentFactoryResolver} from "@angular/core";
import {BrowserModule} from '@angular/platform-browser'
import {Subject} from 'rxjs/Subject';

@Injectable()
export class SharedService {
  showModal:Subject<any> = new Subject();
}

@Component({
  selector: 'comp-comp',
  template: `MyComponent {{dataToPass}}`
})
export class CompComponent { }

@Component({
  selector: 'child-component',
  template: `
      <button (click)="showDialog()">show modal from child</button>
  `,
})
export class ChildComponent {
  constructor(private sharedService:SharedService) {}

  showDialog() {
    this.sharedService.showModal.next({'type': CompComponent, 'title': 'titolo2', 'dataToPass': 'dataToPass'});
  }

}

@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">{{theHeader}}</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 {
  @ViewChild('theBody', {read: ViewContainerRef}) theBody;

  theHeader: string = '';
  cmpRefBody:ComponentRef<any>;

  constructor(
    sharedService:SharedService, 
    private componentFactoryResolver: ComponentFactoryResolver, 
    injector: Injector) {

    sharedService.showModal.subscribe(data => {
      if(this.cmpRef) {
        this.cmpRef.destroy();
      }
      let factory = this.componentFactoryResolver.resolveComponentFactory(data.type);
      this.cmpRef = this.theBody.createComponent(factory);
      this.cmpRef.instance.dataToPass = data.dataToPass;
      this.theHeader = data.title;
      console.log(data.title);
      console.log(data.dataToPass);
      $('#theModal').modal('show');
    });
  }

  close() {
    if(this.cmpRef) {
      this.cmpRef.destroy();
    }
    this.cmpRef = null;
  }
}

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2>Hello</h2>
      <button (click)="showDialog()">show modal</button>
      <child-component></child-component>
    </div>
  `,
})
export class App {

  constructor(private sharedService:SharedService) {}

  showDialog() {
    this.sharedService.showModal.next({'type': CompComponent, 'title': 'titolo1', 'dataToPass': 'dataToPass'});
  }

}

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ App, ModalComponent, CompComponent, ChildComponent],
  providers: [SharedService],
  entryComponents: [CompComponent],
  bootstrap: [ App, ModalComponent ]
})
export class AppModule{}