Angular 4+ назначить @Input для динамически созданного компонента ngComponentOutlet

В Angular 4 для динамического создания компонента вы можете использовать директиву ngComponentOutlet: https://angular.io/docs/ts/latest/api/common/index/NgComponentOutlet-directive.html

что-то вроде этого:

Динамический компонент

@Component({
  selector: 'dynamic-component',
  template: `
     Dynamic component
  `
})
export class DynamicComponent {
  @Input() info: any;
}

Приложение

@Component({
  selector: 'my-app',
  template: `
     App<br>
     <ng-container *ngComponentOutlet="component"></ng-container>
  `
})
export class AppComponent {
  this.component=DynamicComponent;
}

Как передать информацию @Input() info: any; в этом шаблоне <ng-container *ngComponentOutlet="component"></ng-container>?

Ответ 1

Такая особенность обсуждалась в запросе на растяжение для ngComponentOutlet, но на данный момент была удалена. Даже componentRef, показанный в настоящее время в https://angular.io/docs/ts/latest/api/common/index/NgComponentOutlet-directive.html, не является общедоступным и, следовательно, недоступен https://github.com/angular/angular/blob/3ef73c2b1945340ca6bd21f1790260c88698ae26/modules/%40angular/common/src/directives/ng_component_outlet.ts#L78

Я предлагаю вам создать свою собственную директиву, полученную из https://github.com/angular/angular/blob/3ef73c2b1945340ca6bd21f1790260c88698ae26/modules/%40angular/common/src/directives/ng_component_outlet.ts#L72

и присвойте значения входам, как показано в Angular 2 динамических вкладках с выбранными вами компонентами с кликом

this.compRef.instance.someProperty = 'someValue';

Ответ 2

С помощью поста @Günter Zöchbauer я решил подобную проблему таким образом - надеюсь, вы сможете каким-то образом ее адаптировать.

Сначала я определил некоторые интерфейсы:

// all dynamically loaded components should implement this guy
export interface IDynamicComponent { Context: object; }

// data from parent to dynLoadedComponent
export interface IDynamicComponentData {
  component: any;
  context?: object;
  caller?: any;
}

то я реализовал их внутри динамически загружаемого компонента

dynamicLoadedComponentA.ts

// ...
export class DynamicLoadedComponentA implements IDynamicComponent {
// ...

// data from parent
public Context: object;

// ...

После этого я построил новый компонент, который отвечает за магию. Важно здесь, что мне пришлось регистрировать все дины. загруженных компонентов как entryComponents.

dynamic.component.ts

@Component({
  selector: 'ngc-dynamic-component',
  template: ´<ng-template #dynamicContainer></ng-template>´,
  entryComponents: [ DynamicLoadedComponentA ]
})
export class DynamicComponent implements OnInit, OnDestroy, OnChanges {
  @ViewChild('dynamicContainer', { read: ViewContainerRef }) public dynamicContainer: ViewContainerRef;

  @Input() public componentData: IDynamicComponentData;

  private componentRef: ComponentRef<any>;
  private componentInstance: IDynamicComponent;

  constructor(private resolver: ComponentFactoryResolver) { }

  public ngOnInit() {
    this.createComponent();
  }

  public ngOnChanges(changes: SimpleChanges) {
    if (changes['componentData']) {
      this.createComponent();
    }
  }

  public ngOnDestroy() {
    if (this.componentInstance) {
      this.componentInstance = null;
    }
    if (this.componentRef) {
      this.componentRef.destroy();
    }
  }

  private createComponent() {
    this.dynamicContainer.clear();
    if (this.componentData && this.componentData.component) {
      const factory: ComponentFactory<any> = this.resolver.resolveComponentFactory(this.componentData.component);
      this.componentRef = this.dynamicContainer.createComponent(factory);
      this.componentInstance = this.componentRef.instance as IDynamicComponent;

      // fill context data
      Object.assign(this.componentInstance.Context, this.componentData.context || {});

      // register output events
      // this.componentRef.instance.outputTrigger.subscribe(event => console.log(event));
    }
  }
}

здесь использование этого блестящего нового материала:

app.html

<!-- [...] -->
<div>
  <ngc-dynamic-component [componentData]="_settingsData"></ngc-dynamic-component>
</div>
<!-- [...] -->

app.ts

// ...
  private _settingsData: IDynamicComponent = {
    component: DynamicLoadedComponentA,
    context: { SomeValue: 42 },
    caller: this
  };
// ...