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

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

ただいまの
回答率

88.04%

javascriptで動的にテーブルを作成したい

解決済

回答 2

投稿

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

score 74

前提・実現したいこと

javaのcontrolelrからjavascriptにデータを渡して、動的にtableを生成したいのですが、
javascriptでtableの行を生成するfor文の部分で無限ループになってしまい、上手くいきません
おそらくfor文のtbody.rows.lengthの部分がおかしいと思うのですが
ご教授いただければと思います。

該当のソースコード

/**
 * 基本給登録ページ
 */
function monthsSelect(obj){
    var objVar = obj.value;
    $.ajax({
        type : "GET",
        url : "baseSalaryMonth",
        data: {
            baseSalaryMonthStr: objVar
            },
        dataType : "json"
    })
    .then(
            function (data) {
                //tableの生成
                  var tbody = document.getElementById('table');
                  var row = document.createElement("tr");//trを生成
                  var thId = document.createElement("th");//thを生成
                  var thNm = document.createElement("th");//thを生成
                  var thBa = document.createElement("th");//thを生成
                  //ユーザIDヘッダ
                  thId.id="userId";
                  thId.innerHTML="ユーザID";
                  row.appendChild(thId);
                  //ユーザ名ヘッダ
                  thNm.id="fullNm";
                  thNm.innerHTML="ユーザ名";
                  row.appendChild(thNm);
                  //基本給ヘッダ
                  thBa.id="baseSalary";
                  thBa.innerHTML="基本給";
                  row.appendChild(thBa);
                  tbody.append(row);
                  for (i = 0; i < tbody.rows.length; i++){
                      var tr = document.createElement("tr");
                      //列(td)用のループ
                      for (j = 0; j < 5; j++){
                          //tdエレメントをを生成
                          var td = document.createElement("td");
                          td.innerHTML = 'こんにちは' + j;
                          tbody.appendChild(td);
                      }
                      tbody.append(tr);
                  }
            },
            function () {
                //通信失敗
                alert("読み込み失敗");
            });
}
    @RequestMapping(value = "/baseSalaryMonth" , method = RequestMethod.GET)
    @ResponseBody
    public List<BaseSalary> baseSalarySelectMonth(String baseSalaryMonthStr, ModelAndView mav)throws JsonParseException, JsonMappingException, IOException{
        System.out.println(baseSalaryMonthStr);
        int aseSalaryMonth = Integer.parseInt(baseSalaryMonthStr);
        List<BaseSalary> baseSalaryList = baseSalaryService.baseSalary(aseSalaryMonth);
        return baseSalaryList;
    }
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org"
    xmlns:sec="http://www.thymeleaf.org/extras/spring-security4">
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="/js/sampleJs.js" th:src="@{/js/baseSalary.js}"></script>
</head>
<body>
<h1>基本給登録ページ</h1>
    <form method="post" th:action="@{/base_salary_upd}">
        <select id="getMonthsSelect" name="getMonthsSelect" onChange="monthsSelect(this)">
        <option th:each="item : ${getMonthsSelect}"
            th:value="${item.key}"
            th:text="${item.value}">singleSelect</option>
        </select><br>
        </form>
    <table id="table"></table>
</body>
</html>

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

java8
SpringBoot2.0
jquery1.9.1

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • yambejp

    2018/12/07 18:56

    javaは具体的にはどういうjsonを返しているのでしょうか?

    キャンセル

  • takahiro00

    2018/12/07 19:07

    javaはlist型のデータを返しています。

    キャンセル

  • takahiro00

    2018/12/07 19:08

    tableに書き込む内容は一旦、こんにちわにしています。とりあえずデータの数だけ「こんにちわ」が表示できればと思っております。

    キャンセル

  • yambejp

    2018/12/07 19:14

    javaはlist型のデータを返しています。 ・・・いや、jsでdataTypeをjsonにしているのでエラーでない限りjsonデータを返してくれているのはわかっているのですが、具体的なデータがないと検証できないといいたいだけです。サンプルが提示できないならこれ以上の回答は望めないと思ったほうがよいでしょう

    キャンセル

回答 2

+3

for (i = 0; i < tbody.rows.length; i++){
}

無限ループになって困っているそうですが、
この書き方はtbody.rows.lengthがInfinifyでなければ確実に終了する極めてセーフティな書き方です。
であれば、全体的にDOM作る箇所、レンダリング周りが愚鈍でCPU使用率が100%振り切って応答しなくなってるだけでしょう。

ブラウザのテーブルはデフォルトでtable-layout: auto;というCSSが効いており、
テーブルの中身に従って各カラムの横幅が自動調整になるようです。
数十行ならまだ何とかなるでしょうけど、100を超えると最新のブラウザでも悲鳴を上げる事態になりそうです。

一度<table style="table-layout: fixed;">を指定してみてください。
横幅の自動調整がなくなるので各横幅はきちんと定義する事になりますが、レンダリングが格段に速くなるはずです。

また、DOMを1個ずつ掴んで挿入というのもコストがでかいので、
var tmp += "<tr><td>value1</td><td>value2</td>...</tr>";みたいな感じで文字列でくっつけまくって、最終的にtable.innerHTML = tmp;等として一撃でぶちこんでレンダリングの手間を最小にしてあげるとパフォーマンス的に許容範囲に収まるんじゃないかと思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/12/07 20:24

    ご回答ありがとうございます。
    tbody.rows.lengthによる無限ループではなかったのですね

    キャンセル

checkベストアンサー

+1

とりあえず

function monthsSelect(obj){
    var objVar = obj.value;
    $.ajax({
        type : "GET",
        url : "baseSalaryMonth",
        data: {
            baseSalaryMonthStr: objVar
            },
        dataType : "text"
    }).done(function (data) {
        console.log(data);
    }).fail(function(xhr,err){
        console.log(err);
    });
}


で、受け取ったdataを提示して下さい。まずはそこから

ajax

<script>
function monthsSelect(obj){
  var objVar = obj.value;
  $.ajax({
    "type"     : "GET",
    "url"      : "baseSalaryMonth",
    "data"     : {baseSalaryMonthStr: objVar},
    "dataType" : "json",
  }).done(function(data){
    $('#t1').append($('<thead>')).append($('<tbody>'));
    $('<tr>')
      .append($('<th>').attr('id','userId').text('ユーザID'))
      .append($('<th>').attr('id','fullNm').text('ユーザ名'))
      .append($('<th>').attr('id','baseSalary').text('基本給'))
      .appendTo($('#t1 thead'));
    data.forEach(function(x){
      $('<tr>')
        .append($('<td>').text(x.userId))
        .append($('<td>').text(x.fullNm))
        .append($('<td>').text(x.baseSalary))
        .appendTo($('#t1 tbody'));
    });
  });
};
</script>
<table id="t1"></table>

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/12/07 19:36

    はい
    受け取った値は以下になります。
    [{"userId":2,"fullNm":"鈴木一郎","baseSalary":0,"yearDay":0},{"userId":4,"fullNm":"pppp","baseSalary":0,"yearDay":0},{"userId":3,"fullNm":"oooo","baseSalary":0,"yearDay":0}]

    キャンセル

  • 2018/12/07 20:11

    ご提示のjsonデータをうけとるのであればajaxサンプルの通り処理すればよいでしょう

    キャンセル

  • 2018/12/07 20:23

    おーできました
    ありがとうございます。
    入れ方がそもそも違いましたね

    キャンセル

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

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

関連した質問

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