0

At the moment I have a Container Component which has a list of dynamic components. Each dynamic component has a @Input() config property. And the Container will process an array with a switch that looks maybe similar to this for a TextComponent

switch (config.selector) {
    case ComponentTypes.TEXT:
         const componentFactory = this.componentFactoryResolver.resolveComponentFactory(TextContentComponent);
         const componentReference = viewContainerRef.createComponent(componentFactory);
         const component = componentReference.instance;
         component.config = config;
         component.detectChanges();
         return componentReference;
    break;
}

When I was looking for how to put my Container into a MatDialog, I found this excellent answer on stack overflow

To dig into that answer a little:

This method is taking a component someComponent. (Which could be my Container). But the second argument seems to be like my config.

this.dialogRef = this.dialog.open(someComponent, {
  width: 330px,
  height: 400px,
  data: {
    dataKey: yourData
  }
});

Where this is interesting though is in someComponent.

import {MAT_DIALOG_DATA} from '@angular/material';
import { Inject } from '@angular/core';


constructor(
   @Inject(MAT_DIALOG_DATA) public data: any
) { }

ngOnInit() {
  // will log the entire data object
  console.log(this.data)
}

Questions

  1. What is going on there? It seems an unlisted way of creating dynamic components which seems less hassle that the method I am using.
  2. I expected an @Input property but here they chose to Inject a token. This is almost like new Container(config) but undocumented. Why did they not consider data an @input?
  3. Should I make a dynamic.create(TextComponent, config) replacement service for my long winded Container switch approach?

PS: The reason I am asking is because @Input and ngOnChanges that doesn't work with dynamic components can be a pain compared to knowing that the data was there as part of instantiation.

user1059939
  • 1,613
  • 2
  • 20
  • 37

1 Answers1

0

You needn't a @Input, when you write

const dialogRef = this.dialog.open(DialogOverviewExampleDialog, {
  width: '250px',
  data: {name: this.name, animal: this.animal}
});
//You can use dialogRef.componentInstance to "get" the component
//e.g. if you has a variable in your Component: "anotherVariable"
dialogRef.componentInstance.anotherVariable="hello word"

Injecting data, you can give value to "data" when open the dialog

Eliseo
  • 50,109
  • 4
  • 29
  • 67
  • The key though is how the `data` property becomes an Injectable Token in the implementation of DialogOverviewExampleDialog and is available through the constructor? Every other dynamic component resource would insist that you need to use `@input`. Having the data provided as an injectable in the constructor seems far superior to the hacky `detectChanges()` stuff that is recommended. – user1059939 Apr 16 '19 at 10:55