-
Notifications
You must be signed in to change notification settings - Fork 787
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
bug/question: ref element validity is not up-to-date on Prop Watch trigger #5965
Comments
Thanks for raising the issue @dpellier the Stencil team currently has a lot of competing priorities and can't promise to be able to take a look at this anytime soon. We recommend to get involved and help us resolve this bug by providing a pull request with a fix. We are happy to provide necessary guidance and appreciate any help! |
@dpellier I have understood the problem here, but when you link a @prop to an element, you are re-rendering it every time, and I think that's not what you want. Try this approch, just rely on the native import { AttachInternals, Component, Host, Method, Prop, Watch, h, State } from '@stencil/core';
@Component({
formAssociated: true,
shadow: true,
tag: 'my-component',
})
export class MyComponent {
private inputElement?: HTMLInputElement;
@AttachInternals() private internals!: ElementInternals;
@Method()
reset() {
this.inputElement.value = null;
// Directly acting on element value does not trigger the event automatically, so dispatch it yourself
this.inputElement.dispatchEvent(new Event('input', { bubbles: true }));
}
private onInput(): void {
// Do what you want here. Assign the value to a local variable if needed.
console.log('onInput, isValid?', this.inputElement.validity.valid);
}
render() {
return (
<Host>
<input
onInput={(): void => this.onInput()}
ref={(el): HTMLInputElement => (this.inputElement = el as HTMLInputElement)}
required={true}
type="text"
></input>
</Host>
);
}
} |
@dpellier I think your problem comes from understanding the stencil life cycle. In the Your validity status will not be invalidated until after the render. To reset the current input value, simply proceed as follows: import { AttachInternals, Component, Host, Method, Prop, Watch, h } from '@stencil/core';
@Component({
formAssociated: true,
shadow: true,
tag: 'my-component',
})
export class MyComponent {
private inputElement?: HTMLInputElement;
@AttachInternals() private internals!: ElementInternals;
@Prop({ mutable: true, reflect: true }) public value: string = null;
@Method()
reset() {
if (this.inputElement) {
this.inputElement.value = null;
}
this.value = null;
}
@Watch('value')
onValueChange(): void {
console.log('onWatch, isValid?', this.inputElement.validity.valid);
}
private onInput(): void {
this.value = this.inputElement?.value ?? null;
}
render() {
return (
<Host>
<input
onInput={ (): void => this.onInput() }
ref={ (el): HTMLInputElement => this.inputElement = el as HTMLInputElement }
required={ true }
type="text"
value={ this.value || '' }>
</input>
</Host>
);
}
} And that will solve your problem. |
Prerequisites
Stencil Version
4.21
Current Behavior
We are implementing form elements components using ElementInternals.
On our component value change, we want to update the internals validity to match the validity of the native form element embedded.
Using this kind of setup:
This does work fine when the trigger comes from a change on the form element directly (like an
onInput
callback), but not when the Prop value of the component change, unless we delay it using a setTimeout 0.(see example below and repro code repo)
Expected Behavior
I can guess why this behaviour is actually happening as the Watch trigger in the case of Prop change does not care about waiting for other DOM changes to occurs.
But I'm not sure the setTimeout 0 is the best way to handle this.
Do you have any best practices about how to sync the internals validity without using such hack?
Or is it something that can actually be fixed on the Watch side?
System Info
Steps to Reproduce
Using a basic input component (or clone https://github.com/dpellier/stencil-set-validity-issue):
Run the example of the component with a reset button and check the console.log
NB: the reset Method is just an example, other usage can be problematic, like global form reset:
Code Reproduction URL
https://github.com/dpellier/stencil-set-validity-issue
Additional Information
No response
The text was updated successfully, but these errors were encountered: