I'm using Angular 8.1.3 . This initial explanation is probably poor, but I hope the example will make it clear:
I'm trying to eliminate repetition in my code, by creating a new angular component. I want this component to place different types of content that is passed into it in different places, based on the type of content. I know I can do this with <ng-content> together with the select attribute. But, this following requirement is the cause of the question: I also want to wrap each content selector match with specific html.
For example, I want to turn this:
<table class="visualization-control">
<tr>
<td>
<app-input
unimportantAttributes1
></app-input>
</td>
<td>
<app-input unimportantAttributes2></app-input>
</td>
</tr>
<tr>
<td>
<app-button unimportantAttributes3</app-button >
</td>
<td>
<app-button unimportantAttributes4></app-button>
</td>
<td>
<app-button unimportantAttributes4</app-button>
</td>
</tr>
</table>
into this:
<app-visualization-control>
<app-input
unimportantAttributes1
></app-input>
<app-input unimportantAttributes2></app-input>
<app-button unimportantAttributes3</app-button >
<app-button unimportantAttributes4></app-button>
<app-button unimportantAttributes5</app-button>
<app-visualization-control>
Notice that there are two rows. The the first row has two data cells in it, each containing an input, and the second three data cells, each with a button in it. But on different occurrences of this structure, I need a different number of inputs and different number of buttons. Note that the components that are seen by app-visualization-control's parents should be the same instances that are seen by app-visualization-control itself, because of data binding. That is, I should not be instancing new components, e.g. with something like *ngComponentOutlet (to my understanding this directive cannot be used with passed-in component instances, it instances and destroys it's "own" components).
Below is my best attempt, but it didn't work: the content was not rendered, though no compilation or runtime errors were thrown upon visiting the page. Further, the correct number of <td> were rendered, but they were empty.
@Component({
selector: 'app-visualization-control',
template: `
<table>
<tr>
<td *ngFor="let inputTemplate of inputTemplates">
<ng-container *ngTemplateOutlet="inputTemplate"></ng-container>
</td>
</tr>
<tr>
<td *ngFor="let buttonTemplate of buttonTemplates">
<ng-container *ngTemplateOutlet="buttonTemplate"> </ng-container>
</td>
</tr>
</table>
`,
styleUrls: ['./visualization-control.component.scss']
})
export class VisualizationControlComponent {
@ContentChildren(InputComponent, { read: TemplateRef }) inputTemplates!: QueryList<TemplateRef<{}>>;
@ContentChildren(ButtonComponent, { read: TemplateRef }) buttonTemplates!: QueryList<TemplateRef<{}>>;
}
PS: the example has been greatly simplified. In fact, I'm not even using <table>, I'm using ionic framework's grid system, but these details don't matter.