shoelace
shoelace copied to clipboard
<sl-input> 'invalid' property is updated after the 'sl-input' event is dispatched
Describe the bug
Checking the input.invalid property in a sl-input event handler does not always return the correct value, because internally the invalid property is updated after the event is dispatched.
To Reproduce
Use the following html:
<sl-input label="What is your name?" minlength=3></sl-input>
and JS:
let input = document.querySelector("sl-input");
input.addEventListener("sl-input", () => {
console.log(`Input value=${input.value} invalid=${input.invalid}`);
});
@claviska any hint on how to fix that?
A workaround looks like this:
let input = document.querySelector('#boom');
input.addEventListener('sl-input', async () => {
await input.updateComplete;
console.log(input.invalid);
});
This is a lifecycle issue and I'm debating a couple ways to solve it, as it isn't unique to <sl-input>
. One idea is to create a deferred emitter that waits until the update is complete before firing off the event. The question is should that be the default behavior for most/all events or not.
A proper fix for this requires more analysis and testing. Thanks for your patience!
This is a non-issue as of 2.0.0-beta.84 because the invalid
attribute has been removed. Instead, you should use the SlInput.checkValidity()
method, which works exactly like HTMLInputElement.checkValidity()
and always returns the current validity of the internal input.
This was a breaking change that applies to all form controls. In addition, the following validity "states" are applied to all form controls that allow you to customize them more like native form controls.
Learn more Custom Validation Styles on this page
An updated example would look like this:
<sl-input
label="Enter your name"
help-text="Check the console to see validity"
minlength="3"
></sl-input>
<script>
const input = document.querySelector('sl-input');
input.addEventListener('sl-input', () => {
console.log(`value: ${input.value}\ninvalid: ${!input.checkValidity()}`);
});
</script>
Thanks for the heads up!
Unfortunately it looks like the validation styles (data-user-* attributes) are not set properly. If you add a minlength = "8"
attribute to the example you'll see that it is considered valid from a styling point of view as soon as a character is typed in, even though checkValidity()
returns the expected value taking the constraints into account.
I opened https://github.com/shoelace-style/shoelace/issues/1063 as a follow-up
Thanks. One of the things on my list is to add tests for all those validation states for each form control. I was hoping to have them done already, but it was quite a chore to get everything updated and I ran out of time that day.
I'll take a look at this one tomorrow!