Understanding ng-content in Angular
Question 1: What is ng-content and why is it used?
Answer: ng-content is a directive that enables content projection in Angular components. It allows you to:
- Insert external content into a component
 - Create reusable component templates
 - Build flexible and composable components
 - Implement the slot pattern from web components
 
Question 2: How do you implement basic and multi-slot content projection?
Answer: Here are examples of different content projection patterns:
// 1. Basic Content Projection
@Component({
  selector: 'app-card',
  template: `
    <div class="card">
      <div class="card-header">
        <ng-content select="[header]"></ng-content>
      </div>
      <div class="card-body">
        <ng-content></ng-content>
      </div>
      <div class="card-footer">
        <ng-content select="[footer]"></ng-content>
      </div>
    </div>
  `,
  styles: [`
    .card {
      border: 1px solid #ddd;
      border-radius: 4px;
    }
  `]
})
export class CardComponent {}
// Usage
@Component({
  selector: 'app-user-card',
  template: `
    <app-card>
      <h2 header>User Profile</h2>
      <div class="content">
        {{ user.name }}
      </div>
      <button footer>Edit Profile</button>
    </app-card>
  `
})
export class UserCardComponent {}
// 2. Multi-Slot Projection with Types
@Component({
  selector: 'app-dashboard-layout',
  template: `
    <div class="layout">
      <header>
        <ng-content select="app-header"></ng-content>
      </header>
      
      <nav class="sidebar">
        <ng-content select="app-sidebar"></ng-content>
      </nav>
      
      <main>
        <ng-content></ng-content>
      </main>
      
      <footer>
        <ng-content select="app-footer"></ng-content>
      </footer>
    </div>
  `
})
export class DashboardLayoutComponent {}Question 3: How do you work with projected content programmatically?
Answer: Here’s how to interact with projected content:
@Component({
  selector: 'app-content-wrapper',
  template: `
    <div class="wrapper">
      <ng-content></ng-content>
    </div>
  `
})
export class ContentWrapperComponent implements AfterContentInit {
  // Query all projected content
  @ContentChildren(ProjectedComponent)
  projectedComponents!: QueryList<ProjectedComponent>;
  
  // Query specific projected content
  @ContentChild('specificContent')
  specificContent!: ElementRef;
  
  // Content queries with read option
  @ContentChildren(ProjectedComponent, { read: ElementRef })
  projectedElements!: QueryList<ElementRef>;
  
  ngAfterContentInit() {
    // Access projected content
    this.projectedComponents.forEach(component => {
      console.log('Projected component:', component);
    });
    
    // Listen for changes
    this.projectedComponents.changes.pipe(
      takeUntilDestroyed()
    ).subscribe(changes => {
      console.log('Projected content changed:', changes);
    });
  }
}Question 4: How do you implement conditional content projection?
Answer: Here’s how to handle conditional content projection:
@Component({
  selector: 'app-conditional-content',
  template: `
    <div class="container">
      @if (hasHeaderContent()) {
        <header>
          <ng-content select="[header]"></ng-content>
        </header>
      }
      
      <main>
        <ng-content></ng-content>
      </main>
      
      <!-- Conditional Footer -->
      <footer>
        @if (hasFooterContent()) {
          <ng-content select="[footer]"></ng-content>
        } @else {
          <default-footer />
        }
      </footer>
    </div>
  `
})
export class ConditionalContentComponent {
  @ContentChild('header')
  headerContent!: ElementRef;
  
  @ContentChild('footer')
  footerContent!: ElementRef;
  
  hasHeaderContent(): boolean {
    return !!this.headerContent;
  }
  
  hasFooterContent(): boolean {
    return !!this.footerContent;
  }
}Interview Tips 💡
Content Projection Patterns
// Single slot <ng-content></ng-content> // Named slots <ng-content select="[header]"></ng-content> // Type-based selection <ng-content select="app-header"></ng-content> // Class-based selection <ng-content select=".content"></ng-content>Performance Optimization
@Component({ // Use OnPush for better performance changeDetection: ChangeDetectionStrategy.OnPush, template: ` <!-- Use defer for heavy content --> @defer (on viewport) { <ng-content select="[heavy-content]"></ng-content> } ` }) export class OptimizedComponent {}Content Lifecycle
@Component({...}) export class ContentAwareComponent implements AfterContentInit, AfterContentChecked { ngAfterContentInit() { // Content is initialized } ngAfterContentChecked() { // Content is checked } }Testing Projected Content
describe('CardComponent', () => { it('should project content', () => { const fixture = TestBed.createComponent(CardComponent); const compiled = fixture.nativeElement; // Test content projection const header = compiled.querySelector('[header]'); expect(header).toBeTruthy(); }); });Dynamic Content
@Component({ template: ` <ng-container *ngTemplateOutlet=" contentTemplate || defaultTemplate; context: { $implicit: data } "></ng-container> <ng-template #defaultTemplate> Default Content </ng-template> ` }) export class DynamicContentComponent { @ContentChild(TemplateRef) contentTemplate?: TemplateRef<any>; }Common Pitfalls
// DON'T: Access content before initialization constructor() { this.content.nativeElement; // Error! } // DO: Wait for content initialization ngAfterContentInit() { this.content.nativeElement; // Safe }
Remember: In interviews, focus on:
- Understanding content projection concepts
 - Implementation patterns
 - Performance implications
 - Testing strategies
 - Lifecycle hooks
 - Common pitfalls
 - Real-world use cases
 
Key points to emphasize:
- Component reusability
 - Template flexibility
 - Performance considerations
 - Content lifecycle
 - Testing approaches
 - Dynamic content handling
 - Best practices
 
Test Your Knowledge
Take a quick quiz to test your understanding of this topic.