0

I'm trying to create a "container" component in Angular which contains other components and formats them / orders them in a predefined way (like a dashboard).

I would like to pass the components to the container as an input array like this:

 <container
    [inputComponents] = "['MapComponent', 'EventsListComponent', 'FileListComponent']"
 >
 </container>

My "container" component should show the Map and the Lists like a Dashboard with special formatting and so on.

I did already lots of research but couldn't find a good solution for this. I don't think passing angular components via input parameter is a good solution?

I found this on Stack Overflow which is very similar to my problem: Angular: Pass Component to a Component

But I don't want to change any of the already existent components to extend an abstract widget component. Is this really the only way to realize this?

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
Manuela
  • 127
  • 1
  • 15
  • Your container component should have ng-content and then just pass those components as templates like: ``. https://medium.freecodecamp.org/everything-you-need-to-know-about-ng-template-ng-content-ng-container-and-ngtemplateoutlet-4b7b51223691 – Roberto Zvjerković May 06 '19 at 08:27
  • In this Tutorial you learn the basics of Angular https://angular.io/tutorial/toh-pt3. Also how to use components within a component – Ronald Haan May 06 '19 at 08:28
  • @ritaj Thanks for your help. But with your solution, I can only pass one single component to my containerComponent. I want to be able to pass multiple components though. – Manuela May 06 '19 at 09:44
  • @RonaldHaan Thanks for the tutorial. It's nice but not helping with finding the answer to my problem. – Manuela May 06 '19 at 09:45
  • You can pass multiple components like that – Roberto Zvjerković May 06 '19 at 10:04
  • @ritaj As far as I have seen, you can use it like that: `` and select it within the container component using `` and ``. But my container component does not know which components it will get. So this is not a solution for me. – Manuela May 06 '19 at 11:09

1 Answers1

0

check this example

item.component.ts

import { Component, OnInit, TemplateRef, ViewChild, ViewContainerRef, Input } from '@angular/core';

@Component({
  selector: 'app-item',
  templateUrl: './item.component.html',
  styleUrls: ['./item.component.css']
})
export class ItemComponent implements OnInit {
  
  @Input() order?: string;

  @ViewChild(TemplateRef, {static: true}) template: TemplateRef<any>;

  ngOnInit() {
  }

}

item.component.html

<ng-template>
 <p>
  item works!
 </p>
 <ng-content></ng-content>
 </ng-template>

item-list.component.ts

import { Component, OnInit, QueryList, ContentChildren, AfterContentInit } from '@angular/core';
import { ItemComponent } from '../item/item.component';

@Component({
  selector: 'app-item-list',
  templateUrl: './item-list.component.html',
  styleUrls: ['./item-list.component.css']
})
export class ItemListComponent implements OnInit, AfterContentInit {

  @ContentChildren(ItemComponent, {descendants: true}) 
  items?: QueryList<ItemComponent>;
  constructor() { }

  ngOnInit() {
  }
    
  ngAfterContentInit(): void {
      
  }

}

item-list.component.html

<p *ngFor="let item of items">
  {{item.order}}
  <ng-template [ngTemplateOutlet]="item.template"></ng-template>
</p>

finally: app.component.html

<app-item-list>
  <app-item  order="2">
    test2
  </app-item>
  <app-item order="1">
    test1
  </app-item>
</app-item-list> 

Complete Example