【问题标题】:Get the ng-content of ng-template from a component into another component从一个组件中获取 ng-template 的 ng-content 到另一个组件中
【发布时间】:2020-08-14 02:39:42
【问题描述】:

我知道还有其他想法,但我想以下面定义的方式使用ng-templateng-content@ContenChild() 装饰器。 这种想法是通过看到角材料组件的实际实现而产生的。

在这里,我有两个组件:

  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);
    }
}


【问题讨论】:

  • app-container 中不使用可选ng-content 而不是ng-container[ngTemplateOutlet] 的任何具体原因?我认为它更直观……但当然也可以只是口味问题。

标签: angular ng-template ng-content


【解决方案1】:

我得到了解决方案!

其实,要获取任何组件的内容,我们都可以使用@ViewChild()装饰器。 因此,对于app-navapp-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>

【讨论】:

    【解决方案2】:

    Stackblitz demo

    我认为不使用ngTemplateOutlet 会获得更简洁的结构。 IMO,您甚至不需要任何 ng-template 元素。当然,我不知道你的最终目标,但你可以做我在下面展示的,这与你所拥有的非常相似,但我认为app-container 中的可选ng-content 使整体结构更加直观和不过更容易理解组件的树设置:

    @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>
    

    【讨论】:

      猜你喜欢
      • 2019-08-23
      • 1970-01-01
      • 2017-10-15
      • 1970-01-01
      • 1970-01-01
      • 2020-12-28
      • 1970-01-01
      • 2023-03-05
      • 1970-01-01
      相关资源
      最近更新 更多