Next.js中ShadCN Combobox表单提交传递planeId数据问题
解决ShadCN Combobox嵌入表单时提交planeId到FormData的问题
ShadCN的Combobox组件基于Command实现,不属于原生表单控件,直接给Combobox.Item加name/id不会被FormData捕获。核心思路是用隐藏的原生input同步选中的planeId,让表单提交时自动带上这个字段。
基础方案(无需额外依赖)
通过React状态管理选中的planeId,绑定到隐藏input的value上:
"use client"; import { useState } from "react"; import { Combobox } from "@/components/ui/combobox"; // 示例飞机数据 const planes = [ { id: "1", name: "波音737" }, { id: "2", name: "空客A320" }, { id: "3", name: "C919" }, ]; export default function PlaneForm() { const [selectedPlaneId, setSelectedPlaneId] = useState(""); const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => { e.preventDefault(); const formData = new FormData(e.currentTarget); console.log("FormData内容:", Object.fromEntries(formData)); }; return ( <form onSubmit={handleSubmit}> {/* 关键:隐藏input,name设为planeId,值同步选中项的ID */} <input type="hidden" name="planeId" value={selectedPlaneId} onChange={() => {}} // 避免React受控组件警告 /> <Combobox> <Combobox.Input placeholder="选择飞机" /> <Combobox.Content> {planes.map((plane) => ( <Combobox.Item key={plane.id} value={plane.id} onSelect={() => setSelectedPlaneId(plane.id)} > {plane.name} </Combobox.Item> ))} </Combobox.Content> </Combobox> {/* 其他表单字段示例 */} <div className="mt-4"> <label className="block mb-1">航班号</label> <input type="text" name="flightNumber" className="border rounded px-2 py-1" /> </div> <button type="submit" className="mt-4 bg-blue-500 text-white px-4 py-2 rounded"> 提交表单 </button> </form> ); }
React Hook Form方案(适合复杂表单)
如果项目用React Hook Form,可以通过setValue同步选中值到注册的隐藏input:
"use client"; import { useForm } from "react-hook-form"; import { Combobox } from "@/components/ui/combobox"; const planes = [ { id: "1", name: "波音737" }, { id: "2", name: "空客A320" }, { id: "3", name: "C919" }, ]; type FormValues = { planeId: string; flightNumber: string; }; export default function PlaneForm() { const { register, handleSubmit, setValue } = useForm<FormValues>(); const onSubmit = (data: FormValues) => { console.log("表单数据:", data); // 转成FormData的方式 const formData = new FormData(); formData.append("planeId", data.planeId); formData.append("flightNumber", data.flightNumber); console.log("FormData内容:", Object.fromEntries(formData)); }; return ( <form onSubmit={handleSubmit(onSubmit)}> {/* 注册隐藏input */} <input type="hidden" {...register("planeId")} /> <Combobox> <Combobox.Input placeholder="选择飞机" /> <Combobox.Content> {planes.map((plane) => ( <Combobox.Item key={plane.id} value={plane.id} onSelect={() => setValue("planeId", plane.id)} > {plane.name} </Combobox.Item> ))} </Combobox.Content> </Combobox> <div className="mt-4"> <label className="block mb-1">航班号</label> <input type="text" {...register("flightNumber")} className="border rounded px-2 py-1" /> </div> <button type="submit" className="mt-4 bg-blue-500 text-white px-4 py-2 rounded"> 提交表单 </button> </form> ); }
原理说明
- 隐藏input是原生表单控件,表单提交时会自动将其
name和value加入FormData。 - 通过
Combobox.Item的onSelect事件,将选中的飞机ID同步到隐藏input的value中,确保提交时数据一致。
内容的提问来源于stack exchange,提问作者Isman Irawan
相关产品推荐
相关产品推荐

