ngOnChanges does not fire before ngOnInit if input attributes are not present

🐞 bug report

Affected Package

@angular/core – Hook Lifecycle

Is this a regression?

Not sure if regression, but the documentation says clearly that ngOnChanges() - Called before ngOnInit() and whenever one or more data-bound input properties change.
https://angular.io/guide/lifecycle-hooks#!#hook-sequence

Description

If a component has @Input() defined, but the parent component does not set that input at all, ngOnChanges does not fire.

<my-hello></my-hello>
export class HelloComponent implements OnChanges  {
  @Input() text?: string;
  ngOnChanges(){
    console.log('changes'); // never happens
  }
}

🔬 Minimal Reproduction

https://stackblitz.com/edit/angular-ivy-dwzgjs?file=src%%2Fapp%%2Fhello.component.html

🌍 Your Environment

Angular Version:
Reproduced with 10.0.4, 10.0.9 and 9.1.6


Angular CLI: 10.0.4
Node: 12.16.0
OS: win32 x64

Angular: 10.0.5
... animations, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router
Ivy Workspace: Yes

Package                            Version
------------------------------------------------------------
@angular-devkit/architect          0.1000.0
@angular-devkit/build-angular      0.1000.4
@angular-devkit/build-optimizer    0.1000.4
@angular-devkit/build-webpack      0.1000.4
@angular-devkit/core               10.0.0
@angular-devkit/schematics         10.0.4
@angular/cdk                       10.1.0
@angular/cli                       10.0.4
@angular/flex-layout               10.0.0-beta.32
@angular/material                  10.1.0
@angular/material-moment-adapter   10.1.0
@ngtools/webpack                   10.0.4
@schematics/angular                10.0.4
@schematics/update                 0.1000.4
rxjs                               6.6.0
typescript                         3.9.7
webpack                            4.43.0

Anything else relevant?
<my-hello [text]></my-hello> also fails
<my-hello [text]="undefined"></my-hello> works as expected

1 possible answer(s) on “ngOnChanges does not fire before ngOnInit if input attributes are not present

  1. since your input was not changed

    Technically <my-hello [text]="undefined"></my-hello> also doesn’t change the input as it is undefined by default, but this triggers ngOnChanges

    But you are right, if I read the Purpose column in the docs it says when Angular sets or resets data-bound input properties
    I think this can be interpreted as “when your input ‘setter’ is called by data binding” it will trigger ngOnChanges.
    So yeah, not setting anything will not trigger it …

    I don’t know how many times I skimmed over this part over the years, and never fully got it :))
    I always looked at the Timing column and saw ngOnChanges() - Called before ngOnInit() / ngOnInit() - Called once, after the first ngOnChanges(). and I assumed ngOnChanges is always the first hook.

    I’ll add a small footnote in the docs to clear things up for others that might fall in the same trap as me.