Help us understand the problem. What is going on with this article?

formタグは入れ子にできない&その対処法

More than 1 year has passed since last update.

突然ですが、次のようなHTMLファイルをブラウザで開いてみましょう。

nested_form.html
<!DOCTYPE html>

<head></head>

<body>
  <form>
    <p>
      <input type='text'>
    </p>
    <form>
      <p>
        <input type='text'>
      </p>
    </form>
  </form>
</body>

開いたら開発者ツールでDOMをインスペクトしてみましょう。

なんと内側のformタグがいなくなってしまっています。

実はHTMLの仕様として、入れ子のformタグは許可されていません。(詳細な話はこちらにのっています→ html - formタグの入れ子とブラウザーの解釈 - スタック・オーバーフロー)

この仕様を知らなかったため、業務で開発しているWEBアプリにバグを入れてしまいました…。
なぜformがなくなってしまうのかわからずフロントエンドで使っているライブラリを疑ってみたり、ダミーのフォームを入れてみたり、いろいろと試行錯誤してずいぶん手間取ってしまいました…。

とはいえ、自分が実際そうしてしまったようにフォームの中にフォームを作りたくなる場合もあるかと思います。たとえば、次のような感じ?メッセージの一覧画面をイメージしてください。

<!DOCTYPE html>

<head></head>

<form>
  <ul>
    <li>
      <input type="checkbox">
      項目1
      <input type="button" value="アーカイブ">
      <form style="display: inline">
        <select>
          <option value="" selected disabled>削除理由を選択…</option>
          <option value="1">理由1</option>
          <option value="1">理由2</option>
        </select>
        <input type="submit" value="削除">
      </form>
    </li>

    <li>
      <input type="checkbox"> 
      項目2
      <input type="button" value="アーカイブ">
      <form style="display: inline">
        <select>
          <option value="" selected disabled>削除理由を選択…</option>
          <option value="1">理由1</option>
          <option value="1">理由2</option>
        </select>
        <input type="submit" value="削除">
      </form>
    </li>

    <li>
      <input type="checkbox"> 
      項目3
      <input type="button" value="アーカイブ">
      <form style="display: inline">
        <select>
          <option value="" selected disabled>削除理由を選択…</option>
          <option value="1">理由1</option>
          <option value="1">理由2</option>
        </select>
        <input type="submit" value="削除">
      </form>
    </li>
  </ul>
  <input type="submit" value="チェックボックスをつけたものをまとめてアーカイブ">
</form>

下の画像のように、リスト要素ひとつひとつについてフォームがあり、さらに外にリスト要素をまとめて操作できるフォームがあるといった具合。
sample.png

しかし、前述の通りformタグ内にformタグがあるという状態は許容されていないため、これではおかしくなってしまいます。

input要素は何もしなければ祖先要素のうち、一番近いフォームの部品として働くのですが、HTML5ではinput要素にformという属性があります。これを使えば、所属させたいフォームをつくるformタグの子孫にしなくてもよくなります。

<input type="text" form="form-form">
<form id="form-form"></form>

とすれば、一行目のテキストボックスは"#form-form"のフォームの部品となってくれます。

これがわかったうえで先程のメッセージ一覧画面をちゃんと動くように直してみましょう。

<!DOCTYPE html>

<head></head>

  <ul>
    <li>
      <input type="checkbox" form="bulk-archive">
      項目1
      <input type="button" value="アーカイブ">
      <form style="display: inline">
        <select>
          <option value="" selected disabled>削除理由を選択…</option>
          <option value="1">理由1</option>
          <option value="1">理由2</option>
        </select>
        <input type="submit" value="削除">
      </form>
    </li>

    <li>
      <input type="checkbox" form="bulk-archive">
      項目2
      <input type="button" value="アーカイブ">
      <form style="display: inline">
        <select>
          <option value="" selected disabled>削除理由を選択…</option>
          <option value="1">理由1</option>
          <option value="1">理由2</option>
        </select>
        <input type="submit" value="削除">
      </form>
    </li>

    <li>
      <input type="checkbox" form="bulk-archive">
      項目3
      <input type="button" value="アーカイブ">
      <form style="display: inline">
        <select>
          <option value="" selected disabled>削除理由を選択…</option>
          <option value="1">理由1</option>
          <option value="1">理由2</option>
        </select>
        <input type="submit" value="削除">
      </form>
    </li>
  </ul>

<form>
  <input id="bulk-archive" type="submit" value="チェックボックスをつけたものをまとめてアーカイブ">
</form>

メッセージをまとめて操作するフォームの中に各メッセージを操作するフォームがあるのではなく、フラットな構造になりました。これで、勝手にformタグがいなくなったりすることはありません!

ほかに「Ajaxを使う」といった解決法もありますが、HTMLだけで解決してしまったほうがシンプルかなーと思います。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした