🎨
フォームタグ外に送信ボタンを切り分け
背景
一般的には form
タグ内に<button type="submit">
があるのが普通です。
でもデザインやコンポーネントの切り分け的に、どうしてもフォームタグ外に送信ボタンをおかなくてはいけないケースもあるかと思います。
react-hook-formのissuesでも上がってました。
Formタグ外に送信ボタン
<form id="applicationForm">
{/* フォーム内容 */}
</form>
<button type="submit" form="applicationForm">送信</button>
ボタンがフォームタグ外にあるにも関わらずきちんと動きます。
form
タグのid
と、button
タグのform
属性の名称が同じになることで関連付け されます。
実装例
react-hook-formを使用して、form
タグ内でなくモーダルコンポーネント内にボタンを置く
フォームコンポーネント
function ApplicationForm({id, setButtonState, onSubmit}) {
const { handleSubmit, formState } = useForm();
const { isValid } = formState
useEffect(() => {
setButtonState(() => !isValid)
}, [isValid])
//...
return (
<form id={id} onSubmit={handleSubmit(onSubmit)}>
{/* フォーム内容 */}
</form>
)
}
モーダルコンポーネント
function MyModal(() {
/** ボタンの状態管理 */
const [buttonState, setButtonState] = useState(true)
const handleSubmitForm = (data) => {
console.log(data);
}
//...
return(
<Modal>
<ModalContent>
<ApplicationForm
id="appForm" //関連付け
setButtonState={setButtonState}
onSubmit={handleSubmitForm} />
<Button
type="submit"
form="appForm" //関連付け
isDisabled={buttonState}>
編集
</Button>
</ModalContent>
</Modal>
)
}
フォームコンポーネントとモーダルコンポーネントで分けることでスッキリし、モーダルを汎用的に使用できます。
ボタンの活性状態も管理できます。
参考文献
How to submit the form outside the form
Submit button outside the form
Discussion
便利ですよね。ぼくも少しチャレンジしてデモを作ってみました。
コンポーネントに切り出したときは、親コンポーネントを
FormProvider
で包み込み、子コンポーネント内でuseFormContext
経由でサブスクするとフォームの状態を拾えます勉強になります!ありがとうございます!!