Using @ContentChild and Content Projection in Angular
📖 Scenario: You are building a reusable Angular card component that can display a title and some custom content inside it. The card should allow users to pass in their own content to be displayed inside the card body.
🎯 Goal: Create an Angular card component that uses @ContentChild to access a projected title element and display it inside the card header. The card body should display any other projected content.
📋 What You'll Learn
Create a card component with a template that has a header and a body section
Use content projection to allow users to pass a title element and body content
Use @ContentChild to get a reference to the projected title element
Display the title inside the card header using the @ContentChild reference
💡 Why This Matters
🌍 Real World
Reusable UI components often need to accept custom content from users. Content projection and @ContentChild let you build flexible components that adapt to user content.
💼 Career
Understanding content projection and @ContentChild is essential for Angular developers building modular and maintainable UI components.
Progress0 / 4 steps
1
Create the card component template with content projection slots
Create an Angular component template with a <div> for the card header and another <div> for the card body. Use <ng-content select=".card-title"></ng-content> inside the header to project the title, and <ng-content></ng-content> inside the body to project the rest of the content.
Angular
Hint
Use <ng-content select=".card-title"></ng-content> to project the title element with class card-title inside the header.
2
Add a @ContentChild property to get the projected title element
In the card component TypeScript file, import ContentChild and ElementRef from @angular/core. Then create a property called titleElement decorated with @ContentChild that selects the element with the CSS selector ".card-title" and has type ElementRef<HTMLElement>.
Angular
Hint
Use @ContentChild('.card-title', { static: false }) to get the projected title element.
3
Use titleElement in the component to access the title content
Add a method called getTitleText() in the card component class that returns the text content of the titleElement native element. Use optional chaining to safely access nativeElement.textContent and return an empty string if not available.
Angular
Hint
Use optional chaining ?. to safely access nativeElement.textContent.
4
Display the title text inside the card header using interpolation
Modify the card component template to display the title text inside the header using interpolation with {{ getTitleText() }}. Remove the <ng-content select=".card-title"></ng-content> from the header since the title text is now accessed via @ContentChild.
Angular
Hint
Use interpolation {{ getTitleText() }} inside the header div to show the title text.
Practice
(1/5)
1. What does the Angular decorator @ContentChild do in a component?
easy
A. It projects content from the component into its parent.
B. It creates a new child component inside the template.
C. It gets a reference to a single element inside the projected content.
D. It listens to events emitted by child components.
Solution
Step 1: Understand content projection
Content projection allows inserting external content inside a component using <ng-content>.
Step 2: Role of @ContentChild
@ContentChild gets a reference to a single element or directive inside that projected content.
Final Answer:
It gets a reference to a single element inside the projected content. -> Option C
Quick Check:
@ContentChild = reference to projected element [OK]
Hint: Remember: @ContentChild targets projected content elements [OK]
Common Mistakes:
Confusing @ContentChild with @ViewChild
Thinking it creates new elements
Assuming it projects content instead of referencing it
2. Which of the following is the correct syntax to use @ContentChild to get a reference to a template variable named myRef?
easy
A. @ContentChild('myRef') myElement!: ElementRef;
B. @ContentChild(myRef) myElement!: ElementRef;
C. @ContentChild(#myRef) myElement!: ElementRef;
D. @ContentChild(myRef, {static: true}) myElement!: ElementRef;
Solution
Step 1: Correct syntax for @ContentChild selector
The selector must be a string matching the template variable name, so it should be quoted: 'myRef'.
Step 2: Static option usage
Static option is optional and usually false by default; not required here.
Final Answer:
@ContentChild('myRef') myElement!: ElementRef; -> Option A
Quick Check:
Use quotes around template variable name in @ContentChild [OK]
Hint: Use quotes around template variable name in @ContentChild [OK]
@ContentChild references are not available in ngOnInit; they become available in ngAfterContentInit.
Step 2: Accessing itemRef in ngOnInit
Accessing itemRef in ngOnInit causes it to be undefined, leading to runtime error when accessing nativeElement.
Final Answer:
Error because itemRef is undefined in ngOnInit -> Option B
Quick Check:
Use ngAfterContentInit for @ContentChild access [OK]
Hint: Access @ContentChild only in ngAfterContentInit [OK]
Common Mistakes:
Accessing @ContentChild in ngOnInit
Assuming @ContentChild is available immediately
Ignoring lifecycle hook order
5. You want to create a component that projects multiple paragraphs and highlights the first paragraph. Which approach correctly achieves this?
Options: A) Use @ContentChildren('para') and highlight the first in the list. B) Use @ContentChild('para') and add #para to the first paragraph only. C) Use @ViewChild('para') inside the component template. D) Use @ContentChild without a selector and highlight all paragraphs.
hard
A. Use @ContentChild without a selector and highlight all paragraphs.
B. Use @ContentChild('para') and add #para to the first paragraph only.
C. Use @ViewChild('para') inside the component template.
D. Use @ContentChildren('para') and highlight the first in the list.
Solution
Step 1: Understand multiple projected elements
When projecting multiple elements with the same template variable, use @ContentChildren to get all references.
Step 2: Highlight the first paragraph
@ContentChildren returns a QueryList; you can access the first element and apply highlight logic.
Final Answer:
Use @ContentChildren('para') and highlight the first in the list. -> Option D
Quick Check:
Multiple projected elements need @ContentChildren [OK]
Hint: Use @ContentChildren for multiple projected elements [OK]
Common Mistakes:
Using @ContentChild for multiple elements
Using @ViewChild for projected content
Omitting selector in @ContentChild
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.