angular-directives について
Angular 21でディレクティブを作成、保守する開発者向けの解説スキルです。ディレクティブのパターンや新しいAPI、再利用しやすく役割を絞るための指針を説明します。
主な機能
- 01属性型・構造型ディレクティブのパターン
- 02hostDirectivesによる合成
- 03シグナル入力とスタンドアロンディレクティブ
- 04TemplateRefとViewContainerRefの利用
- 05役割を絞った設計と明確なセレクター
活用シーン
- 01再利用可能な要素動作の作成
- 02条件付き埋め込みビューの構築
- 03コンポーネント上でのディレクティブ合成
- 04ディレクティブへのリアクティブ入力追加
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ oguzhan18/ angular-ecosystem-skills --skill angular-directivesインストール後、Claude Code で/angular-directivesを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/discussions/_INDEX.mdreferences/docs/_INDEX.mdreferences/issues/_INDEX.mdreferences/releases/_INDEX.md詳細
Angular ディレクティブ
バージョン: Angular 21(2025) タグ: ディレクティブ、コンポーネント、DOM、カスタムディレクティブ
参考資料: ディレクティブガイド • 属性ディレクティブ • 構造ディレクティブ
API の変更
このセクションでは、最近のバージョン固有の API の変更について説明します。
-
NEW:ディレクティブ合成 API —
hostDirectivesを使ってディレクティブを合成します source -
NEW:ディレクティブのシグナル入力 —
input()を使ってリアクティブなディレクティブのプロパティを定義します -
NEW:スタンドアロンディレクティブ — すべてのディレクティブをスタンドアロンにできます
-
NEW:制御フロー構文 — @if、@for、@switch が *ngIf、*ngFor に置き換わります
ベストプラクティス
- 再利用可能な動作には属性ディレクティブを作成します
import { Directive, ElementRef, Renderer2, Input } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
@Input() set appHighlight(color: string) {
this.renderer.setStyle(this.el.nativeElement, 'background-color', color || 'yellow');
}
constructor(private el: ElementRef, private renderer: Renderer2) {}
}
- ディレクティブ間の通信には @Input と @Output を使います
@Directive({
selector: '[appClickTracker]'
})
export class ClickTrackerDirective {
@Input() trackName = 'default';
@Output() clicked = new EventEmitter<string>();
@HostListener('click')
onClick() {
this.clicked.emit(this.trackName);
}
}
- 構造ディレクティブには TemplateRef を使います
import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
@Directive({
selector: '[appUnless]'
})
export class UnlessDirective {
@Input() set appUnless(condition: boolean) {
if (!condition) {
this.vcRef.createEmbeddedView(this.templateRef);
} else {
this.vcRef.clear();
}
}
constructor(
private templateRef: TemplateRef<any>,
private vcRef: ViewContainerRef
) {}
}
- 複雑な構造ロジックには ViewContainerRef を使います
@Directive({ selector: '[appDynamic]' })
export class DynamicDirective {
constructor(
private vcr: ViewContainerRef,
private templateRef: TemplateRef<any>
) {
this.vcr.createEmbeddedView(this.templateRef);
}
}
- 合成には hostDirectives を使います
@Component({
selector: 'app-card',
standalone: true,
imports: [HighlightDirective],
hostDirectives: [
{
directive: HighlightDirective,
inputs: ['appHighlight: highlight']
}
],
template: `<ng-content></ng-content>`
})
export class CardComponent {}
- 最新のディレクティブでは standalone: true を使います
@Directive({
selector: '[appStandalone]',
standalone: true
})
export class StandaloneDirective {}
- ディレクティブでシグナルを使います
@Directive({
selector: '[appSignal]'
})
export class SignalDirective {
value = input<string>('');
ngOnInit() {
console.log(this.value());
}
}
- プロパティバインディングには @HostBinding を使います
@Directive({
selector: '[appDisable]'
})
export class DisableDirective {
@Input() set disabled(value: boolean) {
this.hostBinding.nativeElement.disabled = value;
}
constructor(private hostBinding: ElementRef) {}
}
- ディレクティブの責務は一つに絞ります
// ✅ Good - focused directive
@Directive({ selector: '[appTooltip]' })
// ❌ Bad - too many responsibilities
@Directive({ selector: '[appTooltip][appTooltipMaxWidth][appTooltipTheme]' })
- 説明的なセレクターを使います
// ✅ Good
@Directive({ selector: '[appUserCard]' })
// ❌ Bad
@Directive({ selector: '[appUc]' })
コメント
Markdown 対応