-
Notifications
You must be signed in to change notification settings - Fork 6.8k
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(slide-toggle): error when disabling while focused #12325
fix(slide-toggle): error when disabling while focused #12325
Conversation
src/lib/slide-toggle/slide-toggle.ts
Outdated
this.onTouched(); | ||
// Do not immediately mark the component as touched because it can happen that the `blur` | ||
// event from `FocusMonitor` fires, while the component is checked after a change detection. | ||
// Immediately updating would then result in a changed after checked exception. Rel: #12323 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't quite follow this scenario; what is it that's being updated after check?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling onTouched
updates the ContolValueAccessor
's state (which is basically the slide-toggle) and technically the associated control.
We could theoretically also check for NgControl
to be present, but I don't think it's worth having a condition here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still don't follow, though, what is triggering an update while/after change detection runs. Handling an event from the focus monitor should inherently happen in a separate tick, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's at least what I figured out from debugging:
- Underlying input element is focused
- Disabled binding is set --> Run change detection
- Update
disabled
property of underlying input (part of change detection) - Setting disabled on a native input element while focused causes a
blur
event to fire (not in the same tick --> so outside of the change detection - Angular checks for changes after the CD ran: Figures out that the
ng-untouched
class binding of the NgModel changed after the actual change detection ran. --> Error thrown!
The comment tries to shortly explain that general issue. From what it says, it's pretty much what happens in 5) and it's also referring to that specific GitHub issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I was missing the fact that setting an input to disabled
immediately fires a blur event. Found angular/angular#17793 that references this. I would phrase the comment as:
// When a focused element becomes disabled, the browser *immediately*
// fires a 'blur' event. Angular does not expect events to be raised during
// change detection, so any template state updates in response to 'blur'
// (such as a form control's 'ng-touched') will cause a changed-after-checked
// error. See https://github.com/angular/angular/issues/17793.
// To work around this, we defer telling the form control it has been touched
// until the next tick.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated. I didn't even start thinking about it potentially being an Angular issue.
* Fixes that Angular throws an `ExpressionChangedAfterItHasBeenCheckedError` when disabling the slide-toggle while the component has been focused. Fixes angular#12323
ce81d78
to
0eb5ec1
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Fixes Angular throwing an `ExpressionChangedAfterItHasBeenCheckedError` when disabling the slide-toggle while the component has been focused. Fixes #12323
Fixes Angular throwing an `ExpressionChangedAfterItHasBeenCheckedError` when disabling the slide-toggle while the component has been focused. Fixes #12323
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
ExpressionChangedAfterItHasBeenCheckedError
when disabling the slide-toggle while the component has been focused.Fixes #12323