仅选择一个选项时发送具有多选的数组
Send an array with multiselect when selected only one option
我使用 react-select 库来处理表单。
字段定义:
<AsyncSelect
isMulti={true}
defaultOptions
cacheOptions
onChange={handleSelectChange}
name={formData.name}
defaultValue={formData.defaultValue}
loadOptions={props.loadOptions}
/>
库使用输入字段来存储选定的值。
例如:
<input name="artists_ids" type="hidden" value="3f9da869-a230-4fc6-8012-40a5f06d694e">
<input name="artists_ids" type="hidden" value="d9741ab8-784e-45bf-af92-0416e97730da">
为了处理表单数据,我使用 FormData
对象:
const handleSubmit = (event: React.ChangeEvent<HTMLFormElement>) => {
event.preventDefault();
Router.post(props.routing, {body: new FormData(event.currentTarget)})
//...
})
API 仅限于获取 ID 数组。
当用户选择多个值时一切正常:
{
"artists_ids":["3f9da869-a230-4fc6-8012-40a5f06d694e","d9741ab8-784e-45bf-af92-0416e97730da"]
}
问题
当用户尝试仅发送一个选定值时,FormData
对象将数据转换为字符串而不是数组:
{
"artists_ids": "3f9da869-a230-4fc6-8012-40a5f06d694e"
}
无效的解决方案:
- 修改发送到服务器的
FormData
对象 - 我无法修改此对象
- 添加空输入以发送数组 - 对 API 的请求将失败
- 更改API以获取字符串或数组作为参数
问题
你知道如何在用户只选择一个字段的情况下发送数组吗?
我可能只是将 artist_ids
包装在一个数组中,因为它还不是一个数组。由于您在某种程度上受到 API 和通用 AddForm
函数的限制,因此解决方案可能涉及使该函数稍微更灵活一些。
考虑到这个目标,我会在您的 IFormComponentProps
界面中添加一个可选的 transform
功能。未定义时,将新的 transform
属性默认为恒等函数 ((x) => x
)。这确保 handleSubmit
将保持与现有形式的向后兼容。
在 AddForm
中,将 props.transform
应用于 Router.post
的 RequestInit
参数,如下所示:
export function AddForm(props: IFormComponentProps) {
const { transform = (x) => x } = props
// ...
const handleSubmit = (event: React.ChangeEvent<HTMLFormElement>) => {
event.preventDefault();
Router.post(props.routing, transform({body: new FormData(event.currentTarget)}))
// ...
}
因为 BodyInit
可以是一个字符串,你应该能够提供一个自定义函数,将你的 new FormData
转换成一个对象(artists_ids
强制成为一个数组),然后 JSON.stringify
那个对象,这样你最终调用 Router.post
与:
{
body: JSON.stringify(transformedFormDataObject),
headers: { 'Content-Type': 'application/json' }
}
这应该可以解决问题(如果 API 可以处理内容类型)并且应该给您更大的灵活性,如果您将来需要的话。
如果 API 无法处理内容类型,您需要在处理后将普通对象转换回新的 FormData
对象以确保 artists_ids
是一个数组(而不是 JSON.stringify
ing 它)。
我使用 react-select 库来处理表单。
字段定义:
<AsyncSelect
isMulti={true}
defaultOptions
cacheOptions
onChange={handleSelectChange}
name={formData.name}
defaultValue={formData.defaultValue}
loadOptions={props.loadOptions}
/>
库使用输入字段来存储选定的值。 例如:
<input name="artists_ids" type="hidden" value="3f9da869-a230-4fc6-8012-40a5f06d694e">
<input name="artists_ids" type="hidden" value="d9741ab8-784e-45bf-af92-0416e97730da">
为了处理表单数据,我使用 FormData
对象:
const handleSubmit = (event: React.ChangeEvent<HTMLFormElement>) => {
event.preventDefault();
Router.post(props.routing, {body: new FormData(event.currentTarget)})
//...
})
API 仅限于获取 ID 数组。
当用户选择多个值时一切正常:
{
"artists_ids":["3f9da869-a230-4fc6-8012-40a5f06d694e","d9741ab8-784e-45bf-af92-0416e97730da"]
}
问题
当用户尝试仅发送一个选定值时,FormData
对象将数据转换为字符串而不是数组:
{
"artists_ids": "3f9da869-a230-4fc6-8012-40a5f06d694e"
}
无效的解决方案:
- 修改发送到服务器的
FormData
对象 - 我无法修改此对象 - 添加空输入以发送数组 - 对 API 的请求将失败
- 更改API以获取字符串或数组作为参数
问题
你知道如何在用户只选择一个字段的情况下发送数组吗?
我可能只是将 artist_ids
包装在一个数组中,因为它还不是一个数组。由于您在某种程度上受到 API 和通用 AddForm
函数的限制,因此解决方案可能涉及使该函数稍微更灵活一些。
考虑到这个目标,我会在您的 IFormComponentProps
界面中添加一个可选的 transform
功能。未定义时,将新的 transform
属性默认为恒等函数 ((x) => x
)。这确保 handleSubmit
将保持与现有形式的向后兼容。
在 AddForm
中,将 props.transform
应用于 Router.post
的 RequestInit
参数,如下所示:
export function AddForm(props: IFormComponentProps) {
const { transform = (x) => x } = props
// ...
const handleSubmit = (event: React.ChangeEvent<HTMLFormElement>) => {
event.preventDefault();
Router.post(props.routing, transform({body: new FormData(event.currentTarget)}))
// ...
}
因为 BodyInit
可以是一个字符串,你应该能够提供一个自定义函数,将你的 new FormData
转换成一个对象(artists_ids
强制成为一个数组),然后 JSON.stringify
那个对象,这样你最终调用 Router.post
与:
{
body: JSON.stringify(transformedFormDataObject),
headers: { 'Content-Type': 'application/json' }
}
这应该可以解决问题(如果 API 可以处理内容类型)并且应该给您更大的灵活性,如果您将来需要的话。
如果 API 无法处理内容类型,您需要在处理后将普通对象转换回新的 FormData
对象以确保 artists_ids
是一个数组(而不是 JSON.stringify
ing 它)。