【ポモドーロタイマーを作ろうVanillaJS編⑤】~ユーザー編集部分の追加~

今回は、ポモドーロタイマーの作業時間や休憩時間を

ユーザーが編集できるように編集部分の実装を行っていきます。

イメージはこのような感じです。

f:id:hnm-n-1029:20200706232226p:plainf:id:hnm-n-1029:20200706232313p:plain
設定時間の表示とユーザー編集部分

ユーザー編集部分の追加


編集できる内容は次の4つとしました。


・作業時間(分)
・小休憩時間(分)
・長休憩時間(分)
・長休憩までの回数(回)


この条件で実装するにあたり、次のように考えました。


●html

①現在の設定時間を表示する部分を作成

②各項目についてinputタグで入力部分を作成
 →数字のみ入力できるようにする


JavaScript

③設定ボタンのクリックイベントで入力された値を取得後
 対応する変数へ値を再代入→描画・関数の実行


上記内容を元に実装したコードが以下になります。

//設定時間の表示部分
<ul>
      <li id="cycle"></li>
      <li id="input_worktime"></li>
      <li id="input_breaktime"></li>
      <li id="input_longbreaktime"></li>
      <li id="input_cyclecount"></li>
</ul>

//編集部分
<p>■タイマーは以下で調整できます■</p>
    <label for="work">作業時間:</label>
    <input type="number" name="work" id="work_time" value="25"><br>
    <label for="break">小休憩時間:</label>
    <input type="number" name="break" id="break_time" value="5"><br>
    <label for="longbreak">長休憩時間:</label>
    <input type="number" name="longbreak" id="longbreak_time" value="20"><br>
    <label for="cycle">長休憩までの回数:</label>
    <input type="number" name="cycle" id="cycle_count" value="4"><br>
    <button type="submit" class="btn" id="submit_btn">設定</button>


表示部分については、JavaScriptで生成させるのでテキストは書いていません。


編集部分は全てinputタグで書きました。

簡単な解説としては、

type="number":数字のみの入力とする

value="25":デフォルト値の指定

name="○○":labelと関連付ける(for="○○"で○○を合わせる)


※ユーザー編集部分のhtmlについて、リファクタリングしました。
最終コードはこちらの記事で説明しております。

【ポモドーロタイマーを作ろうVanillaJS編⑦】~CSSによるスタイリングとhtmlの修正~ - 30代未経験からフロントエンドエンジニアへ



続いて、JavaScriptのコードです。

//①設定時間を描画する関数
function displayInput(workTime, breakTime, longBreakTime, cycleCount) {
    input_worktime.textContent = `作業時間:${workTime}分`;
    input_breaktime.textContent = `小休憩時間:${breakTime}分`;
    input_longbreaktime.textContent = `長休憩時間:${longBreakTime}分`;
    input_cyclecount.textContent = `長休憩までの回数:${cycleCount}回`;
  };

//②設定ボタンクリックで値の更新、描画処理が実行
submit_btn.addEventListener('click', () => {
    workTime = work_time.value;
    breakTime = break_time.value;
    longBreakTime = longbreak_time.value;
    cycleCount = cycle_count.value;
    displayInput(workTime, breakTime, longBreakTime, cycleCount);
    displayTime(workTime);
    displayState(state, count);
  });


①は設定した時間を描画する関数です。

引数を4つ渡し、一気に全て描画させるようにまとめました。

最初は①の内容を②の中にべた書きしていたのですが
可読性が悪いのと、ページのロード時にもデフォルト値として
描画させたかったのでどこでも呼び出せるように関数化しました。

②については、設定ボタンが押された際に
値が更新され、各部分の描画に関する関数を呼び出すようにしています。


躓きポイント

上記コードに至るまで、いくつか躓いたポイントがありましたので
エラーの内容とどのように解決したかを紹介します。

※そんなところで!?と思われる部分が多いかもしれませんが
 同じように迷われている方がいるかもしれませんので書き留めておきます。
 そして、なにより自分自身への備忘として.....

①エラー:Assignment to constant variable. 定数へ代入しようとしています

原因: 定数に再代入

   const workTime = 25;
   ....
   workTime = work_time.value;


workTimeを初期値「25」で宣言した後、
ユーザーが設定ボタンをクリックした際にworkTimeを更新する
というコードを書いていた際にエラーが出ました。


はい。すみません。constに代入しようとしておりました。

letは極力使わない精神でいたいのですが
今回の仕様ではletでないと動きませんね....

グローバルで宣言してしまうと、どんどん機能を追加してく際に
知らない間に違う値が代入されたり思わぬバグに繋がるようなので
スコープを狭めたいのですが、それは後々考えようと思います。

まずは一旦の完成を目指します。


②Cannot set property 'textContent' of nullエラー:オブジェクトのプロパティを参照できない

原因:id名の誤りでHTML要素の取得ができていなかった

 //↓ここで取得できていなかった
 const input_cyclecount = document.getElementById('input_cyclecount');
 .....
 //↓ここで値は取得できていた
  cycleCount = cycle_count.value;
 .....
 //↓ここでエラーが出た
 input_cyclecount.textContent = `長休憩までの回数:${cycleCount}回`;


getしたつもりがgetできていませんでした.....

inputからの取得方法や変数名の確認は何度も行ったのですが
そもそも大元が取得できていなかったという.....

ただ、エラーの内容から想像できる内容だと思うので
エラーを正しく読み取ることが大事ですね。

当たり前のことですが....できていなかった...反省です....


このエラー解決のために行ったのは以下です

①どこまで処理が動いているか
②データ型の確認
google先生

①については、console.log(cycleCount)でどこまで
処理が動いているのかを確認しました。

すると、inputからの値は取得できており
変数への代入もできていることが分かりました。

そこで②のデータ型が良くないのか?と考え

console.log(typeof work_time.value)でデータ型を確認しました。

※number型で宣言されているのでString型だと代入できないという考え
後々気付いたら、これはTypeScriptのお話でしたね.....


ただ、型については関係なさそうだったので
結局、google先生で同じエラーでの解決方法を参考に
原因を見つけ出しました。


小さいエラーにハマってしまいましたが、なんとか編集エリアを追加できました。

UIについてはこれから整えていきます!


次回はさらに使いやすさを改善させるために
効果音の追加などを進めていきます!



↓↓私の師匠、もりけんさんの武骨日記。問題集、要チェック

kenjimorita.jp