Angularの公式ドキュメントでは解説されていない、@ViewChildと@ContentChildの秘密
Angularにおける@ViewChildと@ContentChildの違い
@ViewChildは、コンポーネントテンプレート内の要素を取得するために使用されます。 一方、@ContentChildは、別のコンポーネントから直接要素を取得するために使用されます。
それぞれの特徴
項目 | @ViewChild | @ContentChild |
---|---|---|
取得対象 | テンプレート内の要素 | 別のコンポーネント |
適用対象 | コンポーネント | コンポーネント |
取得方法 | 参照名 | プロパティ |
使用例 | 子コンポーネントへのアクセス | プロジェクションされたコンテンツへのアクセス |
例
- @ViewChild
<button #myButton (click)="onClick()">Click me!</button>
@Component({
selector: 'my-component',
templateUrl: './my-component.html',
})
export class MyComponent {
@ViewChild('myButton') button!: ElementRef;
onClick() {
this.button.nativeElement.click();
}
}
- @ContentChild
<my-child>
<p>This is projected content</p>
</my-child>
@Component({
selector: 'my-parent',
templateUrl: './my-parent.html',
})
export class MyParentComponent {
@ContentChild(MyChildComponent) child!: MyChildComponent;
}
@Component({
selector: 'my-child',
templateUrl: './my-child.html',
})
export class MyChildComponent {
// ...
}
- @ViewChildは、テンプレート内の要素を取得する
- @ContentChildは、別のコンポーネントから直接要素を取得する
どちらを使用するかは、取得したい要素の場所によって異なります。
@ViewChild
<div>
<button #myButton (click)="onClick()">Click me!</button>
</div>
@Component({
selector: 'my-parent',
templateUrl: './my-parent.html',
})
export class MyParentComponent {
@ViewChild('myButton') button!: ElementRef;
onClick() {
console.log('Button clicked!');
}
}
@ContentChild
子コンポーネント
<p>This is projected content</p>
@Component({
selector: 'my-child',
templateUrl: './my-child.html',
})
export class MyChildComponent {
// ...
}
<my-parent>
<my-child>
<p>This is projected content</p>
</my-child>
</my-parent>
@Component({
selector: 'my-parent',
templateUrl: './my-parent.html',
})
export class MyParentComponent {
@ContentChild(MyChildComponent) child!: MyChildComponent;
constructor() {
console.log('Child component:', this.child);
}
}
実行結果
Child component: MyChildComponent {
// ...
}
Button clicked!
my-parent.html
テンプレート内の#myButton
という参照名のボタン要素を取得し、MyParentComponent
クラスのbutton
プロパティに格納しています。
onClick()
メソッド内で、button
プロパティのnativeElement
プロパティを使用して、ボタン要素のclick()
イベントを発火しています。
my-parent.html
テンプレート内でmy-child
コンポーネントがプロジェクションされた内容を取得し、MyParentComponent
クラスのchild
プロパティに格納しています。
constructor
内で、child
プロパティの内容を出力しています。
Angularで要素を取得する他の方法
テンプレート変数を使用して、テンプレート内の要素に直接アクセスできます。
<button #myButton (click)="onClick()">Click me!</button>
@Component({
selector: 'my-component',
templateUrl: './my-component.html',
})
export class MyComponent {
onClick() {
console.log('Button clicked:', myButton);
}
}
ElementRef
を使用して、DOM要素への直接アクセスを取得できます。
<button (click)="onClick($event)">Click me!</button>
@Component({
selector: 'my-component',
templateUrl: './my-component.html',
})
export class MyComponent {
onClick(event: Event) {
const button = event.target as HTMLButtonElement;
console.log('Button clicked:', button);
}
}
QueryList
を使用して、特定の条件に一致する要素のリストを取得できます。
<div>
<button #button1>Button 1</button>
<button #button2>Button 2</button>
</div>
@Component({
selector: 'my-component',
templateUrl: './my-component.html',
})
export class MyComponent {
@ViewChildren('button') buttons!: QueryList<ElementRef>;
ngAfterViewInit() {
console.log('Buttons:', this.buttons);
}
}
getElementsByClassName()
を使用して、特定のクラス名を持つ要素のリストを取得できます。
<div>
<button class="my-button">Button 1</button>
<button class="my-button">Button 2</button>
</div>
@Component({
selector: 'my-component',
templateUrl: './my-component.html',
})
export class MyComponent {
ngAfterViewInit() {
const buttons = document.getElementsByClassName('my-button');
console.log('Buttons:', buttons);
}
}
- テンプレート変数は、最もシンプルで簡単な方法です。
- @ViewChildは、コンポーネントテンプレート内の特定の要素を取得する必要がある場合に適しています。
QueryList
は、特定の条件に一致する要素のリストを取得する必要がある場合に適しています。
angular