Skip to content

[ivy rc4] new unbound (static) input handling breaks existing code and makes component lifecycle inconsistent #34227

Closed as not planned
@Phil147

Description

🐞 bug report

Affected Package

Is this a regression?

No.

Description

In the ivy compatibility docs you can find this important sentence about a change coming with v9/ivy:

Unbound inputs for directives (e.g. name in <my-comp name="">) are now set upon creation of the view, before change detection runs (previously, all inputs were set during change detection).

We ran into a lot of issues with this, e.g. when you use a ViewChild query in an input setter.
I created a really simple example showing the problem and that the same code works for v8 but not in v9 (couldn't reproduce it in stackblitz)
https://github.com/Phil147/unbound-input-problem-v8
https://github.com/Phil147/unbound-input-problem-v9

The example is very simplified and not best practice but imagine you want to call a function of another custom component you query here.
In the v9 repo you will get an error once you start the app with ng serve because the ViewChild query is not yet resolved and thus undefined.

With v8 this works fine because the inputs are set during first change detection and the ViewChild query was resolved (with static: true). With v9 this code breaks but only in the particular situation when the input is not used with a binding but with a static value. We only found this issue by accident because in our unit tests we typically used bindings, but one specific example in our documentation (of our component library) failed during runtime.
This is a very confusing behavior now that the timing changes depending on how the inputs are used in templates. For me it would make more sense to keep this consistent.

From what I found this change was made to get better performance because static inputs don't change and you can leave them out during change detection, which makes total sense.
I wonder if it might be possible to still use the information you gather about static attributes but run them together with all other inputs during the first change detection run and then ignore them instead of moving their calls before the change detection happens.

🔬 Minimal Reproduction

works fine:
https://github.com/Phil147/unbound-input-problem-v8
same code breaks in v9:
https://github.com/Phil147/unbound-input-problem-v9

🌍 Your Environment

Angular Version:

9.0.0-rc.4
Angular CLI: 9.0.0-rc.4
Node: 12.13.0
OS: darwin x64

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

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.900.0-rc.4
@angular-devkit/build-angular     0.900.0-rc.4
@angular-devkit/build-optimizer   0.900.0-rc.4
@angular-devkit/build-webpack     0.900.0-rc.4
@angular-devkit/core              9.0.0-rc.4
@angular-devkit/schematics        9.0.0-rc.4
@ngtools/webpack                  9.0.0-rc.4
@schematics/angular               9.0.0-rc.4
@schematics/update                0.900.0-rc.4
rxjs                              6.5.3
typescript                        3.6.4
webpack                           4.41.2

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions