Получить ng-содержимое ng-template из компонента в другой компонент - PullRequest
1 голос
/ 29 апреля 2020

Я знаю, что есть и другие идеи, но я хочу использовать декоратор ng-template, ng-content и @ContenChild() нижеуказанным образом. Идея этого пришла, увидев фактическую реализацию angular компонентов материала.

Здесь у меня есть два компонента:

  1. Контейнерный компонент (app-container)
  2. Дочерний компонент (app-child)

Я хочу получить содержимое компонента app-child, непосредственно показанное в app-container.

У меня есть несколько связанных решений: https://stackblitz.com/edit/ngtemplateoutlet-and-content-projection?file=src%2Fapp%2Fapp.component.html. Но это не совсем соответствует моему требованию.

Желательно следовать html, в основном в app.component.html:

<app-container>
   <app-nav>
       <a routerLink="/home">Home</a>
       <a routerLink="/about">About</a>
   </app-nav>
  <app-main>
    <p>This is the content to be reflect.</p>
  </app-main>
</app-container>

, который должен выдавать результат, подобный этому:

<div class="container">
        <nav role="navigation" class="navigation">
             <a routerLink="/home">Home</a>
             <a routerLink="/about">About</a>
        </nav>
        <section role="main" class="main__content">
               <p>This is the content to be reflect.</p>
        </section>
</div>

Мои коды выглядят так

import { Component, ContentChild, AfterContentInit } from '@angular/core';

@Component({
    selector: 'app-main'
    template: `<ng-template><ng-content></ng-content></ng-template>`
})
export class AppMain {

}
@Component({
    selector: 'app-nav'
    template: `<ng-template><ng-content></ng-content></ng-template>`
})
export class AppNav {

}


@Component({
    selector: 'app-container',
    template: `
               <div class="container">
                      <nav role="navigation" class="navigation">
                         <ng-container [ngTemplateOutlet="nav"></ng-container>
                      </nav>
                      <section role="main" class="main__content">
                         <ng-container [ngTemplateOutlet]="main"></ng-container>
                      </section>
               </div>
              `
})
export class AppContainer implements AfterContentInit {
    @ContentChild(AppMain) main: AppMain;
    @ContentChild(AppNav) nav: AppNav;

    ngAfterContentInit() {       
        console.log(this.main);
        console.log(this.nav);
    }
}


Ответы [ 2 ]

0 голосов
/ 30 апреля 2020

Я получил решение !!

На самом деле, чтобы получить содержимое любого компонента, мы можем использовать @ViewChild() декоратор. Итак, для компонентов app-nav и app-main я использовал одну и ту же технику, как показано ниже:

import { Component, ContentChild, AfterContentInit, TemplateRef, ViewChild } from '@angular/core';
@Component({
    selector: 'app-main',
    template: `<ng-template><ng-content></ng-content></ng-template>`
})
export class AppMain{
    @ViewChild(TemplateRef, { static: true }) content: TemplateRef<any>;
}
@Component({
    selector: 'app-nav',
    template: `<ng-template><ng-content></ng-content></ng-template>`
})
export class AppNar {
    @ViewChild(TemplateRef, { static: true }) content: TemplateRef<any>;

}


@Component({
    selector: 'app-container',
    template: `
               <div class="container">
                      <nav role="navigation" class="navigation">
                         <ng-container [ngTemplateOutlet="nav.content"></ng-container>
                      </nav>
                      <section role="main" class="main__content">
                         <ng-container [ngTemplateOutlet]="main.content"></ng-container>
                      </section>
               </div>
              `
})
export class AppContainer implements AfterContentInit {

    @ContentChild(AppMain) main: AppMain;
    @ContentChild(AppNav) nav!: AppNav;

    ngAfterContentInit() {

    }

}

Итак, в app.component.html у меня было:

<app-container>
   <app-nav>
       <a routerLink="/home">Home</a>
       <a routerLink="/about">About</a>
   </app-nav>
  <app-main>
    <p>This is the content to be reflect.</p>
  </app-main>
</app-container>

И вывод, который я получил на самом деле желаемый:

<div class="container">
        <nav role="navigation" class="navigation">
             <a routerLink="/home">Home</a>
             <a routerLink="/about">About</a>
        </nav>
        <section role="main" class="main__content">
               <p>This is the content to be reflect.</p>
        </section>
</div>
0 голосов
/ 30 апреля 2020

Демонстрация Stackblitz

Я думаю, что вы получите более чистую структуру, не используя ngTemplateOutlet. ИМО, вам даже не нужен элемент ng-template. Конечно, я не знаю вашей конечной цели, но вы могли бы сделать то, что я покажу ниже, что очень похоже на то, что у вас есть, но я думаю, что выбор ng-content в app-container делает общую структуру более интуитивной и проще понять настройку дерева компонента, хотя:

@Component({
  selector: "app-main",
  template: `<ng-content></ng-content>`
})

export class AppMain {}
@Component({
  selector: "app-nav",
  template: `<ng-content></ng-content>`
})
export class AppNav {}

@Component({
  selector: "app-container",
  template: `
    <div class="container">
      <nav role="navigation" class="navigation">
        <ng-content select="[nav-slot]"></ng-content>
      </nav>
      <section role="main" class="main__content">
        <ng-content select="[main-slot]"></ng-content>
      </section>
    </div>
  `
})
export class AppContainer {
  @ContentChild(AppMain) main: AppMain;
  @ContentChild(AppNav) nav: AppNav;

  ngAfterContentInit() { /* ... */}
}

И вы можете использовать его так:

<app-container>
    <app-nav nav-slot>
        <a routerLink="/home">Home</a>
        <a routerLink="/about">About</a>
    </app-nav>
    <app-main main-slot>
        <p>This is the content to be reflect.</p>
    </app-main>
</app-container>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...