Closed SaizDev closed 9 months ago
Hey! This is by design at the moment — it works like an HTML checkbox which works the same way, the only time a value is included in the form data and sent to the server is when the checkbox is checked, otherwise it is omitted 👍
What's the actual problem you're running into as a result? Open to making changes here for sure if there's a good reason to do so.
Hey! Thanks for such quick answer!
The problem comes when I want to retrieve the value of the input. I retrieve the value of the input automatically based on a config array previously generated. If the input does not appear, it throws an error. I found a workaround, but makes the code ugly and less reusable.
What would you suggest?
@SaizDev It looks like you're pulling data based on the name from the form element.
There's a couple of notes I have about what you've written:
form[field_name]
Using form[input.id]
doesn't work with multiple inputs with the same name as it produces a collection instead of a single element. Another thing is that you can run into weird issues when there are form fields with the same name as a property on the form (for example action
). When a field with tne name of action
is present form.action
no longer returns the value of the action
attribute but the element (or list of elements if there are multiple). Additionally, for something like a checkbox that value can change conditionally based on whether or not it's checked. It might be a string if unchecked and an element if checked.
The best thing to do here is use new FormData(form)
to get the form data which also helps clarify the intent. You can use Object.fromEntries(…)
and FormData#entries
to get the data into a JS object. Given that you've got a config array this code in your case might be a bit more complex but the idea is still similar:
const handleEdit = (e) => {
e.preventDefault();
let submitData = Object.fromEntries(new FormData(e.target).entries())
submitData['active'] ??= 'false' // your workaround
editAthlete({id, submitData})
navigate("/athletes")
}
In HTML you can have multiple inputs with the same name and in many cases servers will override the value for a given form field with whatever the "latest" value is (though this is not a given — some preserve all values but still in order). The Object.fromEntries
trick does the same thing here as well.
So, if you place a hidden input before the Headless UI switch — and it has the same name:
<form>
<input type="hidden" value="false" name="active" />
<Switch
name="active"
value="true"
>
<span className="sr-only">Is Active</span>
</Switch>
</form>
Coupled with the use of Object.fromEntries(…)
and FormData
you'll be able to remove your workaround.
const handleEdit = (e) => {
e.preventDefault();
let submitData = Object.fromEntries(new FormData(e.target).entries())
// no workaround :)
editAthlete({id, submitData})
navigate("/athletes")
}
reduce
This isn't directly related — I'd just like to share some knowledge here.
In a line like this:
config.reduce((o, input) => ({...o, [input.id]: 'value here'}), {})
This creates objects and copies over properties a lot more than necessary. For example, with an array of 1000 entries this creates 1000 additional objects and copies over properties more than 500k times. (1 on the first, 2 on the second, 3 on the 3rd, etc… up to 1000 on the 1000th item).
You can tweak it like so to keep it roughly the same length and while it still creates more objects than necessary it only copies over properties 1000 times — 1 copy per property:
config.reduce((o, input) => Object.assign(o, { [input.id]: 'value here' }), {})
Though, in a small or even semi-large list this isn't really a big deal. Just something to be aware of and figured I'd share :)
What component (if applicable)
Describe the bug When provided the switch component with a prop name, an input type hidden should appear. It only appears if the toggle is switched to on. The input dissappear when the toggle is off. https://headlessui.com/react/switch#using-with-html-forms
Expected behavior The input related to the toggle does not disappear when the toggle is off
Screenshots
Browser/Device (if applicable)