如何使用angular4中的动态内容加载器在同一视图中动态加载两个或多个相同或不同的组件

时间:2017-11-01 13:19:25

标签: angular

我使用dynamic component loader动态加载model.component.ts上的组件。这适用于单个组件加载,但没有查看加载两个相同或不同的组件。 如何使用dynamic component loader加载两个相同或不同的组件? 注意:我已经明确标出了代码中的问题所在?

service.ts

import { Injectable } from '@angular/core';
import { Http, Response, RequestOptions, Headers } from 
'@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
@Injectable()
export class DataOrMethodCallService {

  constructor(private http: Http) {
  }
  jsondta(): Observable<any> {
    console.log('Retriving Data from File.......');
    return this.http.get('assets/json/abcd/abc.json')
      .map(this.extractData)
      .catch(this.handleError);
  }


  private extractData(res: Response) {
    const body = res.json();
    return body || [];
  }

  private handleError(error: any) {
    const errMsg = (error.message) ? error.message :
      error.status ? `${error.status} - ${error.statusText}` : 'Server error';
    console.error(errMsg);
    alert('Server Error!');
    return Observable.throw(errMsg);
  }
}

然后,我使用动态组件加载器动态加载组件。

modal.component.ts

  componentData = [];

  ngOnInit() {
    this.jsonDataService.jsondta().subscribe(
      data => this.jsdata = data
    );
  }
  //after a click event in some other component below method is called
  showDialog(){
for(let i=0; i<2;i++){   //calling component two times to create components twice.
      this.displayshiftChartComponent(this.jsdata);
}
    }

  displayshiftChartComponent(jsdata) {
    this.componentData[index] = {
      component: CustomShiftChartComponent,
      inputs: {
       shiftData: [
          {
            shiftdata: this.jsdata     
          }
        ]
      }
    };
  }

modal.component.html

<!-- here loading components dynamically.
     Need to load two or more same components
       or different components here. -->
<!-- need to do something here -->

<div class="col-xs-6">
     <!-- first component load here -->
     <app-dynamic-content-loader [componentData]="componentData[0]">
     </app-dynamic-content-loader>
</div>
<div class="col-xs-6">
     <!-- second component should load here -->
     <app-dynamic-content-loader [componentData]="componentData[1]">
     </app-dynamic-content-loader>
</div>

shift.component.ts

export class CustomShiftChartComponent implements OnInit, AfterContentInit, AfterContentChecked {
 constructor(el: ElementRef, public injector: Injector) {
    this.el = el;
    try {
      this.shiftdata = this.injector.get('shiftData')[0].shiftdata;
      this.gridStatus = true;
    } catch (e) {
      console.log('Error Occured :: ' + e.status);
    }
    if (this.gridStatus === true) {
      alert(this.gridStatus);
      this.shiftdata = this.shiftdata;
      console.log(this.shiftdata);
    }

  ngAfterContentInit() {

  }

}

Dynamic.content-loader.ts

 import { Component, OnInit, ComponentFactoryResolver, 
    ReflectiveInjector, ViewContainerRef, ViewChild, Input } from 
    '@angular/core';
    import { CustomShiftChartComponent } from '../components/------';
    import { hellotComponent } from '../hello/-------';

    @Component({
      selector: 'app-dynamic-content-loader',
      templateUrl: './dynamic-content-loader.component.html',
      styleUrls: ['./dynamic-content-loader.component.css'],
      entryComponents: [CustomShiftChartComponent,hellotComponent]
    })
    export class DynamicContentLoaderComponent implements OnInit {
      currentComponent = null;
      @ViewChild('dynamicComponentContainer', { read: ViewContainerRef }) dynamicComponentContainer: ViewContainerRef;

      ngOnInit(): void {
      }



      // component: Class for the component you want to create
      // inputs: An object with key/value pairs mapped to input name/input value
      @Input() set componentData(data: { component: any, inputs: any }) {
        // console.log("Component Data :: "+JSON.stringify(data));
        if (!data) {
          return;
        }
        // Inputs need to be in the following format to be resolved properly
        let inputProviders = Object.keys(data.inputs).map((inputName) => ({ provide: inputName, useValue: data.inputs[inputName] }));
        const resolvedInputs = ReflectiveInjector.resolve(inputProviders);

        // We create an injector out of the data we want to pass down and this components injector
        const injector = ReflectiveInjector.fromResolvedProviders(resolvedInputs, this.dynamicComponentContainer.parentInjector);

        // We create a factory out of the component we want to create
        const factory = this.resolver.resolveComponentFactory(data.component);

        // We create the component using the factory and the injector
        const component = factory.create(injector);

        // We insert the component into the dom container
        this.dynamicComponentContainer.insert(component.hostView);

        // We can destroy the old component is we like by calling destroy
        if (this.currentComponent) {
          this.currentComponent.destroy();
        }

        this.currentComponent = component;
      }

      constructor(private resolver: ComponentFactoryResolver) {

      }

    }

1 个答案:

答案 0 :(得分:0)

添加组件:

addComponent(){
  // check and resolve the component
  var comp = this._cfr.resolveComponentFactory(YourComponent);
  // Create component inside container
  var forFurtheruse = this.container.createComponent(comp);      
}

See the rest of detail有工作的plunker示例