1
votes

I would like to load the content of my page dynamically depending on the active navigation point.

export class Sub_navigation_item {
    constructor(
      public title: string,
      public templateName: string
    ) {}
  }

I therefore have a navigation item with the ID from an ng-template. I would like to pass the content to a child component based on this ID.

These are my navigation items:

this.navbarItems = [
        new Sub_navigation_item('General', 'generalTemplate'),
        new Sub_navigation_item('Actions', 'actionTemplate'),
        new Sub_navigation_item('Inactivity', 'inactivityTemplate')
];

Here is my template for the general page:

<ng-template #generalTemplate>
    <div class="generalContent">
        <div>
         hello world
       </div>
  </ng-template>

And here is my child component:

HTML:

<div class="container">
    <div class="row">
        <div class="col col-lg-8">
            <h1>{{title}}</h1>
        </div>
    </div>
</div>

<ng-container [ngTemplateOutlet]="content"></ng-container>

TS:

import { Sub_navigation_item } from './../../../../models/sub_navigation_item';
import {
    Component,
    OnInit,
    Input,
    TemplateRef
  } from '@angular/core';

  import { RestApiService } from './../../../../services/api/rest-api.service';
  import { Actionevent_Type } from 'src/app/models/actionEvent';

  @Component({
    // tslint:disable-next-line:component-selector
    selector: 'bot-detail-page',
    templateUrl: './bot-detail-page.component.html',
    styleUrls: ['./bot-detail-page.component.scss']
  })
  export class BotDetailPageComponent implements OnInit {

    @Input() title: string;
    @Input() content: TemplateRef<any>;

    constructor(private restApiService: RestApiService) {
    }

ngOnInit() {
}

}

I am trying to create the content via ngFor:

<bot-detail-page [title]="navbarItem.title" [content]="navbarItem.templateName"> 
            
</bot-detail-page>

If i pass 'generalTemplate'to the [content] it works but navbarItem.templateName doesnt work.

2
you seem to be instantiating your navigation items with strings only (new Sub_navigation_item('Actions', 'actionTemplate'),), shouldn't the second argument be a variable holding the template? - D Pro
it was an error. I fixed it. - Torben G
Sub_navigation_item.templateName is string, and BotDetailPageComponent.content expects a TemplateRef, that must be the issue - D Pro

2 Answers

1
votes

In parent component you need to have all the templates in .html. Then in the parent component's class you need to get references to all these templates, one of the options is to select them via ViewChild property decorator. And then you can pass these templates into child component's content input.

in parent component's class:

export class ParentComponent {    
  @ViewChild('generalTemplate') gt: TemplateRef<any>;
  @ViewChild('actionTemplate') at: TemplateRef<any>;
}

you can introduce any intermediate logic to select target template (here we just pass directly gt):

<bot-detail-page [title]="navbarItem.title" [content]="gt">
0
votes

As @D Pro mentioned in the comment ngTemplateOutlet expects template reference instead of string. I would sugggest you to create directive to get TemplateRef of element somethink like this:

sub-navigation.directive.ts

import { Directive,Input,TemplateRef } from '@angular/core';

@Directive({
  selector: '[appSubNavigation]'
})
export class SubNavigationDirective {
  @Input() public title:string;
  constructor(public template: TemplateRef<any>) { }

}

Then in parent component html place directive on the ng-template

<ng-template appSubNavigation title="General">
    <div class="generalContent">
        <div>
         hello world
       </div>
    </div>
  </ng-template>

<app-bot-details *ngIf="navbarItem?.length"

[title]="navbarItem[0].title" [content]="navbarItem[0].template"
> 
</app-bot-details>

In component ts use ViewChildren to get all the defined templateRef

@ViewChildren(SubNavigationDirective)  set subNavigation(ref:QueryList<SubNavigationDirective>){
    this.navbarItem = ref.toArray();
  }; 

Working Example