BrightspaceUI / core

A collection of accessible, free, open-source web components for building Brightspace applications.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Setting "checked" property of d2l-input-checkbox after clicking the checkbox does not work.

alexli01 opened this issue · comments

I ran into this behavior but not sure if it is a bug or it is just by design.
Here is the setup.
I created a simple d2l-input-checkbox. And in a event listener of the "change" event, I always uncheck the checkbox by setting the "checked" property to false, so when the user clicks on the checkbox, the checkbox should always be unchecked. But it does not seem to work.
I tried the same setup on a native html checkbox, and I got it working.

I wrote a simple page to demo the behavior of both core and native checkboxes.

`

<script type="module"> import '../../demo/demo-page.js'; import '../input-checkbox.js'; import '../input-checkbox-spacer.js'; </script> <script> window.addEventListener('change', function(e) {
            if (e.target.id === 'core_checkbox') {
                console.log('You are cliking on Core Checkbox, but I will uncheck it regardless');
                document.getElementById('core_checkbox').checked = false;
            }

            if (e.target.id === 'native_checkbox') {
                console.log('You are cliking on Native Checkbox, but I will uncheck it regardless');
                document.getElementById('native_checkbox').checked = false;
            }
        })
    </script>
</head>
<body unresolved>
	<d2l-demo-page page-title="d2l-input-checkbox-set-checked-property">
		<h2>Setting checked property after clicking the checkbox</h2>
		<d2l-demo-snippet>
			<template>
				<d2l-input-checkbox id="core_checkbox" >Core Checkbox</d2l-input-checkbox>
                <input type="checkbox" id="native_checkbox" ><label>Native Checkbox</label></input>
			</template>
		</d2l-demo-snippet>
	</d2l-demo-page>
</body>
`

Hi Alex, thanks for raising this. I think it's a bit of a bug, and a bit by design.

What's happening is this:

  • Inside <d2l-input-checkbox>, there's just a native checkbox. So when you click that native checkbox, <d2l-input-checkbox> handles that event, sets its internal state to checked = true, then fires its own change event.
  • Note that at this point, the Lit element itself hasn't yet re-rendered -- the reason the checkbox is displaying checked is because that's the native checkbox itself doing it.
  • In your event handler you then set checked = false.
  • At this point, Lit's render() finally happens, except it notices that checked hasn't actually changed since the last time it rendered (it's still false), so it doesn't actually perform any updates.
  • This causes the internal native checkbox's visual state to be out of whack with the Lit wrapper.

I can think of a couple solutions for this:

  1. <d2l-input-checkbox> can defer firing the change event until it has actually re-rendered (using a setTimeout). That way your event handler will run after it has rendered in a "checked" state, you'll change it back to unchecked which will re-render again.
  2. You can do the same -- set it back to unchecked in a setTimeout. This isn't great since ideally things "just work" without setTimeout hacks.

I'll experiment with firing the event a bit later and if it doesn't break any tests in a scary way, I'll put up a PR.

One thing to note with those solutions -- it causes a "flicker" where the checkbox does appear checked and then unchecked. Is that OK in your situation?

The other possible solution here would be to just use a native checkbox and style it to look like ours.

Hi Dave, thank you for looking into this. We are actually currently using the native checkbox and styled it to look like the one in the core using the old vui-input stuff. But we want to migrate every thing to use d2l-core components and get rid of any old tech and keep everything in sync with the rest of the world, and that's what I have been doing in the last dragon slayer, then I ran into this issue.
I guess if there is no other better solution, then the "flicker" one doesn't sound too bad.

So the link I provided actually lets you use @brightspace-ui/core and doesn't have a requirement on vui-input or anything like that. It does however need to be used from a Lit element.

Awesome!!! I will just take that approach then!! Thanks Dave.

Ok I'm going to close this for now then. If it ultimately ends up being an issue somewhere else we can investigate further.