angularng-templateng-content

Access child component variables within ng-container


I have a custom component called Suggestion List, which displays a list of Suggestions to the user from an observable. I have created this component as generic as possible so you can pass any array of data, so I'd like to be able to customize the display of it from the parent as I'll never know for certain what the objects will look like until implementing it. Unfortunaly I can't access the child components variables from the parent in ng-container.

Is this possible with ng-container or ng-template or should I be taking another route altogether?

Parent Component

    <suggestion-list (suggestionSelected)="selectSuggestion($event)" [$suggestions]="$suggestionSource">
      <ng-container>
        {{suggestion.firstname + ' ' + suggestion.lastname}}
      <ng-container>
    </suggestion-list>

Child Component

  <mat-list role="list">
    <mat-list-item *ngFor="let suggestion of $suggestions | async">
      <mat-icon mat-list-icon>person</mat-icon>
      <mat-card (click)="selectSuggestion(suggestion)">
        <ng-container></ng-container>
      </mat-card>
    </mat-list-item>
  </mat-list>

Solution

  • One approach would be to use ng-template. You can define a template for each element in the parent component and display the template in the child component for each element in the array:

    Parent component:

    <suggestion-list (suggestionSelected)="selectSuggestion($event)" 
                     [suggestions]="$suggestionSource | async" 
                     [suggestionTemplate]="suggestionTemplate">
    </suggestion-list>
    
    <ng-template #suggestionTemplate let-suggestion>
    <span>{{suggestion.firstname + ' ' + suggestion.lastname}}</span>
    </ng-template>
    

    And in your child component you could just do (notice that we pass the suggestion var in the template through the implicit context of the ng-template:

    <ng-container *ngFor="let suggestion of suggestions>
        <ng-container *ngTemplateOutlet="suggestionTemplate; context: {$implicit: suggestion}"></ng-container>
    </ng-container>
    

    In the .ts file of the child component, you declare the template passed in like:

    @Input() suggestionTemplate: TemplateRef<any>;
    

    PS: I've written this code right now, so it's not tested, but I think you can get an idea of what you can do!