我知道还有其他想法,但我想以下面定义的方式使用ng-template
、ng-content
和@ContenChild()
装饰器。这种想法是通过观察有角度的材料组件的实际实现而产生的。
这里,我有两个组件:
- 容器组件(应用程序容器(
- 子组件(应用程序子组件(
我想直接在应用容器中显示应用子组件的内容。
我在这里得到了一些相关的解决方案: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);
}
}
Stacklitz演示
我认为不使用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>
我得到了解决方案!!
实际上,为了获得任何组件的内容,我们可以使用@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>