Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(angular): defer control value accessor write until after hydration #24401

Closed
wants to merge 2 commits into from

Conversation

sean-perkins
Copy link
Contributor

Pull request checklist

Please check if your PR fulfills the following requirements:

  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been reviewed and added / updated if needed (for bug fixes / features)
  • Build (npm run build) was run locally and any changes were pushed
  • Lint (npm run lint) has passed locally and any fixes were made for failures

Pull request type

Please check the type of change your PR introduces:

  • Bugfix
  • Feature
  • Code style update (formatting, renaming)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • Documentation content changes
  • Other (please describe):

What is the current behavior?

Stencil hydrated web components can delay the execution timing for the connectedCallback() on first initialization. This results in the Angular control value accessors writing the value to the element before it is initialized.

In the event of using Angular forms with a form control that has an existing value; this will mean that the control will be initialized without a value. The emitStyle() from our Ionic form controls will update the ion-item appearance, without the appropriate item-has-value class. Then, before attributeChangedCallback() is registered, the value will be assigned to the web component. This results in the inner control displaying with a value, but the side-effect behavior that ion-item is out of sync.

This wasn't an issue before angular/angular-cli@22e0208, as likely the connectedCallback behavior in Stencil was benefiting from the defect in Zone.js.

Issue Number: Resolves #23809

What is the new behavior?

The Ionic custom control value accessors will delay the writeValue operation (assigning the value to the element), until after both the custom element is defined and the componentOnReady life cycle method has completed.

This aligns the Ionic web components with native web component behavior that the operations will occur in this order for each initialization of the component:

  1. connectedCallback()
  2. controlValueAccessor.#writeValue()

Updates the removeEventListener implementation for Stencil hydrated web components to make use of the monkey-patch method, just as the addEventListener operates.

Does this introduce a breaking change?

  • Yes
  • No

Other information

@sean-perkins sean-perkins requested a review from a team as a code owner December 14, 2021 19:47
@github-actions github-actions bot added package: angular @ionic/angular package package: core @ionic/core package labels Dec 14, 2021
@github-actions github-actions bot removed the package: core @ionic/core package label Dec 14, 2021
@sean-perkins
Copy link
Contributor Author

Looks like ngModel implementation behaves differently than NgControl, with it's own set of oddities (angular/angular#14988).

Need to dig a little deeper to make this PR satisfy both requirements.

@sean-perkins
Copy link
Contributor Author

Discovered a flaw with this while triaging another issue and checking this fix against it.

The ngModel change, actually fixes an issue where form controls are emitting ionChange the 2nd+ time it's rendered (i.e. a datetime in an inline modal) when opened (#24452). This is because the value is now being assigned before the component fully mounts.

It however regresses the form control behavior to do what ngModel was previously doing; as the write value is deferred until after the component is mounted. This results in our @Listen callbacks for value change to fire and re-emit the same value as a change.

I need to dig further into this, it may be a race condition between web component initialization and when Angular decides to write the value prop.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
package: angular @ionic/angular package
Projects
None yet
Development

Successfully merging this pull request may close these issues.

bug: ion-label not floating inside ion-item with select input on ion-modal dialog
1 participant