質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.50%

  • JavaScript

    19286questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • Java

    15324questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • Spring

    801questions

    Spring Framework は、Javaプラットフォーム向けのオープンソースアプリケーションフレームワークです。 Java Platform上に、 Web ベースのアプリケーションを設計するための拡張機能が数多く用意されています。

  • Thymeleaf

    186questions

    Thymeleaf(タイムリーフ)とは、Java用のテンプレートエンジンで、特定のフレームワークに依存せず使用することが可能です。

[Spring Boot+thymleaf] jsで動的に追加したinput要素のPOSTができない

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 125

前提・実現したいこと

プログラミング全般暦の浅い初心者です。
備品管理システムのようなWEBアプリケーションを開発しています。

貸し出し画面にて
Formに入力する項目は
・userId
・itemId
・testNo
・date(hidden)
ですが、testNoは複数登録する場合もありJsでテキストボックスを増やせるようにしています。
(testNoはList<TestNoList>のフィールドtestNo)

その後コントローラーにPOSTしてDBの処理をしますが
testNoの数分の登録をします。(testNo以外のデータ同じデータが複数できる)

その際Jsで動的に増やした分の情報がPOSTされず
もともとあったtextboxに入力した1件ぶんしかPOSTされていません。

どうしたらコントローラーにすべてのtestNoをPOSTすることができるでしょうか?

※入力フォームをなぜかテーブルで作ってしまっているのはスルーしてください・・・
多分影響はないと思いますが・・・
※該当箇所以外は省略させてください。

・spring boot
・javaScript
・HTML
・thymleaf

該当のソースコード

var input_count = 0;
function add() {
 input_count = input_count +1 ;

 var ele = document.createElement("div");
 ele.innerHTML = "<input type='text' name='testNoList[" + input_count + "].testNo' th:field='*{testNoList[" + input_count + "].testNo}'>";

 var parent_object = document.getElementById("piyo");
 parent_object.appendChild(ele);
}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">

        <link href="/css/Style.css" th:href="@{/css/Style.css}" rel="stylesheet"></link>
        <script src="/js/use.js" th:src="@{/js/use.js}"></script>

        <title>利用開始</title>

    </head>

    <body>

        <table>
            <form name= form1 action="#" method="post" th:action= "@{/Use/submit}" th:object= "${historyForm}">
                <tr>
                    ~userId の入力テキストボックス
                </tr>

                <tr>
                            ~itemID の入力テキストボックス

                </tr> 


                <tr id="testNo_input">
                    <th class="login_field">テストコード                        <a href="javascript: void(0);" onclick="add();" tabIndex=-1> +追加</a>
                    </th>
                    <td>
                        <input type="text" id="testNo[0]" th:name="testNoList[0].testNo" onkeyup="fieldChanged();" onchange="fieldChanged();" th:field="*{testNoList[0].testNo}"></input>
                        <div id="piyo"></div>
                    </td>
                </tr>


                <tr>
                      ~date の入力テキストボックス    
                </tr>

                <tr>
                    <td colspan="2">
                    <br>
                        <input type="submit" value="この内容で登録する" id="submit">
                    </td>
                </tr>

            </form>
        </table>
    </body>
</html>
package springbootapp.form;

import java.io.Serializable;
import java.util.List;

import javax.validation.constraints.NotNull;

import lombok.Data;

@Data
public class HistoryForm implements Serializable {

  private static final long serialVersionUID = 1L;

  @NotNull
  private String userId;

  @NotNull
  private String itemId;

  private List<TestNoList> testNoList;

  @NotNull
  private String date;


    @Data
    public static class TestNoList implements Serializable {
        private String testNo;
    }
}
@RequestMapping(value = "Use/submit", method = RequestMethod.POST)
    public ModelAndView create(@Valid @ModelAttribute HistoryForm historyForm,ModelAndView mv,Model model) {

        for(int n=0; n<=historyForm.getTestNoList().size() -1; n++) {
            ~~処理        
         }


        return mv;
    }

試したこと

testNoを配列型にしてみたり
String[] testNo;

jsで作成するInnerHTMLをいろいろといじってはみましたが
(th:fieldをなくしてみたり足してみたり)
どうやっても最初の要素(0番目)しかPOSTできていないようです。

jsで動的に追加された要素がFormタグの外側だとPOSTされない
という記事もみましたので
F12の管理者ツールでDOM Explorerをみたところ、きちんとFormタグの中には入っていました。

何日も詰まってしまっています。。。
助けてください

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • yu-smc

    2019/03/07 11:34

    環境はInternet Explorerですか?
    全てのブラウザでPOSTされない状況でしょうか。

    キャンセル

  • kirby_candypop

    2019/03/07 11:39

    Internet Explorerです。
    念のためChromeでは確認しましたが同じように1件しかPOSTされませんでした。

    キャンセル

  • yu-smc

    2019/03/07 11:51

    IEだけとなるともしかすると、と思ったのですが、Chromeでも同じとなるとちょっとわからないですね。。
    時間見つけてまた考えてみます。

    キャンセル

  • kirby_candypop

    2019/03/07 12:00

    すいません。ありがとうございました!

    キャンセル

回答 1

checkベストアンサー

+2

thymeleafを使って作成したテンプレートファイル(*.html)はサーバーサイドでレンダリングされた後、ブラウザで表示されます。
ブラウザに表示されたページのソースコードを見てみるとth:textth:actionといったthymeleafの属性は消えていることが確認できると思います。
なのでJavaScriptを使って動的に追加する要素にth:fieldのようなthymeleafの属性を付けても動作しません。

テンプレートの下記の行が最終的にどのようなhtmlになっているか確認し、これと同じようなinputタグをJavascriptで組み立ててください。

<input type="text" id="testNo[0]" th:name="testNoList[0].testNo" onkeyup="fieldChanged();" onchange="fieldChanged();" th:field="*{testNoList[0].testNo}"></input>

追記 2019/03/14

少し調べてみましたが、Spring Bootやthymeleafの問題というよりもhtmlとJavaScriptの書き方の方に原因があったようです。
下記のようにhtmlとJavaScriptの書き方を変えれば配列を送信できました。
大きな変更点はtableタグの位置です。今まではformタグの外側にありましたが、それをformタグの内側へ移動させています。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>利用開始</title>
    <script type="text/javascript">
        function add() {
            var inputCount = document.getElementsByClassName("testNo").length;
            var input = document.createElement("input");
            input.setAttribute("type", "text");
            input.setAttribute("id", "testNoList" + inputCount + ".testNo");
            input.setAttribute("class", "testNo");
            input.setAttribute("name", "testNoList[" + inputCount + "].testNo")
            input.setAttribute("value", "");
            var ele = document.createElement("div");
            ele.appendChild(document.createTextNode(inputCount + ". "));
            ele.appendChild(input);
            document.getElementById("piyo").appendChild(ele);
        }
    </script>
</head>
<body>
<form name="form1" action="#" method="post" th:action="@{/Use/submit}" th:object="${historyForm}">
    <table>
        <tr>
            <td>~userId の入力テキストボックス</td>
            <td>
                <input type="text" th:field="*{userId}"/>
            </td>
        </tr>
        <tr>
            <td>~itemID の入力テキストボックス</td>
            <td>
                <input type="text" th:field="*{itemId}"/>
            </td>
        </tr>
        <tr id="testNo_input">
            <td class="login_field">テストコード <a href="#" id="addInput" tabIndex="-1">+追加</a></td>
            <td>
                <div>
                    0. <input class="testNo" type="text" th:field="*{testNoList[0].testNo}"/>
                </div>
                <div id="piyo"></div>
            </td>
        </tr>
        <tr>
            <td>~date の入力テキストボックス</td>
            <td>
                <input type="text" th:field="*{date}"/>
            </td>
        </tr>
        <tr>
            <td colspan="2">
                <input type="submit" value="この内容で登録する" id="submit">
            </td>
        </tr>
    </table>
</form>
<script type="text/javascript">
    document.getElementById("addInput").addEventListener("click", function (e) {
        add();
    }, false);
</script>
</body>
</html>

Java(Spring Boot)側のコードは修正していませんが、確認用に下記のコードを追記しています。

@PostMapping("Use/submit")
public ModelAndView create(@Valid @ModelAttribute HistoryForm historyForm, ModelAndView mv) {
    System.out.println(historyForm);
    System.out.println("size:" + historyForm.getTestNoList().size());
    historyForm.getTestNoList().forEach(a -> System.out.println("testNo:" + a.getTestNo()));
    mv.setViewName("history_confirm");
    return mv;
}

この状態で動かしてみると
イメージ説明

コンソールには以下の内容が出力されます。

HistoryForm(userId=100, itemId=101, testNoList=[HistoryForm.TestNoList(testNo=a), HistoryForm.TestNoList(testNo=bb), HistoryForm.TestNoList(testNo=ccc), HistoryForm.TestNoList(testNo=dddd), HistoryForm.TestNoList(testNo=eeeee), HistoryForm.TestNoList(testNo=ffffff)], date=103)
size:6
testNo:a
testNo:bb
testNo:ccc
testNo:dddd
testNo:eeeee
testNo:ffffff

以上ご確認ください。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/03/14 09:24 編集

    ご回答ありがとうございます。
    DOM Explorerで確認したところ、

    <input name="testNoList[0].testNo" id="testNo[0]" onkeyup="fieldChanged();" onchange="fieldChanged();" type="text" value="">

    となっていましたので
    jsを下記のように編集しました

    ele.innerHTML = "<td><input type='text' id='testNo[" + input_count + "]' name='testNoList[" + input_count + "].testNo' onkeyup='fieldChanged();' onchange='fieldChanged();' value=''></td>";

    これによって生成されるHTMLは

    <input name="testNoList[1].testNo" id="testNo[1]" onkeyup="fieldChanged();" onchange="fieldChanged();" type="text" value="">

    こちらです。
    しかしこれでもうまくいかず、POSTされたtestNoList.size()は1になってしまいます。

    キャンセル

  • 2019/03/15 09:29

    やりたかったことができました!!!
    関係ないとおもっていたTableタグがいけなかったんですね。。。
    レイアウトは後で直そうと思っていたのもよくなかったようです。
    詳しいご回答本当にありがとうございました!

    キャンセル

同じタグがついた質問を見る

  • JavaScript

    19286questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • Java

    15324questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • Spring

    801questions

    Spring Framework は、Javaプラットフォーム向けのオープンソースアプリケーションフレームワークです。 Java Platform上に、 Web ベースのアプリケーションを設計するための拡張機能が数多く用意されています。

  • Thymeleaf

    186questions

    Thymeleaf(タイムリーフ)とは、Java用のテンプレートエンジンで、特定のフレームワークに依存せず使用することが可能です。