素のJavascript(Vanilla)だけでフロントエンド開発(06:入力値制御編)

このページでは、ReactやVueではなく、Vanillaと呼ばれる素のJavascriptのみで、フロントエンド開発が可能であるか?を解説します。今回はラジオボタンやSELECTなどの変更値で制御を行います。初期表示にも活用します。

今回は、前回…

の続きになります。

目次

今回の課題のゴールは?

入力画面では、ラジオボタンやセレクトボックスを選択することで、入力可能な項目が増えたり減ったりすることがあります。

例えば、業務日報の入力で、直行・直帰を選択した際、実際の業務開始・終了時刻を打刻時間の代わりに入力できる…といったケースでしょうか。

今回は、特に入力画面のタイトルは定義しませんが、外出ありを選択した場合、外出時刻欄を表示するようにします。

変更時の値の取得方法

と、その前に。

いきなりプログラムを提示すると混乱するかもしれませんので、まずは、下準備として、各種選択項目の値の取得方法を再確認しましょう。

プログラム例

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<script>
// セレクト
function chgFoo2() {
  let elm = document.forms['frm'].elements['foo2'];
  console.log('foo2=>' + elm.value);
}

// ラジオボタン
function chgGaishutsu() {
  let elm = document.forms['frm'].elements['gaishutsu'];
  console.log('gaishutsu=>' + elm.value);
}

// チェックボックス
function chgKintai() {
  let elm = document.forms['frm'].elements['kintai'];
  let arr = [];
  elm.forEach(function (el) {
    if (el.checked == true) {
      arr.push(el.value);
    }
  });
  console.log('kintai=>' + arr); // arrはリスト変換される
} // function
</script>
</head>
<body>
<form name="frm" id="FORM_AREA">
元号2:<select name="foo2" class="sel_gengo" onchange="chgFoo2()">
  <option value="X">ここには追加しません</option>
  <option value="M">明治</option>
  <option value="T">大正</option>
</select>  
<br />
外出:<input type="radio" name="gaishutsu" value="1" onclick="chgGaishutsu()">あり
<input type="radio" name="gaishutsu" value="0" checked onclick="chgGaishutsu()">なし
<br />
勤怠:<input type="checkbox" name="kintai" value="1" onclick="chgKintai()">遅刻
<input type="checkbox" name="kintai" value="2" onclick="chgKintai()">早退
<input type="checkbox" name="kintai" value="3" onclick="chgKintai()">電車遅延
<br />
</form>
</body>
</html>

実行

http://localhost/~(ユーザー名)/test_no_disp01.html

項目を選択、あるいは押下するたびに、F12のConsole画面が…

foo2=>M

に、なったり、

kintai=>1,3

のようになります。

ソースを見ると、チェックボックスのみ配列化する必要があり面倒ですが、ラジオボタンやセレクトボックスについては、obj.valueのようなシンプルな表記で、現在の選択値が取得可能です。

まとめるとこうなります。

タグ発火点取得方法
SELECTonchange()elm.value
INPUT(radio)onclick()elm.value
INPUT(checkbox)onclick()elm.forEach(function (el)
⇒el.checkedを確認(true or false)

値変更時に動きをつける

この内、ラジオボタンを活かして、外出=ありのときに、開始・終了時間欄を表示し、外出=なしの場合は非表示…とするようにしましょう。

セレクトボックスについても、ラジオボタンと同様に値の変化を容易に確認できると思います。

プログラム例

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<style>
.vj-nodisp {
  display:none;
}
</style>
<script>
// 外出時刻の表示制御
function chgGaishutsu() {
  let elm = document.forms['frm'].elements['gaishutsu'];
  //console.log('gaishutsu=>' + elm.value);
  let gaiTim = document.getElementById("gai_time");
  if (elm.value === '0') {
    gaiTim.classList.add("vj-nodisp");
  } else {
    gaiTim.classList.remove("vj-nodisp");
  }
} // function
</script>
</head>
<body>
<form name="frm" id="FORM_AREA">
外出:<input type="radio" name="gaishutsu" value="1" onclick="chgGaishutsu()">あり
<input type="radio" name="gaishutsu" value="0" checked onclick="chgGaishutsu()">なし
<br />
外出時刻:<span id="gai_time" class="vj-nodisp"><input type='text' name="str_time" value="">~<input type='text' name="end_time" value=""><span>
<br />
</form>
</body>
</html>

実行

http://localhost/~(ユーザー名)/test_no_disp02.html

処理説明

このプログラムは、ラジオボタンのクリックのたびに、(クリックしたelementsのvalueではなく)結果有効となっているラジオボタンの値を確認し、1の場合はクラスvj-nodispを外出時刻を囲むSPANタグに追加し、0の場合はそのSPANタグから削除します。

classList.addclassList.removeの便利なところは、

  • 「あり」を何回押しても(=classList.addを何度も実行しても)、vj-nodispが多重に増えない
  • 「なし」を何回押しても(=classList.removeを何度も実行しても)、エラーにならない

といったところです。

値変更のfunctionを、そのまま初期表示にも活かす

さて、登録画面の制御は出来ましたが、変更画面の初期表示についてはいかがでしょうか?

今まではonchangeあるいはonclickでしたから、クリックも変更もない、初期画面表示の際は、どうやってあり・なしを表現すれば良いのでしょうか?

onloadあるいはDOMContentLoadedのロジックで、制御する

はい。
onloadあるいはDOMContentLoadedのロジックで、あり・なしを制御すれば良いのですが、先程作成したロジックを、同じ様に書いたとして、二重の手間にならないでしょうか?

先程書いたロジックと共通化出来ないものでしょうか?

onClickのfunctionを共通化するには?

実は、前項のロジックがそのまま活用できます。

前項で「(クリックしたelementsのvalueではなく)結果有効となっているラジオボタンの値を確認」とあるように、アクションを起こした位置の値で判断するのではなく、結果どのような値になったか?…という聞き方をすれば、流用できます。

プログラム例

以下のプログラムファイルを作成します。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<script src="js/vanilla-front-end.js"></script>
<style>
.vj-nodisp {
  display:none;
}
</style>
<script>
// APIを使用した初期表示
async function setInitData() {

  // INPUTタグの値をセット
  // API実行
  let result = await fetch("api_mock/get_input.json", {
      method: "GET"
  });
  // JSONを取り出す
  let jsonData = await result.json();
  //console.log(jsonData.result);
  // selectのoptionを追加する
  setInputValue(jsonData.result, 'frm');

  // 外出時刻の「初期」表示制御
  chgGaishutsu();
} // function

// 外出時刻の表示制御
function chgGaishutsu() {
  let elm = document.forms['frm'].elements['gaishutsu'];
  //console.log('gaishutsu=>' + elm.value);
  let gaiTim = document.getElementById("gai_time");
  if (elm.value === '0') {
    gaiTim.classList.add("vj-nodisp");
  } else {
    gaiTim.classList.remove("vj-nodisp");
  }
} // function

// DOMコンテンツのロード完了時に実行
window.addEventListener('DOMContentLoaded', (ex) => {
  // APIを使用した初期表示
  setInitData();

  // ★ここには「chgGaishutsu();」は入れない(非同期実行されるため)
});
</script>
</head>
<body>
<form name="frm" id="FORM_AREA">
外出:<input type="radio" name="gaishutsu" value="1" onclick="chgGaishutsu()">あり
<input type="radio" name="gaishutsu" value="0" checked onclick="chgGaishutsu()">なし
<br />
<!-- Javascriptでの改めて初期設定を行うので、class="vj-nodisp"の有無はどちらでもよい -->
外出時刻:<span id="gai_time" class="vj-nodisp"><input type='text' name="str_time" value="">~<input type='text' name="end_time" value=""><span>
<br />
</form>
</body>
</html>

setInputValue()vanilla-front-end.jsにない場合は、前回の内容をコピペしてください。
vanilla-front-end.jsの作成方法がわからない場合も、前回を参照してみてください。

実行

http://localhost/~(ユーザー名)/test_no_disp03.html

で、初期表示の外出が「あり」となり、時間が表示されるようになります。

JSONのgaishutsuを0で試してみましょう。
外出時刻欄が表示されなくなるはずです。
(上手く行かない場合は、F12>NetworkでJSONファイルのキャッシュをクリアして、再実行してください。)

外出=なしの場合に、時刻欄をクリアしなくてよいか?

今回の制御とは直接関係はありませんが、「なし」を選択した時点で、時刻欄の中身をクリアしたくありませんか?

好みの問題かもしれませんが、私はクリアしません。
理由は下記のとおり…

  • 間違って「なし」を押下してしまうこともあるので、「あり」に戻した際に復活させてあげたほうが良い
  • もし、「なし」で時刻がセットされているのがマズいのなら、API側でDB更新する際にクリアすれば良い

です。

こういった事も含めて、API側(バックエンド側)は、データの整合性を中心としたプログラミングを行う必要があります。
(フロントエンド技術者を疑う訳ではありませんが、)エラーチェックはバックエンドでひととおり行うことが望ましいです。

このあたりのロジックは共通のJavascriptでまとめて良いか?

この入力項目の制御については、共通ではなく、この画面固有のものですので、vanilla-front-end.jsではない方が良いかなとは思います。

ただし、外部のJavascriptファイルにしておいたほうが、ソースはそれぞれに短くなりますね。

各プログラム固有のJavascriptコードについては、画面名(or プログラム名).jsといった名前にすれば、わかりやすいでしょうね。

最後に

かなり進みましたね。

残された機能は、エラーチェックをAPIで行ったり、明細行に対応したり…でしょうか。

次回は、エラーチェックAPIを実装してみます。

それでは、また。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

CAPTCHA

目次