如何在表单验证失败时阻止shadcn/ui的Sheet组件关闭
shadcn/ui Sheet表单验证失败时阻止关闭的解决方案
问题背景
使用shadcn/ui的Sheet组件内嵌表单时,点击提交按钮后即便表单验证失败,Sheet仍会自动关闭,需要重新打开修正错误。现有代码中提交按钮被SheetClose包裹,导致无论验证结果如何都会触发Sheet关闭;尝试添加aria-errormessage、onError等属性无效。
原代码结构:
<Sheet> <SheetTrigger asChild>...</SheetTrigger> <SheetContent> <div className="grid gap-4 py-4"> <Form { ...form }> <form onSubmit={ form.handleSubmit(onSubmit) } className="w-full space-y-6"> ... <SheetFooter> <SheetClose asChild> <Button type="submit">Save changes</Button> </SheetClose> </SheetFooter> </form> </Form> </div> </SheetContent> </Sheet>
解决方法
方法1:通过Sheet状态手动控制关闭(推荐)
核心是取消SheetClose对提交按钮的包裹,仅在表单验证通过后手动调用关闭方法。
- 引入并使用
useDisclosure钩子管理Sheet状态:
import { useDisclosure } from '@/components/ui/use-disclosure'; const { open, onOpen, onClose } = useDisclosure();
- 修改Sheet绑定状态,并调整提交逻辑:
<Sheet open={open} onOpenChange={(newState) => { // 可选:处理状态变化逻辑 }}> <SheetTrigger asChild>...</SheetTrigger> <SheetContent> <div className="grid gap-4 py-4"> <Form { ...form }> <form onSubmit={ form.handleSubmit((validatedData) => { // 验证通过后执行提交逻辑 onSubmit(validatedData); // 手动关闭Sheet onClose(); }) } className="w-full space-y-6" > {/* 表单字段 */} ... <SheetFooter> {/* 直接使用提交按钮,不包裹SheetClose */} <Button type="submit">Save changes</Button> {/* 单独保留取消按钮用SheetClose */} <SheetClose asChild> <Button variant="secondary">Cancel</Button> </SheetClose> </SheetFooter> </form> </Form> </div> </SheetContent> </Sheet>
form.handleSubmit只会在验证通过时执行回调,此时才会调用onClose()关闭Sheet;验证失败时回调不触发,Sheet保持打开。
方法2:阻止SheetClose的默认行为(备选)
如果不想大幅修改结构,可在SheetClose上添加点击事件,检查表单错误后阻止关闭:
<SheetFooter> <SheetClose asChild onClick={(e) => { // 检查表单是否存在验证错误 if (Object.keys(form.formState.errors).length > 0) { e.preventDefault(); e.stopPropagation(); } }} > <Button type="submit">Save changes</Button> </SheetClose> </SheetFooter>
注意:需确保表单开启了实时验证,否则点击按钮时可能还未生成错误状态,导致判断失效。
内容的提问来源于stack exchange,提问作者Sounak Mandal
相关产品推荐
相关产品推荐

