AngularでNgTemplateOutletを使用して再利用可能なコンポーネントを作成する方法
序章
単一責任の原則は、アプリケーションの一部に1つの目的があるべきであるという考えです。 この原則に従うと、Angularアプリのテストと開発が簡単になります。
Angularでは、 NgTemplateOutlet
特定のコンポーネントを作成する代わりに、コンポーネント自体を変更することなく、さまざまなユースケースに合わせてコンポーネントを簡単に変更できます。
この記事では、既存のコンポーネントを使用するように書き直します NgTemplateOutlet
.
前提条件
このチュートリアルを完了するには、次のものが必要です。
- Node.jsはローカルにインストールされます。これは、Node.jsのインストール方法とローカル開発環境の作成に従って実行できます。
- Angularプロジェクトのセットアップにある程度精通している。
このチュートリアルは、Nodev16.6.2で検証されました。 npm
v7.20.6、および @angular/core
v12.2.0。
ステップ1-構築 CardOrListViewComponent
検討 CardOrListViewComponent
表示されます items
で 'card'
または 'list'
そのに応じてフォーマット mode
.
それはで構成されています card-or-list-view.component.ts
ファイル:
import {
Component,
Input
} from '@angular/core';
@Component({
selector: 'card-or-list-view',
templateUrl: './card-or-list-view.component.html'
})
export class CardOrListViewComponent {
@Input() items: {
header: string,
content: string
}[] = [];
@Input() mode: string = 'card';
}
そして、 card-or-list-view.component.html
テンプレート:
<ng-container [ngSwitch]="mode">
<ng-container *ngSwitchCase="'card'">
<div *ngFor="let item of items">
<h1>{{item.header}}</h1>
<p>{{item.content}}</p>
</div>
</ng-container>
<ul *ngSwitchCase="'list'">
<li *ngFor="let item of items">
{{item.header}}: {{item.content}}
</li>
</ul>
</ng-container>
このコンポーネントの使用例を次に示します。
import { Component } from '@angular/core';
@Component({
template: `
<card-or-list-view
[items]="items"
[mode]="mode">
</card-or-list-view>
`
})
export class UsageExample {
mode = 'list';
items = [
{
header: 'Creating Reuseable Components with NgTemplateOutlet in Angular',
content: 'The single responsibility principle...'
} // ... more items
];
}
このコンポーネントには単一の責任はなく、柔軟性もあまりありません。 それはその追跡する必要があります mode
表示する方法を知っています items
両者に card
と list
見る。 そしてそれは表示することができるだけです items
とともに header
と content
.
テンプレートを使用してコンポーネントを個別のビューに分割することにより、これを変更しましょう。
ステップ2–理解する ng-template
と NgTemplateOutlet
許可するために CardOrListViewComponent
あらゆる種類の表示 items
それらを表示する方法を教えることができる必要があります。 これは、スタンプを押すために使用できるテンプレートを与えることで実現できます。 items
.
テンプレートは次のようになります TemplateRefs
を使用して <ng-template>
スタンプは EmbeddedViewRefs
から作成された TemplateRefs
. EmbeddedViewRefs
独自のコンテキストでAngularのビューを表し、最小の必須ビルディングブロックです。
Angularは、テンプレートからビューをスタンプアウトするというこの概念を使用する方法を提供します。 NgTemplateOutlet
.
NgTemplateOutlet
を取るディレクティブです TemplateRef
とコンテキストとスタンプアウト EmbeddedViewRef
提供されたコンテキストで。 コンテキストは、テンプレートで次の方法でアクセスされます let-{{templateVariableName}}="contextProperty"
テンプレートが使用できる変数を作成するための属性。 コンテキストプロパティ名が指定されていない場合は、 $implicit
財産。
次に例を示します。
import { Component } from '@angular/core';
@Component({
template: `
<ng-container *ngTemplateOutlet="templateRef; context: exampleContext"></ng-container>
<ng-template #templateRef let-default let-other="aContextProperty">
<div>
$implicit = '{{default}}'
aContextProperty = '{{other}}'
</div>
</ng-template>
`
})
export class NgTemplateOutletExample {
exampleContext = {
$implicit: 'default context property when none specified',
aContextProperty: 'a context property'
};
}
例からの出力は次のとおりです。
<div>
$implicit = 'default context property when none specified'
aContextProperty = 'a context property'
</div>
The default
と other
変数はによって提供されます let-default
と let-other="aContextProperty"
小道具。
ステップ3–リファクタリング CardOrListViewComponent
に柔軟性を提供するため CardOrListViewComponent
あらゆるタイプの表示を許可します items
、テンプレートとして読み込む2つの構造ディレクティブを作成します。 これらのテンプレートは、カードとリストアイテムになります。
ここは card-item.directive.ts
:
import { Directive } from '@angular/core';
@Directive({
selector: '[cardItem]'
})
export class CardItemDirective {
constructor() { }
}
そしてここに list-item.directive.ts
:
import { Directive } from '@angular/core';
@Directive({
selector: '[listItem]'
})
export class ListItemDirective {
constructor() { }
}
CardOrListViewComponent
インポートします CardItemDirective
と ListItemDirective
:
import {
Component,
ContentChild,
Input,
TemplateRef
} from '@angular/core';
import { CardItemDirective } from './card-item.directive';
import { ListItemDirective } from './list-item.directive';
@Component({
selector: 'card-or-list-view',
templateUrl: './card-or-list-view.component.html'
})
export class CardOrListViewComponent {
@Input() items: {
header: string,
content: string
}[] = [];
@Input() mode: string = 'card';
@ContentChild(CardItemDirective, {read: TemplateRef}) cardItemTemplate: any;
@ContentChild(ListItemDirective, {read: TemplateRef}) listItemTemplate: any;
}
このコードは、構造ディレクティブを次のように読み取ります。 TemplateRefs
.
<ng-container [ngSwitch]="mode">
<ng-container *ngSwitchCase="'card'">
<ng-container *ngFor="let item of items">
<ng-container *ngTemplateOutlet="cardItemTemplate"></ng-container>
</ng-container>
</ng-container>
<ul *ngSwitchCase="'list'">
<li *ngFor="let item of items">
<ng-container *ngTemplateOutlet="listItemTemplate"></ng-container>
</li>
</ul>
</ng-container>
このコンポーネントの使用例を次に示します。
import { Component } from '@angular/core';
@Component({
template: `
<card-or-list-view
[items]="items"
[mode]="mode">
<div *cardItem>
Static Card Template
</div>
<li *listItem>
Static List Template
</li>
</card-or-list-view>
`
})
export class UsageExample {
mode = 'list';
items = [
{
header: 'Creating Reuseable Components with NgTemplateOutlet in Angular',
content: 'The single responsibility principle...'
} // ... more items
];
}
これらの変更により、 CardOrListViewComponent
提供されたテンプレートに基づいて、カードまたはリストフォームに任意のタイプのアイテムを表示できるようになりました。 現在、テンプレートは静的です。
最後に行う必要があるのは、コンテキストを与えることでテンプレートを動的にすることです。
<ng-container [ngSwitch]="mode">
<ng-container *ngSwitchCase="'card'">
<ng-container *ngFor="let item of items">
<ng-container *ngTemplateOutlet="cardItemTemplate; context: {$implicit: item}"></ng-container>
</ng-container>
</ng-container>
<ul *ngSwitchCase="'list'">
<li *ngFor="let item of items">
<ng-container *ngTemplateOutlet="listItemTemplate; context: {$implicit: item}"></ng-container>
</li>
</ul>
</ng-container>
このコンポーネントの使用例を次に示します。
import { Component } from '@angular/core';
@Component({
template: `
<card-or-list-view
[items]="items"
[mode]="mode">
<div *cardItem="let item">
<h1>{{item.header}}</h1>
<p>{{item.content}}</p>
</div>
<li *listItem="let item">
{{item.header}}: {{item.content}}
</li>
</card-or-list-view>
`
})
export class UsageExample {
mode = 'list';
items = [
{
header: 'Creating Reuseable Components with NgTemplateOutlet in Angular',
content: 'The single responsibility principle...'
} // ... more items
];
}
注目すべき興味深い点は、構文糖衣にアスタリスクプレフィックスとmicrosyntaxを使用していることです。 それは次と同じです:
<ng-template cardItem let-item>
<div>
<h1>{{item.header}}</h1>
<p>{{item.content}}</p>
</div>
</ng-template>
以上です! 元の機能はありますが、テンプレートと CardOrListViewComponent
責任が少ない。 次のようなアイテムコンテキストにさらに追加できます first
また last
に似ている ngFor
または完全に異なるタイプを表示します items
.
結論
この記事では、既存のコンポーネントを取得して、使用するために書き直しました NgTemplateOutlet
.
Angularについて詳しく知りたい場合は、Angularトピックページで演習とプログラミングプロジェクトを確認してください。