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

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

ただいまの
回答率

87.34%

Java Spring BootでDropDownListの初期値をDBの値とする方法

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 4,591

score 9

SpringBootでHTMLにDBのテーブルデータを一覧表示しており
その中の列にDoropDownlistを置いて(データソースもDBからです)値を表示・選択しようとしているのですが
現状だとDoropDownlistの初期値がすべての行で先頭の値が指定されてる状態です。
これをDBの値と連動するにはどのようにすればよいのでしょうか?

発生している問題・エラーメッセージ

該当のソースコード

st_id Integer PRYMARYKEY
strength Text
package com.ncapl.pro;

import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class Test {

    @Autowired
    JdbcTemplate jdbcPostgres;

    @RequestMapping("/test")
    public String test(Model model) {
        List<Map<String,Object>> list;
        list = jdbcPostgres.queryForList("select * from t_strength");
        model.addAttribute("st_id", list);
        model.addAttribute("strength", list);
        return "test";
    }
}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>test</title>
    <link rel="stylesheet" type="text/css" href="master.css" />
</head>
<body>


<table id="strength" class="table table-striped table-bordered table-hover table-condensed">
      <tr>
        <th>No.</th>
        <th>列1</th>
      </tr>
 <tr th:each="strength : ${strength}">
            <td align="left" th:text="${strength.st_id}"></td>
             <td align="left">
             <div>
                <select id="st_id" name="strength">
                    <option th:each="strength : ${st_id}"
                            th:value="${strength.st_id}"
                            th:selected="${strength.st_id == st_id}"
                            th:inline="text">[[${strength.strength}]]
                    </option>
                </select>
                </div>
            </td>
 </tr>
</table>
</body>
</html>

試したこと

th:selected="${strength.st_id == st_id}"のように設定しても
テーブルの先頭の値が初期値になってしまいます。
イメージ説明

ご指摘のとおり重複IDを下記のとおり変更したところDBの初期値を表示させることが出来ました。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>test</title>
<link rel="stylesheet" type="text/css" href="master.css" />
</head>
<body>
    <table id="t_strength"
        class="table table-striped table-bordered table-hover table-condensed">
        <tr>
            <th>No.</th>
            <th>列1</th>
        </tr>
        <tr th:each="strength : ${strength}">
            <td align="left" th:text="${strength.st_id}"></td>
            <td align="left">
                <div>
                    <select id="st_Id" name="Strength">
                        <option th:each="Strength : ${st_id}" th:value="${strength.st_id}"
                            th:selected="${strength.st_id == st_Id}" th:inline="text">[[${strength.strength}]]
                        </option>
                    </select>
                </div>
            </td>
        </tr>
    </table>
</body>
</html>


しかし、ドロップダウンすると以下のようにその値一色(リスト内が同じ値)になってしまいます。
イメージ説明
表示(初期値)は現在のDBの値とするけれど、変更可能なようにドロップダウン自体リスト表示は可能でしょうか?

補足情報(FW/ツールのバージョンなど)

java spring boot
IDE:eclipse 2019-06
DB:postgresql 11

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

+1

見た感じループの中で変数上書きしてませんか?(Javaでそれができるとは思えないけど・・)
strength 、st_id などぱっと見、今Listなのか値なのか見分けがつきません。
th:selectedの構文自体は合ってるように見えますので、きちんと想定通りの値がきていないだけにも思います。
※念のため、ブラウザの「ソースを表示」からHTMLがどうなってるか確認してください

蛇足:

<select id="st_id" name="strength">

ループの中でこれだと同じページに重複IDができてしまうことになるのでこれはHTML的にNGです。
IDは一意の名前をそれぞれつけましょう。
あとnameも同じだと1つしか送信されなくなります。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/07/30 12:59

    質問にコードを追記してください。

    キャンセル

  • この投稿は削除されました

  • 2019/07/30 13:50

    投稿編集についてはteratailのバグもあるようですので、何度かやってみてください。
    コメント欄ではマークダウン利用できませんし、インデントもきかないのでコードの把握が簡単ではないので

    キャンセル

checkベストアンサー

0

直接の回答にはなりませんが、こう書くこともできるという1例で参考になれば幸いです。

サンプルコード

コントローラー

@GetMapping(value = "list")
public String list(Model model) {
    // optionのマスタデータを想定
    Map<String ,String> options = new TreeMap<>();
    options.put("18", "【18】");
    options.put("21", "【21】");
    options.put("24", "【24】");
    options.put("27", "【27】");
    options.put("30", "【30】");
    options.put("33", "【33】");
    options.put("36", "【36】");
    options.put("40", "【40】");
    model.addAttribute("options", options);

    // DBのデータを想定
    List<Map<String, Object>> list = new ArrayList<>();
    list.add(createItem(1, "18"));
    list.add(createItem(2, "18"));
    list.add(createItem(3, "21"));
    list.add(createItem(4, "40"));
    list.add(createItem(5, "27"));
    list.add(createItem(6, "24"));
    list.add(createItem(7, "33"));
    list.add(createItem(8, "36"));
    list.add(createItem(9, "30"));
    model.addAttribute("strengthList", list);

    return "list";
}

private Map<String, Object> createItem(int id, String strength) {
    Map<String, Object> item = new HashMap<>();
    item.put("st_id", Integer.valueOf(id));
    item.put("strength", strength);
    return item;
}

テンプレート

<table>
  <tr>
    <th>No.</th>
    <th>列1</th>
  </tr>
  <tr th:each="strength : ${strengthList}">
    <td align="left" th:text="|${strength.st_id} (${strength.strength})|"></td>
    <td align="left">
      <select name="strength">
        <option th:each="option : ${options}"
                th:value="${option.key}"
                th:text="${option.value}"
                th:selected="${strength.strength} == ${option.key}"></option>
      </select>
    </td>
  </tr>
</table>

表示されるページ

イメージ説明

解説

それぞれのselect要素を描画するためのマスタデータとしてコントローラで以下のMapにデータを用意します。

Map<String ,String> options = new TreeMap<>();
options.put("18", "【18】");
options.put("21", "【21】");
options.put("24", "【24】");
// ...省略...

このMapを使ってselect要素を描画します。描画結果のhtmlは以下の通りです。Mapのキーがoption要素のvalueになり、Mapの値がoption要素のテキストとして使われます。

<select name="strength">
    <option value="18">【18】</option>
    <option value="21">【21】</option>
    <option value="24">【24】</option>
    <option value="27">【27】</option>
    <option value="30">【30】</option>
    <option value="33">【33】</option>
    <option value="36">【36】</option>
    <option value="40">【40】</option>
</select>

テーブルの描画

テーブルの行を描画するためのデータとしてコントローラで以下のListにデータを用意します。

List<Map<String, Object>> list = new ArrayList<>();
list.add(createItem(1, "18"));
list.add(createItem(2, "18"));
// ... 省略 ...

このListのデータは以下のようなテーブルからデータを取得したという想定です。

+-----+--------+
|st_id|strength|
+-----+--------+
|1    |18      |
|2    |18      |
|3    |21      |
|4    |40      |
|5    |27      |
|6    |24      |
|7    |33      |
|8    |36      |
|9    |30      |
+-----+--------+

描画されるtr要素は以下の通りです。
No.列のテキストはデバッグしやすいように"st_id (strength)"というフォーマットで表示しています。
この行はst_idが1、strengthが"18"のデータを表示しているということがわかります。

<tr>
    <td align="left">1 (18)</td>
    <td align="left">
      <select name="strength">
        <option value="18" selected="selected">【18】</option>
        <option value="21">【21】</option>
        <option value="24">【24】</option>
        <option value="27">【27】</option>
        <option value="30">【30】</option>
        <option value="33">【33】</option>
        <option value="36">【36】</option>
        <option value="40">【40】</option>
      </select>
    </td>
</tr>

この行のstrengthが"18"のとき、option要素の"18"を初期表示にしたいのであれば、th:selectedで比較するのは
行のデータを保持するstrength変数のstrengthとoption要素のデータを保持するoption変数のkey(htmlでいえばoptionのvalue)ということになります。

th:selected="${strength.strength} == ${option.key}"

質問文のコードではstrengthという変数が多用されているので分かりずらいコードになっていると思いました。
変数名の付け方を工夫することで分かりやすくなると思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

  • ただいまの回答率 87.34%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

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