- Angular
Angular ng-contentの使い方|selectと投影の基本
ng-content とは、コンポーネントのテンプレートの中に「利用する側が渡した中身を差し込む場所」を作るための要素です。 利用する側がコンポーネントのタグの内側に書いた HTML が、ng-content の位置に表示されます。この仕組みをコンテンツ投影と呼びます。select 属性を付けると、タイトル用・本文用・ボタン用のように差し込み口(スロット)を複数に分けられます。
この記事では、カード・モーダル・一覧テーブルの3つの部品を実際に作り、描画後の HTML をそのまま掲載します。select による複数スロット、フォールバック、ngProjectAs、ngTemplateOutlet と context で行データを渡す書き方に加え、@if と組み合わせたときに投影されない場面を再現し、ng-template を使った直し方まで確かめました。
確認環境:Ubuntu 24.04 / Node.js 22.22.2 / Angular 21.2.25(@angular/cli 21.2.24、ng new の既定構成で zone.js なし)/ TypeScript 5.9.3 / Chromium 141(Playwright 1.56.0 で操作)。
ng-contentの早見表
| やりたいこと | 書き方(部品側) | 書き方(利用する側) |
|---|---|---|
| 中身を1か所に差し込む | <ng-content /> |
タグの内側に自由に書く |
| 差し込み口を分ける | <ng-content select="[card-title]" /> |
<h2 card-title>...</h2> |
| タグ名で振り分ける | <ng-content select="h2" /> |
<h2>...</h2> |
| クラスで振り分ける | <ng-content select=".note" /> |
<p class="note">...</p> |
| 渡されなかったときの既定の表示 | <ng-content>既定の内容</ng-content> |
何も書かない |
| 複数の要素をまとめて1つのスロットへ | select はそのまま | <ng-container ngProjectAs="[card-title]">...</ng-container> |
| 条件つきで表示する・遅れて生成する | ng-template を contentChild で受け取り ngTemplateOutlet で描画 |
<ng-template #body>...</ng-template> |
| 行ごとにデータを渡して繰り返し描画 | [ngTemplateOutletContext]="{ $implicit: row }" |
<ng-template #row let-item>...</ng-template> |
| 項目 | ng-content | ng-template + ngTemplateOutlet |
|---|---|---|
| 中身が生成される時期 | 部品が表示していなくても、利用する側で生成される | 部品が描画したときに生成される |
| 同じ中身を複数回描画 | できない(1か所だけ) | できる |
| 部品から中身へデータを渡す | できない | context で渡せる |
| 書きやすさ | タグの内側に書くだけ | ng-template で包む必要がある |
まずは ng-content で作り、「条件つきで出したい」「繰り返したい」「データを渡したい」のどれかが必要になったら ng-template に切り替える、という順で考えると選びやすくなります。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Angular ng-contentの使い方|selectと投影の基本」
基本:ng-content で中身を差し込む
最小の例です。部品のテンプレートに ng-content を1つ置くと、利用する側がタグの内側に書いたものがそこに表示されます。
import { Component } from '@angular/core';
@Component({
selector: 'app-box',
template: `<div class="box"><ng-content /></div>`,
})
export class Box {}
<app-box id="box">
<p>ここに書いた内容が box の中に表示されます。</p>
</app-box>
描画後の HTML は次のとおりです。
<app-box id="box"><div class="box"><p>ここに書いた内容が box の中に表示されます。</p></div></app-box>
Angular 日本語版ドキュメントのコンテンツ投影のページでは、ng-content はブラウザー標準の slot 要素に似た働きをするものと紹介されています。あわせて「ng-content はコンポーネントでも DOM 要素でもない」とも説明されており、ng-content 自体にクラスやディレクティブを付けることはできません。スタイルを当てたいときは、上の例のように外側を div などで包みます。
部品1:カード(select・フォールバック・ngProjectAs)
タイトル・本文・操作ボタンの3つのスロットを持つカードです。
// src/app/proj.ts
import { Component, signal } from '@angular/core';
@Component({
selector: 'app-card',
template: `
<section class="card">
<header><ng-content select="[card-title]">無題のカード</ng-content></header>
<div class="card-body"><ng-content /></div>
<footer>
<ng-content select="[card-actions]"><button>閉じる</button></ng-content>
</footer>
</section>
`,
})
export class Card {}
@Component({
selector: 'app-card-demo',
imports: [Card],
template: `
<app-card id="card1">
<h2 card-title>在庫のお知らせ</h2>
<p>ノートが残り 3 冊です。</p>
<p>補充を検討してください。</p>
<ng-container ngProjectAs="[card-actions]">
<button>発注する</button>
<button>あとで</button>
</ng-container>
</app-card>
<app-card id="card2">
<p>本文だけを渡したカードです。</p>
</app-card>
<app-card id="card3">
@if (showTitle()) {
<h2 card-title>@if の中のタイトル</h2>
}
<p>条件つきでタイトルを渡します。</p>
</app-card>
`,
})
export class CardDemo { showTitle = signal(true); }
select で複数スロットに振り分ける
select には CSS セレクターを書きます。[card-title] は「card-title 属性を持つ要素」という意味です。select のない ng-content は、どのスロットにも一致しなかった残り全部を受け取ります。
1枚目のカード(card1)の描画後の HTML です。以降の HTML 出力は、ブラウザーで要素の outerHTML を取得し、読みやすいように改行とインデントを加え、Angular が目印として入れるコメントノードを省いたものです。
<app-card id="card1">
<section class="card">
<header><h2 card-title="">在庫のお知らせ</h2></header>
<div class="card-body">
<p>ノートが残り 3 冊です。</p>
<p>補充を検討してください。</p>
</div>
<footer><button>発注する</button><button>あとで</button></footer>
</section>
</app-card>
h2は header へ、2つのpは本文へ、ボタン2つは footer へ入りました。- 利用する側で書いた順番に関係なく、部品側の ng-content の位置に並びます。
- 出力に ng-content や ng-container というタグは残りません。
タグ名・クラスで振り分ける
select には、属性のほかにタグ名やクラスも書けます。ドキュメントでは、ng-content はコンポーネントのセレクターと同じ CSS セレクターをサポートすると説明されています。
import { Component } from '@angular/core';
@Component({
selector: 'app-sel',
template: `
<div class="head"><ng-content select="h2" /></div>
<div class="notes"><ng-content select=".note" /></div>
<div class="rest"><ng-content /></div>
`,
})
export class Sel {}
<app-sel id="sel">
<p>ふつうの段落</p>
<p class="note">メモ</p>
<h2>見出し</h2>
</app-sel>
<app-sel id="sel">
<div class="head"><h2>見出し</h2></div>
<div class="notes"><p class="note">メモ</p></div>
<div class="rest"><p>ふつうの段落</p></div>
</app-sel>
利用する側では見出しを最後に書きましたが、出力では部品側の並びどおり先頭に入っています。
フォールバック:渡されなかったときの既定の表示
ng-content の開始タグと終了タグの間に書いた内容は、そのスロットに何も渡されなかったときに表示されます。本文だけを渡した2枚目のカード(card2)の出力です。
<app-card id="card2">
<section class="card">
<header>無題のカード</header>
<div class="card-body"><p>本文だけを渡したカードです。</p></div>
<footer><button>閉じる</button></footer>
</section>
</app-card>
タイトルには「無題のカード」、footer には「閉じる」ボタンが入りました。よく使う既定値を部品側に持たせておくと、利用する側の記述が短くなります。
ngProjectAs:複数の要素をまとめて1つのスロットへ
1枚目のカードでは、ボタン2つを ng-container で包み、ngProjectAs="[card-actions]" を付けました。ng-container は DOM に要素を出力しない入れ物なので、余分な div を増やさずに「この中身全体を card-actions スロットに入れる」と指定できます。上の出力でも、footer の中にはボタン2つだけが入っています。ドキュメントには、ngProjectAs は静的な値のみをサポートし、動的な式にはバインドできないと書かれています。
利用する側の @if とスロットの関係
3枚目のカード(card3)は、タイトルを @if で包んで渡しています。テンプレートの中で文字として @ を書くときは、例のように @ と書きます。
<app-card id="card3">
<section class="card">
<header><h2 card-title="">@if の中のタイトル</h2></header>
<div class="card-body"><p>条件つきでタイトルを渡します。</p></div>
<footer><button>閉じる</button></footer>
</section>
</app-card>
@if の直下が1つの要素だけなら、その要素のセレクターでスロットに振り分けられました。一方、@if の直下に2つの要素を置いた場合は、次のようになります。
<app-card id="card4">
@if (showTitle()) {
<h2 card-title>タイトル</h2>
<small>補足</small>
}
<p>本文</p>
</app-card>
ng build で次の警告が出ます。
▲ [WARNING] NG8011: Node matches the "[card-title]" slot of the "Card" component, but will not be projected into the specific slot because the surrounding @if has more than one node at its root. To project the node in the right slot, you can:
1. Wrap the content of the @if block in an <ng-container/> that matches the "[card-title]" selector.
2. Split the content of the @if block across multiple @if blocks such that each one only has a single projectable node at its root.
3. Remove all content from the @if block, except for the node being projected.
描画結果も、タイトルが header ではなく本文のスロットに入り、header にはフォールバックが表示されました。
<app-card id="card4">
<section class="card">
<header>無題のカード</header>
<div class="card-body">
<h2 card-title="">タイトル</h2><small>補足</small>
<p>本文</p>
</div>
<footer><button>閉じる</button></footer>
</section>
</app-card>
警告の1番の案のとおり、@if の中身を ngProjectAs 付きの ng-container で包むと、意図どおり header に入ります。
<app-card id="card5">
@if (showTitle()) {
<ng-container ngProjectAs="[card-title]">
<h2>タイトル</h2>
<small>補足</small>
</ng-container>
}
<p>本文</p>
</app-card>
<app-card id="card5">
<section class="card">
<header><h2>タイトル</h2><small>補足</small></header>
<div class="card-body"><p>本文</p></div>
<footer><button>閉じる</button></footer>
</section>
</app-card>
@if の中に ng-content を置くと投影されない場面
ここからは部品側の話です。ドキュメントには「ng-content を @if、@for、@switch によって条件付きで含めるべきではありません」と書かれています。実際に何が起きるかを2つの例で再現しました。
例1:分岐の両方に ng-content を置く
import { Component, input } from '@angular/core';
@Component({
selector: 'app-panel-two',
template: `
@if (compact()) {
<div class="compact"><ng-content /></div>
} @else {
<div class="wide"><ng-content /></div>
}
`,
})
export class PanelTwo { compact = input(false); }
<app-panel-two id="p-compact" [compact]="true"><b>中身A</b></app-panel-two>
<app-panel-two id="p-wide" [compact]="false"><b>中身B</b></app-panel-two>
描画後の HTML です。
<app-panel-two id="p-compact"><div class="compact"></div></app-panel-two>
<app-panel-two id="p-wide"><div class="wide"><b>中身B</b></div></app-panel-two>
compact が true のほうは、div は出ているのに中身が空です。同じセレクター(ここでは select なし)の ng-content がテンプレートに2つあると、中身はあとに書いたほう(@else の中)に割り当てられ、先に書いたほうには入りませんでした。ビルド時のエラーや警告は出ないので、気づきにくい動きです。
例2:@if の中に ng-content を1つだけ置く
閉じているあいだは中身を表示しない、モーダル風の部品です。中身に、生成と破棄をログに出すコンポーネント(Heavy)を渡します。
import { Component, OnDestroy, input } from '@angular/core';
@Component({
selector: 'app-heavy',
template: `<p>重い中身</p>`,
})
export class Heavy implements OnDestroy {
constructor() { console.log('Heavy: constructor(生成された)'); }
ngOnDestroy() { console.log('Heavy: ngOnDestroy(破棄された)'); }
}
@Component({
selector: 'app-modal-if',
template: `
@if (open()) {
<div class="modal"><ng-content /></div>
}
`,
})
export class ModalIf { open = input(false); }
<app-modal-if id="m-if" [open]="false"><app-heavy /></app-modal-if>
open が false のままページを開いたときの、コンソール出力と HTML です。
Heavy: constructor(生成された)
<app-modal-if id="m-if"></app-modal-if>
画面には何も出ていないのに、Heavy は生成されています。 ng-content に渡す中身は、利用する側のテンプレートの一部として先に作られるためです。ドキュメントにも「Angularは常にレンダリングされたコンテンツのDOMノードをインスタンス化して作成します」と書かれており、差し込み先が表示されていなくても中身は作られます。中身がデータ取得を行うコンポーネントだと、開いていないモーダルの分まで処理が走ることになります。
ng-template と ngTemplateOutlet での直し方
直し方1:ng-content を ng-template の中に1つだけ置く
例1(分岐の両方に表示したい)は、ng-content を ng-template の中に1つだけ置き、分岐の中からは ngTemplateOutlet で呼び出す形にします。
import { NgTemplateOutlet } from '@angular/common';
import { Component, input } from '@angular/core';
@Component({
selector: 'app-panel-fixed',
imports: [NgTemplateOutlet],
template: `
<ng-template #content><ng-content /></ng-template>
@if (compact()) {
<div class="compact"><ng-container [ngTemplateOutlet]="content" /></div>
} @else {
<div class="wide"><ng-container [ngTemplateOutlet]="content" /></div>
}
`,
})
export class PanelFixed { compact = input(false); }
<app-panel-fixed id="f-compact"><div class="compact"><b>中身A</b></div></app-panel-fixed>
<app-panel-fixed id="f-wide"><div class="wide"><b>中身B</b></div></app-panel-fixed>
どちらの分岐でも中身が表示されました。
直し方2(部品2:モーダル):利用する側から ng-template を受け取る
例2(開くまで中身を生成したくない)は、利用する側に中身を ng-template で包んでもらい、部品側は contentChild で TemplateRef を受け取って、開いたときだけ ngTemplateOutlet で描画します。タイトルは ng-content、本文と footer は ng-template、という組み合わせです。
import { NgTemplateOutlet } from '@angular/common';
import { Component, TemplateRef, contentChild, signal } from '@angular/core';
@Component({
selector: 'app-modal',
imports: [NgTemplateOutlet],
template: `
@if (open()) {
<div class="backdrop">
<div class="modal" role="dialog" aria-modal="true">
<header><ng-content select="[modal-title]">確認</ng-content></header>
<div class="modal-body">
<ng-container [ngTemplateOutlet]="body()" />
</div>
<footer>
@if (footer(); as f) {
<ng-container [ngTemplateOutlet]="f" [ngTemplateOutletContext]="{ close: closeFn }" />
} @else {
<button (click)="closeFn()">閉じる</button>
}
</footer>
</div>
</div>
}
`,
})
export class Modal {
open = signal(false);
body = contentChild.required<TemplateRef<unknown>>('body');
footer = contentChild<TemplateRef<{ close: () => void }>>('footer');
closeFn = () => this.open.set(false);
}
利用する側です(imports に Modal と Heavy を入れます)。
<button id="open" (click)="modal.open.set(true)">モーダルを開く</button>
<app-modal #modal id="m-good">
<span modal-title>削除の確認</span>
<ng-template #body><app-heavy /></ng-template>
<ng-template #footer let-close="close">
<button id="cancel" (click)="close()">やめる</button>
<button>削除する</button>
</ng-template>
</app-modal>
「モーダルを開く」→「やめる」の順に押したときの、コンソール出力と HTML です。
| 操作 | コンソール出力 | app-modal の中身 |
|---|---|---|
| 初回表示(閉じている) | なし | 空 |
| 「モーダルを開く」を押す | Heavy: constructor(生成された) | 下の HTML |
| 「やめる」を押す | Heavy: ngOnDestroy(破棄された) | 空 |
<app-modal id="m-good">
<div class="backdrop">
<div role="dialog" aria-modal="true" class="modal">
<header><span modal-title="">削除の確認</span></header>
<div class="modal-body"><app-heavy><p>重い中身</p></app-heavy></div>
<footer><button id="cancel">やめる</button><button>削除する</button></footer>
</div>
</div>
</app-modal>
- Heavy は開いたときに初めて生成され、閉じると破棄されました。 ng-template の中身は、ngTemplateOutlet で描画されるまで作られません。
- footer のテンプレートには、context で
closeという関数を渡しています。利用する側はlet-close="close"で受け取り、自分のボタンから呼び出せます。 - 本文の ng-template だけを渡したモーダルを開くと、タイトルはフォールバックの「確認」、footer は
@else側の「閉じる」ボタンになりました。ng-template でも、contentChild の結果が undefined かどうかで既定の表示を切り替えられます。 - タイトルの ng-content は
@ifの中にありますが、1つだけで、中身も軽い要素なので、このまま使っています。
部品3:一覧テーブル(ngTemplateOutlet + context で行データを渡す)
「表の枠は部品が持ち、1行の見た目は利用する側が決める」テーブルです。部品が行ごとに ngTemplateOutlet を呼び、context で行データと番号を渡します。
import { NgTemplateOutlet } from '@angular/common';
import { Component, TemplateRef, contentChild, input } from '@angular/core';
@Component({
selector: 'app-data-table',
imports: [NgTemplateOutlet],
template: `
<table>
<thead>
<tr>
@for (c of columns(); track c) { <th>{{ c }}</th> }
</tr>
</thead>
<tbody>
@for (row of rows(); track $index; let i = $index, odd = $odd) {
<tr>
<ng-container
[ngTemplateOutlet]="rowTpl()"
[ngTemplateOutletContext]="{ $implicit: row, index: i, odd: odd }" />
</tr>
} @empty {
<tr><td [attr.colspan]="columns().length"><ng-content select="[empty]">データがありません</ng-content></td></tr>
}
</tbody>
</table>
`,
})
export class DataTable<T> {
columns = input.required<string[]>();
rows = input.required<T[]>();
rowTpl = contentChild.required<TemplateRef<{ $implicit: T; index: number; odd: boolean }>>('row');
}
interface Item { name: string; stock: number; }
@Component({
selector: 'app-table-demo',
imports: [DataTable],
template: `
<app-data-table id="t1" [columns]="['No', '品名', '在庫']" [rows]="items">
<ng-template #row let-item let-i="index">
<td>{{ i + 1 }}</td>
<td>{{ item.name }}</td>
<td>{{ item.stock }} 個</td>
</ng-template>
</app-data-table>
<app-data-table id="t2" [columns]="['No', '品名', '在庫']" [rows]="[]">
<ng-template #row let-item><td>{{ item.name }}</td></ng-template>
<span empty>該当する備品はありません</span>
</app-data-table>
`,
})
export class TableDemo {
items: Item[] = [
{ name: 'ノート', stock: 3 },
{ name: 'ボールペン', stock: 12 },
{ name: '付箋', stock: 0 },
];
}
1つ目のテーブル(3件)の出力です。
<app-data-table id="t1">
<table>
<thead><tr><th>No</th><th>品名</th><th>在庫</th></tr></thead>
<tbody>
<tr><td>1</td><td>ノート</td><td>3 個</td></tr>
<tr><td>2</td><td>ボールペン</td><td>12 個</td></tr>
<tr><td>3</td><td>付箋</td><td>0 個</td></tr>
</tbody>
</table>
</app-data-table>
2つ目のテーブル(0件)の出力です。
<app-data-table id="t2">
<table>
<thead><tr><th>No</th><th>品名</th><th>在庫</th></tr></thead>
<tbody>
<tr><td colspan="3"><span empty="">該当する備品はありません</span></td></tr>
</tbody>
</table>
</app-data-table>
context と let- の対応
| 部品側の context | 利用する側の受け取り方 | 意味 |
|---|---|---|
$implicit: row |
let-item |
値を書かない let- は $implicit を受け取る。変数名は自由 |
index: i |
let-i="index" |
右辺が context のキー、左辺がテンプレート内の変数名 |
odd: odd |
let-isOdd="odd" |
1行目は false、2行目は true が届いた。使わないキーは受け取らなくてよい |
close: closeFn(モーダルの例) |
let-close="close" |
関数も渡せる |
context にないキー名を右辺に書いた場合(たとえば let-x="idx")は、エラーにはならず、その変数を表示した箇所が空になりました。値が出ないときは、まず右辺のキー名を確認します。
Angular 公式の NgTemplateOutlet の API リファレンスでも、context オブジェクトのキーがテンプレート側の let 宣言で使えること、$implicit というキーの値が既定値になることが説明されています。
1つの ng-template を行の数だけ繰り返し描画できるのが、ng-content との大きな違いです。ng-content は1か所にしか表示できないので、行ごとの見た目を外から渡す用途には ng-template を使います。0件のときのメッセージのように「1か所に出すだけ」の部分は、ng-content とフォールバックで十分です(2つ目のテーブルでは、@empty の中に置いた ng-content へ span が入りました)。
ng-content と ngTemplateOutlet の使い分け表
| 場面 | 選ぶもの | 今回の例 |
|---|---|---|
| 見た目の枠だけ部品にして、中身は自由に書かせたい | ng-content | カードの本文 |
| タイトル・本文・ボタンなど場所を分けたい | ng-content + select | カード、モーダルのタイトル |
| 渡されなかったときの既定の表示がほしい | ng-content のフォールバック | 「無題のカード」「閉じる」 |
| 複数の要素を余分なタグなしで1つのスロットへ | ng-container + ngProjectAs | カードのボタン2つ |
| 開くまで中身を生成したくない | ng-template + contentChild + ngTemplateOutlet | モーダルの本文 |
| 分岐のどちらにも同じ中身を出したい | ng-template の中に ng-content を1つ + ngTemplateOutlet | PanelFixed |
| 同じ中身を繰り返し描画したい | ng-template + ngTemplateOutlet | テーブルの行 |
| 部品から中身へデータや関数を渡したい | ngTemplateOutletContext と let- | 行データ、close 関数 |
つまずきやすい点と直し方
| 起きること | 原因 | 直し方 |
|---|---|---|
| select を付けたスロットに入らず、本文に入る | 属性名やクラス名がセレクターと合っていない | セレクターと渡す側の属性を見直す |
@if で包んだ要素がスロットに入らない(NG8011 の警告) |
@if の直下に要素が2つ以上ある |
ngProjectAs 付きの ng-container で包む |
| 分岐の片方で中身が空になる | 同じセレクターの ng-content が2つある | ng-template の中に ng-content を1つだけ置く |
| 閉じているのに中身のコンポーネントが動いている | ng-content の中身は常に生成される | ng-template で受け取り、開いたときに描画する |
| ng-content 自体にクラスやディレクティブを付けたい | ng-content は DOM 要素ではない(ドキュメントの説明) | 外側を div などで包んでクラスを付ける |
| let- で受け取った値が空 | context のキー名と let- の右辺が合っていない | let-i="index" の右辺をキー名に合わせる |
よくある質問
Q. ng-content と ng-template の違いは何ですか? A. ng-content は「渡された中身をここに表示する」ための場所で、中身は利用する側で先に生成されます。ng-template は「あとで描画するためのひな形」で、ngTemplateOutlet などで描画するまで生成されません。条件つきの表示、繰り返し、データの受け渡しが必要なら ng-template が向いています。
Q. select にはどんな書き方ができますか?
A. CSS セレクターを書きます。今回は属性([card-title])、タグ名(h2)、クラス(.note)の3通りで振り分けられることを確かめました。select のない ng-content は、どこにも一致しなかった残りを受け取ります。
Q. ng-content を @if の中に置いてもよいですか? A. ドキュメントでは、条件付きで置かないよう案内されています。今回の再現でも、分岐の両方に置くと片方が空になり、1つだけ置いた場合も中身のコンポーネントは表示前に生成されました。条件つきにしたいときは ng-template と ngTemplateOutlet を使います。
Q. スロットに中身が渡されたかどうかを部品側で知るには? A. ng-content ならフォールバックを書いておけば、渡されなかったときに自動で表示されます。ng-template で受け取る場合は、contentChild の結果が undefined かどうかで分岐できます(モーダルの footer の例)。
まとめ
- ng-content は、利用する側がタグの内側に書いた中身を差し込む場所。出力の HTML に ng-content のタグは残らない。
- select で複数スロットに振り分け、select のない ng-content が残り全部を受け取る。
- 開始タグと終了タグの間に書いた内容がフォールバックになり、渡されなかったときに表示される。
- 複数の要素を1つのスロットに入れるときは ng-container と ngProjectAs。
@ifの直下に要素が2つ以上あるときの NG8011 もこれで直せる。 - 同じ ng-content を分岐の両方に置くと片方が空になる。ng-template の中に1つだけ置いて ngTemplateOutlet で呼び出す。
- ng-content の中身は表示していなくても生成される。開くまで生成したくない中身は ng-template で受け取る。
- 行ごとの描画やデータの受け渡しは ngTemplateOutlet と context。
$implicitはlet-item、ほかのキーはlet-i="index"で受け取る。
参考・出典
- Angular 日本語版ドキュメント「ng-content によるコンテンツ投影」 https://angular.jp/guide/components/content-projection
- Angular 公式 API リファレンス NgTemplateOutlet https://angular.dev/api/common/NgTemplateOutlet
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Angular ng-contentの使い方|selectと投影の基本」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。