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

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

ただいまの
回答率

90.34%

リロードした時に前に登録した要素を取得する

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 451

rinneP2525

score 11

前提・実現したいこと

Monacaでアプリを作っています。
入力ボタンを押した際にtable bodyが増えていき、そこにinputから文字を入力しているのですが、inputボタンを押した際に実行される処理の途中から(表にlocalstorageの内容を出力するところ)再度同じ処理を実行したいのですが、同じコードを書くのはスマートじゃないと思って四苦八苦しています。
今のコードは一回ウインドウを更新して、その時に表を表示するようになればいいなと思って書いているのですが、うまくいきません。
何か手立てがあればご教授いただけたら幸いです。
初心者な質問で申し訳ないのですが、よろしくお願いいたします。

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

ページをリロードするとtableが消えてしまう

該当のソースコード

/* ローカルストレージ設定 */
  var storage = localStorage;

  /* 履歴を保存 */
  $('#f1').on('submit', function (e) {
    e.preventDefault()
    var obj = {
      day: $("#day").val(),
      money: $("#money").val()
    }
    var i = Math.floor(Math.random() * 101);
    storage.setItem("datalist" + i, JSON.stringify(obj));

    /* 履歴を取得 */
    var str = storage.getItem("datalist" + i);
    var obj = JSON.parse(str);
    window.location.reload();
    $(document).ready(function () {

      /* いったんデータを全部消す */
      $("#list").empty();

      /* 全ての要素を取得する */
      for (i = 0; i < storage.length; i++) {
        var key = storage.key(i)
        storage.getItem("datalist" + i)
      }

      /* 登録されているkey, valueを順に取得して表示 */
      var v_id = "datalist" + i;
      var v_day = obj.day;
      var v_money = obj.money;
      if (v_day !== "" && v_money !== "") $('#t1 tbody').after($('<tr>').append($('<td>').html(v_day)).append($('<td>').text(v_money)).append($('<td>').html('<button class="remove">-</button>')));
      $("#day,#money").val("");
    });
  });
     <div class="main">
      <form id="f3">
        <div class="jougen">
          <p>課金上限</p>
          <p>
            <output id="rslt" form="settei" class="jogen">0</output></p>
        </div>
      </form>
      <div class="honbun1">
        <p>入力</p>
        <div style="display:inline-flex">
          <form id="f1">
            <div class="moji">
              <input type="date" name="day" id="day" class="day">
              <input type="number" class="money" name="money" id="money"><input type="submit" value="入力" class="kettei1">
            </div>
          </form>
        </div>
      </div>
      <div class="nokori">
        <p>今月の残り課金額</p>
        <p>
          <output name="result" >0</output></p>
      </div>
      <br>
      <form id="f2">
        <p>履歴</p>
        <div class="rireki">
          <table id="t1" border="1">
            <thead>
              <tr>
                <th hidden>id</th>
                <th width="30%">日付</th>
                <th width="50%">金額</th>
                <th width="20%">削除</th>
              </tr>
            </thead>
            <tbody id="list"></tbody>
          </table>
        </div>
      </form>
      <input type="button" value="クリア" id="clear">
    </div>
  </body>

試したこと

データを全部消す前で一回切って新しく$(document).ready( function()で始めた
→obj.dayなどが上から引っ張られずにデータが入ってこなかった

途中でリロードしてHTMLを取り込んだ後の処理を入れた
→現状。一瞬だけtableが現れて消える

追記:できました!

/* ローカルストレージ設定 */
    var storage = localStorage;
    let datalist_st = storage.getItem('datalist');
    /* 入力ボタンを押すとデータを取得する */
    $(function() {
        const day = $('#day').val();
        const money = $('#money').val();

        displayList();
        $('#f1').on('submit', function(e) {

            e.preventDefault()

            if ($('#day').val() === '') {
                alert('日付を入力してください');
                return false;
            }
            if ($('#money').val() === '') {
                alert('金額を入力してください');
                return false;
            }


            if (datalist_st != null) {
                datalist = JSON.parse(datalist_st);
            } else {
                datalist = [];
            }

            const row_data = {
                day: $('#day').val(),
                money: $('#money').val()
            };

            datalist.push(row_data);

            storage.setItem('datalist', JSON.stringify(datalist));
            $("#day,#money").val("");
            window.location.reload();
        });
    });

    function displayList() {
        if (datalist_st != null) {
            datalist = JSON.parse(datalist_st);
        } else {
            datalist = [];
        }
        for (i = 0; i < datalist.length; i++) {
            let record_tr = $('<tr></tr>', {
                id: 'row_' + i
            });
            const td_id = $('<td></td>', {
                hidden: 'hidden',
                html: i
            });
            const td_day = $('<td></td>', {
                html: datalist[i].day
            });
            const td_money = $('<td></td>', {
                html: datalist[i].money
            });
            const remove_btn = $('<button></button>', {
                html: '-',
                type: 'button',
                class: 'remove'
            });
            remove_btn.attr('data-id', i);
            const td_remove = $('<td></td>', {
                html: remove_btn
            });
            record_tr.append(td_id);
            record_tr.append(td_day);
            record_tr.append(td_money);
            record_tr.append(td_remove);
            record_tr.append(td_remove);
            $('#list').append(record_tr);
        }
        /* 選択した列のデータを削除 */
        $("#list").click(function() {
            let storageItem = JSON.parse(storage.getItem('datalist'));
            const id = 'data-id';
            const index = storageItem.findIndex((v) => v.id === id);
            const removeid = storageItem.splice(index, 1);
            storage.setItem('datalist', JSON.stringify(storageItem));
            window.location.reload();
        });
    }


    /*  全てのデータを削除 */
    $("#clear").click(function() {
        storage.clear();
        window.location.reload();
    });
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • m.ts10806

    2019/04/16 11:03 編集

    ↑で私が提示したhtml整形サービス
    http://u670.com/pikamap/htmlseikei.php
    でも構文チェックができるのでそちらで確認してみてください(構文チェック機能のあるエディタ使うのが確実ですが)

    キャンセル

  • m.ts10806

    2019/04/16 11:05

    >現在のhtmlでも最初の </form>と最後の</div>が開始タグがないようです。
    というより</form>を</div>にして最後の</div>を削除するか</form>を削除するか、ですかね。
    レイアウトによるのでそこは確認してみてください。

    キャンセル

  • rinneP2525

    2019/04/16 11:19

    これで構文チェックは問題なかったのですが…大丈夫でしょうか…

    キャンセル

回答 1

checkベストアンサー

+2

$(document).ready(function() { });は「ドキュメント読み込み時」のイベントを取る機能になるのでonsubmitの中に入っているのはおかしいです。
毎回押さないとこの中のイベントが発生しません。

むしろ、セレクタ.on()のイベントをdocument.readyの中に入れるべき。
で、「データを読みだしてくる」を関数にしておくと有用です。

あと、終端;があったりなかったりしていますが、間違いを起こさないために「終端すべてにつける」癖をつけておくと良いと思います。


そこだけ修正したJavaScriptのコードは下記。

/* ローカルストレージ設定 */
var storage = localStorage;

$(function() {
    displayList();
    /* 履歴を保存 */
    $('#f1').on('submit', function(e) {
        e.preventDefault()
        var obj = {
            day: $("#day").val(),
            money: $("#money").val()
        }
        var i = Math.floor(Math.random() * 101);
        storage.setItem("datalist" + i, JSON.stringify(obj));

        /* 履歴を取得 */
        var str = storage.getItem("datalist" + i);
        var obj = JSON.parse(str);
        window.location.reload();
    });
});

function displayList(){
    /* いったんデータを全部消す */
    $("#list").empty();

    /* 全ての要素を取得する */
    for (i = 0; i < storage.length; i++) {
        var key = storage.key(i);
        storage.getItem("datalist" + i);
    }

    /* 登録されているkey, valueを順に取得して表示 */
    var v_id = "datalist" + i;
    var v_day = obj.day;
    var v_money = obj.money;
    if (v_day !== "" && v_money !== "") $('#t1 tbody').after($('<tr>').append(
        $('<td>').html(v_day)).append($('<td>').text(v_money)).append($('<td>')
        .html('<button class="remove">-</button>')));
    $("#day,#money").val("");
}

切り分けると色々と見えてきます。


リロードするなら取得するのは意味がない

        var str = storage.getItem("datalist" + i);
        var obj = JSON.parse(str);
        window.location.reload();


変数なのでリロードしてしまっては値を保持しません。


storageのlength。。。?

    for (i = 0; i < storage.length; i++) {


LocalStorageをこのデータのためだけに使うのでしたらこれでも良いかもしれませんが、このやり方はお世辞にも良いとは言えません。
LocalStorageはドメイン内で共有されます。同じアプリケーション内の他の用途でLocalStorageを使う場合もあるかもしれません。
その際にこのやり方だと「LocalStorageの情報全て回す」ことになります。


下記は何がしたいのかわかりません。

    for (i = 0; i < storage.length; i++) {
        var key = storage.key(i); // ローカルスコープでkeyを保持してて使ってない
        storage.getItem("datalist" + i); //getItem()の結果をどこにも保持していない

ランダムで振っているのは大丈夫?

        var i = Math.floor(Math.random() * 101);
        storage.setItem("datalist" + i, JSON.stringify(obj));


そのためstorage.lengthをとっているのかもしれませんが結構煩雑になっています。

そもそもランダムに振る必要があるのか?そこも考える必要があります。
今後、行の削除、行の更新とか発生した際に、この運用がやりやすいかどうか?です。

単に追記していくだけなら良いでしょうけど・・・。

上記踏まえたうえで、自分なりにコードを(あまり元のコードのやり方を崩さずに)書いてみました。

私ならこう書く、というのを作ってみました。
おおよそ動くとは思いますが、きちんと全て理解してから使うようにしてください。
一応、それなりに動くコードなので「できた」と思い込んでしまってはきっとここから何も対応できなくなりますので、コードを確認したうえで不明な点はこの回答のコメント欄にて解決するようにしてください。

var storage = localStorage;
let datalist_st = storage.getItem('datalist');
$(function() {
    displayList();
    $('#f1').on('submit', function(e) {

        e.preventDefault()

        if(datalist_st != null){
            datalist = JSON.parse(datalist_st);
        }else{
            datalist = [];
        }
        const row_data = {
            day: $('#day').val(),
            money: $('#money').val()
        };
        datalist.push(row_data);
        storage.setItem('datalist', JSON.stringify(datalist));
        $("#day,#money").val("");
        window.location.reload();
    });
});

function displayList(){
    if(datalist_st != null){
        datalist = JSON.parse(datalist_st);
    }else{
        datalist = [];
    }
    for (i = 0; i < datalist.length; i++) {
        let record_tr = $('<tr></tr>',{id:'row_'+i}); 
        if(datalist[i].day != '' && datalist[i].money != ''){
            const td_id = $('<td></td>',{hidden:'hidden',html:i});
            const td_day = $('<td></td>',{html:datalist[i].day});
            const td_money = $('<td></td>',{html:datalist[i].money});
            const remove_btn = $('<button></button>',{html:'-',type:'button',class:'remove'});
            remove_btn.attr('data-id',i);
            const td_remove = $('<td></td>',{html:remove_btn});
            record_tr.append(td_id);
            record_tr.append(td_day);
            record_tr.append(td_money);
            record_tr.append(td_remove);
            record_tr.append(td_remove);
            $('#list').append(record_tr);
        }
    }
}

作ってて思った。
表示時にday,moneyのデータ有無確認するんじゃなくて、登録するときに入力ない場合はそもそも入力チェックに引っ掛けて保存させないようにしたほうが動作として自然では?

そこはやってみてください。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/04/18 16:35

    素晴らしいですね。最初の質問の時からすると、これだけのコードでそこまでできたのは大したものだと思います。
    組み方や考え方は他の場面でも活用できるので、がんばってください

    キャンセル

  • 2019/04/18 16:37

    mts10806様を含め回答をいただいたおかげです!
    ありがとうございます!

    キャンセル

  • 2019/04/18 16:44

    いえいえ。少しでも助けになれたのなら幸いです

    キャンセル

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

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

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