kobalte icon indicating copy to clipboard operation
kobalte copied to clipboard

controlled text field never updates if first controlled values is `undefined`

Open jcmonnin opened this issue 4 months ago • 5 comments

When having controlled TextField, it never updates if the value at construction time is undefined. I would expect that the controlled value is allowed to be initially undefined and update the text field content when it becomes a string. Both pairs of text fields in following example should be kept in sync:

https://stackblitz.com/edit/solidjs-templates-yxfy22g2

This regression was introduced in #9ccdc68.

	// Disable reactivity to only track controllability on first run
	// Our current implementation breaks with undefined (stops tracking controlled value)
	const initialValue = local.value;

	const [value, setValue] = createControllableSignal({
		value: () => (initialValue === undefined ? undefined : local.value ?? ""),
		defaultValue: () => local.defaultValue,
		onChange: (value) => local.onChange?.(value),
	});

It's not clear to me what this commit fixes, therefore not proposing a PR reverting it.

Would this work?

		value: () => local.value ?? "",

jcmonnin avatar Sep 01 '25 09:09 jcmonnin

Also a note that null value will work the way you intend.

Additionally, as someone who only transpiles to javascript, it's wild that it's normal to leave something uninitialized (or even accept a null) 😅.

shayanhabibi avatar Sep 01 '25 10:09 shayanhabibi

It's a bit strong to say it's "wild that it's normal to leave something uninitialized". I assumed that because the TypeScript definition allows for both string and undefined, but I realize not that the undefined comes just from the optional property, so it was indeed a misunderstanding on my side of the component's interface.

It's very common to have controlled value as undefined in a select when nothing is selected. I was coming from there, but I agree it doesn't make much sense for a TextField because when all the text is deleted, there is no way to make the distinction between empty string and undefined. I will make sure to avoid using a signal that may be undefined. Unfortunately TypeScript won't be able to help me there.

jcmonnin avatar Sep 01 '25 11:09 jcmonnin

I didn't close the issue before because I wasn't sure if this is a bug or not.

I think this should be considered as a bug. props of solidjs components should allow for passing constant values or signals without surprise for the user of the component. When value changes from undefined to a string it effecvely becomes a controlled text field. It's more idomatic for a solidjs component if it can accept a change anytime.

In case the value at construction time puts the component permanetly in a different mode, this should be documented.

null is a case I personally don't care since the component doesn't accept null according to documented types.

jcmonnin avatar Sep 01 '25 16:09 jcmonnin

Oh don’t misunderstand me, I understand it’s normal for it to be uninitialised. I’m just having a laugh to myself because I’m not used to dynamic languages, so the idea of something being uninitialised is alien.

That’s my own thing though. I do agree with you here.

At the very least, if this is a bug that is known, then it should be documented

On Tue, 2 Sep 2025 at 12:34 am, Jean-Claude Monnin @.***> wrote:

jcmonnin left a comment (kobaltedev/kobalte#627) https://github.com/kobaltedev/kobalte/issues/627#issuecomment-3242888030

I didn't close the issue before because I wasn't sure if this is a bug or not.

I think this should be considered as a bug. props of solidjs components should allow for passing constant values or signals without surprise for the user of the component. When value changes from undefined to a string it effecvely becomes a controlled text field. It's more idomatic for a solidjs component if it can accept a change anytime.

In case the value at construction time puts the component permanetly in a different mode, this should be documented.

null is a case I personally don't care since the component doesn't accept null according to documented types.

— Reply to this email directly, view it on GitHub https://github.com/kobaltedev/kobalte/issues/627#issuecomment-3242888030, or unsubscribe https://github.com/notifications/unsubscribe-auth/AN2EZW3646VO2BECK2SUAO33QRYQDAVCNFSM6AAAAACFJ3UWCWVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTENBSHA4DQMBTGA . You are receiving this because you commented.Message ID: @.***>

shayanhabibi avatar Sep 01 '25 23:09 shayanhabibi

Supporting undefined as is tricky since it's also used for "not controlled". I tried supporting it a while ago, will need to revisit. Otherwise will update types and docs to mention using null.

jer3m01 avatar Sep 16 '25 09:09 jer3m01