Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
93
Help us understand the problem. What is going on with this article?
@k5trismegistus

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

More than 3 years have 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だけで解決してしまったほうがシンプルかなーと思います。

93
Help us understand the problem. What is going on with this article?
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.
Sign Up
If you already have a Qiita account Login
93
Help us understand the problem. What is going on with this article?