angular / components

Component infrastructure and Material Design components for Angular
https://material.angular.io
MIT License
24.32k stars 6.72k forks source link

bug(checkbox 15 (not legacy)): Checkbox "checked" not working properly after update to 15th version #26101

Closed Tilesto closed 1 year ago

Tilesto commented 1 year ago

Is this a regression?

The previous version in which this bug was not present was

14 (for 15 it's also working for legacy-checkbox)

Description

Checkbox changes own css-classes even if I have event.preventDefault() in (click) handler. The issue is only for the checkbox (15), not for legacy-checkbox.

It sounds like not a critical issue, but it causes big problems in complex cases (e.g., when I change checkbox state through a ConfirmationDialog). It looks like: [checked] attr is changing, but checkbox is not rerendering (and ChangeDetectorRef cannot help too)

Reproduction

Steps to reproduce:

  1. Create default app (Angular version - 15, AngularMaterial version - 15)
  2. Import "new" Checkbox import { MatCheckboxModule } from '@angular/material/checkbox';
  3. Set (click) handler with one line inside: event.preventDefault()
  4. Click on the checkbox

I created two sandboxes: First one - legacy-checkbox https://stackblitz.com/edit/components-issue-3657ht?file=src%2Fapp%2Fexample-component.ts Second - checkbox 15 https://stackblitz.com/edit/components-issue-wrcpmh?file=src%2Fapp%2Fexample-component.ts

Expected Behavior

Checkbox doesn't change self state (attr and styles/css-classes), if I have event.preventDefault()

Actual Behavior

Checkbox CHANGES css-classes (it's not okay), but doesn't change state (it's okay)

Also, I made videos Legacy https://user-images.githubusercontent.com/117910324/204268636-e51ac1c0-f971-4bf0-9759-9497c1c95543.mp4 15 https://user-images.githubusercontent.com/117910324/204268673-79fb902f-a36f-438e-bdd4-1d91a57ccdd5.mp4

Environment

Oledjio commented 1 year ago

same issue

crisbeto commented 1 year ago

This isn't something that we supported before either, it happened to work based on the old DOM structure. You should be able to achieve something similar by setting pointer-events: none on the checkbox.

Tilesto commented 1 year ago

@crisbeto but I need to have possibility to have (click) handler on it. It's not disabled.

mmalerba commented 1 year ago

Calling preventDefault on checkboxes causes strange behavior and is error prone and therefore shouldn't be done. This is something we call out in the migration guide for moving to MDC-based components: https://material.angular.io/guide/mdc-migration#checkbox

Here's an example demonstrating this strangeness (plain JS, no Angular to illustrate that this is not an Angular issue): https://jsfiddle.net/q4evac57/ You'll notice in the example that the checked value is not what you'd expect when the click fires. Furthermore if you try to set the checked value in the click handler it gets ignored.

The reason this used to work is that it only looked like you were clicking on the native checkbox element, but in reality you were clicking a div. With the new version we've changed it so you are actually clicking the native checkbox. I'd suggest changing your logic to not depend on preventDefault(), you could try instead binding a FormControl to the checkbox and updating the value of the FormControl in the click handler or wherever else you need.

angular-automatic-lock-bot[bot] commented 1 year ago

This issue has been automatically locked due to inactivity. Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.