Angular @ContentChild와 @ContentChildren 활용
@ViewChild와 @ViewChildren은 같은 컴포넌트 내에서 뷰 요소를 참조하는데 사용됩니다.
반면, @ContentChild와 @ContentChildren은 부모 컴포넌트가 ng-content를 통해 전달받은 자식 컴포넌트나 요소를 참조할 때 사용됩니다.
@ContentChild의 개념 및 활용
@ContentChild 개요
@ContentChild는 ng-content를 통해 삽입된 단일 자식 요소를 참조하는 데 사용됩니다.
2.2 예제: 부모 컴포넌트가 자식의 메서드 호출하기
// child.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-child',
template: `<p>자식 컴포넌트</p>`
})
export class ChildComponent {
showMessage() {
return '자식 컴포넌트의 메시지';
}
}
// parent.component.ts
import { Component, ContentChild, AfterContentInit } from '@angular/core';
import { ChildComponent } from './child.component';
@Component({
selector: 'app-parent',
template: `
<ng-content></ng-content>
<button (click)="showChildMessage()">자식 메시지 출력</button>
`
})
export class ParentComponent implements AfterContentInit {
@ContentChild(ChildComponent) child!: ChildComponent;
ngAfterContentInit() {
console.log('자식 컴포넌트 접근 가능:', this.child.showMessage());
}
showChildMessage() {
alert(this.child.showMessage());
}
}
<!-- app.component.html -->
<app-parent>
<app-child></app-child>
</app-parent>
- @ContentChild(ChildComponent)를 사용해 부모 컴포넌트가 자식의 인스턴스를 참조합니다.
- ngAfterContentInit()에서 showMessage()를 호출하여 자식 컴포넌트의 데이터를 활용합니다.
- 버튼 클릭 시 showChildMessage()가 호출되어 자식의 메시지가 표시됩니다.
@ContentChildren의 개념 및 활용
@ContentChildren 개요
@ContentChildren은 여러 개의 자식 컴포넌트를 QueryList 형태로 참조할 때 사용됩니다.
부모가 여러 개의 자식 컴포넌트를 관리하기
// item.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-item',
template: `<p>아이템 컴포넌트</p>`
})
export class ItemComponent {
getItemName() {
return '아이템 데이터';
}
}
// parent.component.ts
import { Component, ContentChildren, QueryList, AfterContentInit } from '@angular/core';
import { ItemComponent } from './item.component';
@Component({
selector: 'app-parent',
template: `
<ng-content></ng-content>
<button (click)="logItemData()">아이템 데이터 출력</button>
`
})
export class ParentComponent implements AfterContentInit {
@ContentChildren(ItemComponent) items!: QueryList<ItemComponent>;
ngAfterContentInit() {
this.items.forEach((item, index) => {
console.log(`아이템 ${index + 1}:`, item.getItemName());
});
}
logItemData() {
this.items.forEach((item, index) => {
console.log(`아이템 ${index + 1}:`, item.getItemName());
});
}
}
<!-- app.component.html -->
<app-parent>
<app-item></app-item>
<app-item></app-item>
<app-item></app-item>
</app-parent>
- @ContentChildren(ItemComponent)을 사용하여 부모가 여러 개의 자식 컴포넌트를 배열 형태로 참조합니다.
- QueryList.forEach()를 이용해 각 자식의 getItemName()을 호출합니다.
- 부모가 모든 자식 데이터를 한 번에 관리하고 조작할 수 있습니다.
@ContentChild vs @ViewChild 차이점
| 특징 | @ContentChild / @ContentChildren | @ViewChild / @ViewChildren |
| 대상 | ng-content로 전달된 자식 요소 | 부모의 템플릿 내 요소 |
| 접근 가능 시점 | ngAfterContentInit 이후 | ngAfterViewInit 이후 |
| 다중 요소 관리 | @ContentChildren 사용 | @ViewChildren 사용 |
- @ViewChild와 @ViewChildren은 부모 템플릿에서 선언된 요소를 다룹니다.
- @ContentChild와 @ContentChildren은 ng-content로 삽입된 외부 요소를 다룹니다.
부모가 자식의 상태 변경 감지하기
자식이 부모에게 변경 사항 알리기
자식이 @Output()을 사용하여 부모에게 상태 변화를 알리는 것도 가능하지만, @ContentChild를 활용하면 더 직관적으로 부모가 자식의 변화를 감지할 수 있습니다.
// child.component.ts
import { Component, EventEmitter, Output } from '@angular/core';
@Component({
selector: 'app-child',
template: `<button (click)="updateState()">상태 변경</button>`
})
export class ChildComponent {
@Output() stateChanged = new EventEmitter<string>();
updateState() {
this.stateChanged.emit('새로운 상태');
}
}
// parent.component.ts
import { Component, ContentChild, AfterContentInit } from '@angular/core';
import { ChildComponent } from './child.component';
@Component({
selector: 'app-parent',
template: `<ng-content></ng-content>`
})
export class ParentComponent implements AfterContentInit {
@ContentChild(ChildComponent) child!: ChildComponent;
ngAfterContentInit() {
this.child.stateChanged.subscribe(state => {
console.log('자식 상태 변경:', state);
});
}
}
'개발 공부 > Angular' 카테고리의 다른 글
| Angular Resolve (0) | 2025.03.15 |
|---|---|
| Angular CanActivate (0) | 2025.03.13 |
| @ViewChild와 @ViewChildren (3) ngAfterViewInit, static (0) | 2025.02.17 |
| @ViewChild와 @ViewChildren (2) 기본 활용 (0) | 2025.02.15 |
| @ViewChild와 @ViewChildren (1) (0) | 2025.02.13 |