1

I have created a demo project: https://stackblitz.com/edit/angular-e6pqlb?file=src%2Fcontent-host%2Fcontent-host.component.ts

Please open above link and check console printed values to understand my point below.

So, if you check src/main.html, content projection is used.

input property called inputValue is provided from AppRootComponent to the projected content component ContentViewComponent.

<app-content-host>
  <app-content-view #testContent [inputValue]="inputValue"></app-content-view>
</app-content-host>

Projected component ContentViewComponent is having a simple paragraph inside its template

<p>{{ inputValue }}</p>

And I am trying to observe value inside paragraph using ContentChild and from direct DOM API.


export class ContentHostComponent implements AfterContentInit {
  @ContentChild('testContent', { read: ElementRef }) contentChild: ElementRef;

  ngAfterContentInit(): void {
    console.log(document.body.innerHTML);
    const innerHTML = this.contentChild.nativeElement.innerHTML;
    console.log('inner HTML inside ngAfterContentInit : ', innerHTML);
  }

  ngAfterContentChecked(): void {
    console.log(document.body.innerHTML);
    const innerHTML = this.contentChild.nativeElement.innerHTML;
    console.log('inner HTML inside ngAfterContentChecked : ', innerHTML);
  }
}

I am unable to understand behaviour of the ngAfterContentInit and ngAfterContentChecked.

What I had understood was: Once projected content is rendered fully (i.e. change detection ran and DOM and component class are in sync) then after ngAfterContentInit method will be called.

Which implies content inside paragraph should NOT be empty if accessed inside ngAfterContentInit method.

Which implies, the paragraph element in should have value testValue

But that is not the case. paragraph is loaded with empty value.

Also, the same thing is printed for the first ngAfterContentChecked method call.

Which confuses me more. because I though ngAfterContentChecked is called after change detection is completed and DOM view and component class are in sync.

So, After change detection is over, empty paragraph should be loaded with value received as input from AppRootComponent(means 'testValue').

But again that is not the case.

Finally, Paragraph is filled with value when ngAfterContentChecked is called second time.

So, how Angular behaves in ngAfterContentInit and ngAfterContentChecked? Where my understanding went wrong? Angular docs says below things:

ngAfterContentInit() -->
Respond after Angular projects external content into the component's view, or into the view that a directive is in.
See details and example in Responding to changes in content in this document.
ngAfterContentChecked -->
Respond after Angular checks the content projected into the directive or component.
See details and example in Responding to projected content changes in this document.

I could not find specific details about above observation.

Kavar Rushikesh
  • 143
  • 1
  • 10

2 Answers2

2

I'll try to sum it up for you:

AfterContentInit is a hook that will run only once : when the projected content is initialized.

@Component({
  selector: 'parent',
  standalone: true,
  template: '<ng-content></ng-content>',
})
class ParentComponent implements AfterContentInit {

  @ContentChild(ChildComponent) content:any;

  ngOnInit(): void {
    console.log('Not init yet:', this.content);
  }

  ngAfterContentInit(): void {
    console.log('content init:', this.content);
  }
}

AfterContentChecked is a hook that will run after the content has been checked (most of the time it's during a Change Detection cycle).

   ngAfterContentChecked(): void {
    console.log('child val: ', this.content.val);
  }

Check this small demo I wrote: Stackblitz

Matthieu Riegler
  • 31,918
  • 20
  • 95
  • 134
  • Is it safe to say that when ngAfterContentInit is called before change detection first cycle executed in content view? If yes, should this fact be documented? – Kavar Rushikesh Apr 04 '23 at 04:12
  • Ignore above comment. I could not edit within few minutes so can not edit that. Thanks for your efforts Matthieu. Is it safe to say that when ngAfterContentInit is called before change detection first cycle executed in content view? If yes, should this fact be documented? because by reading "fully initialised" it will create perception that "view is rendered and component and dom view are in sync". Is it? And is it that AfterContentChecked is called BEFORE change detection has run on content view? still term "after content checked" is not clear to me. – Kavar Rushikesh Apr 04 '23 at 04:25
  • Also I want to see the source code which will dissolve all my queries . Will you please share files or modules I can check in angular source code? – Kavar Rushikesh Apr 04 '23 at 04:52
  • Yes `ngAfterContentInit ` is called after the projected component's `ngOnInit` and CD hasn't run yet. To me "initialized" isn't the same as "rendered". Init doesn't mean rendered in angular. But that could be more explicit in the doc. About the `AfterContentChecked` I need to investigate more. I don't fully grasp why it runs befone `AfterviewChecked` in my example – Matthieu Riegler Apr 04 '23 at 13:33
  • Can some other experts help here? Should I directly jump to source code right now? – Kavar Rushikesh Apr 04 '23 at 14:06
0

the first time ngAfterContentChecked of ContentHostComponent is called, the ContentViewComponent view is not yet done initializing(only the content is projected) reason why it returns an empty paragraph. The second time ngAfterContentChecked of ContentHostComponent is called, this is after the ContentViewComponent View is initialized and checked.

Ariel
  • 69
  • 5