HTML
HTML5

htmlだけでinputの合計した入力値を出力 Output

htmlだけでinputの合計した入力値を出力

単純な値の計算であればonClickやonChangeで計算出来ますが複雑な計算だと
以前はjQueryなんかで要素の変更を検知したり、ライブラリーなんかで双方向データバインディングで結果を出力したりしてました

今はhtml5 のinput を使えばjavascriptを使わずに値を計算して結果を出力できることを恥ずかしながらつい最近知りました・・・
html5もcss3もちゃんと把握できていないのを最近痛感しています

Output属性

今回使うのはhtml5で追加されたOutput要素です
これを使うことでform内の値を計算して出力することが出来ます

Output - 加算

まずはAとBのinputの要素の加算です
よくあるのが買い物カゴの中身を計算する時とかに使います

oninput

oninputでform内のフィールドに値が入力された時実行します
その際にoutputに指定したname属性に計算した値の結果を入れています

parseIntで整数にしているのは変換しないと文字列連結になってしまうため整数値に一度変換しています

<form oninput="result.value = (hoge.value && fuga.value) && parseInt(hoge.value) + parseInt(fuga.value)">
  <input type="number" name="hoge"> + <input type="number" name="fuga">
  = <output name="result">
</form>

最終的にリファクタするとこんな感じに外部で関数化したもので評価すれば使い回せるはずです

See the Pen html output 1 by Hideto (@HidetoNagamatsu) on CodePen.

OutPut 表示要素の切り替え

今度はある一定の合計値以上に文字列を表示してみたいと思います

<script>
  const add = (x,y) => {
    if(!x || !y) return "";       
    x = parseInt(x);
    y = parseInt(y);
    if(x+y < 10){
      return "10より小さい";      
    }
    return "10より大きい"
  }
</script>

<form oninput="result.value = add(hoge.value,fuga.value)">
  <input type="number" name="hoge"> + <input type="number" name="fuga">
  = <output name="result">
</form>

value値以外の文字列などのも表示できます
またif文などの判定も使えるので処理によって特定の要素のclassやスタイルを変えることもできます

See the Pen html output 2 by Hideto (@HidetoNagamatsu) on CodePen.

Output エラー時の表示

今度はinputのバリデーションエラーの文言を表示して見たいと思います

<form
  oninput="result.value = hoge.validity.valid ? hoge.value : hoge.validationMessage"
>
  <input type="number" name="hoge" required
    oninvalid="this.setCustomValidity('入力内容が空です')"
    oninput="this.validity.valid ? this.setCustomValidity('') : this.setCustomValidity('入力内容が空です')"
  />
  :<output name="result"></output>
  <div>
    <input type="submit" />
  </div>
</form>

バリデーションメッセージの表示

input要素の validity にはバリデーションのフラグ情報が入っています
それを判別して要素が持っているバリデーション用のメッセージを表示します

oninput="result.value = hoge.validity.valid ? hoge.value : hoge.validationMessage"

バリデーションメッセージの変更

oninvalidでsubmit時にバリデーションに引っかかればここが発火します
setCustomValidityでバリデーションメッセージを書き換えられるので変更します

入力時にも変更したいのでoninputイベントにもsetCustomValidityでメッセージを書き換えます
注意しなければいけないのが、下記のように書き換えた場合です

<input type="number" name="hoge" required
    oninput="this.setCustomValidity('入力内容が空です')"
  />

setCustomValidity()で内容を書き換えると validationMessageが書き変わるのですが
validity.validもfalseに変わるため常にバリデーションでエラーが出た状態になってしまいます
なので通常時は this.setCustomValidity('') で初期化してあげる必要があります

補足

ダメなパターン
<input type="number" name="hoge" required
    oninvalid="this.setCustomValidity('入力内容が空です')"
    oninput="this.validity.valid ? this.setCustomValidity('') : this.setCustomValidity('入力内容が空です')"
  />

この内容だとthis.validity.validがfalseの時にthis.setCustomValidity()でメッセージをセットするのはいいけど
その際validity.validもfalseに変わるため常にfalseになってしまっていた。。。(上で全く同じことを自分で説明しているのに・・・)

なので正しくは下記になります

正しいパターン
<input type="number" name="hoge" required
  oninvalid="this.setCustomValidity('入力内容が空です')" 
  oninput="
    this.setCustomValidity('');
    this.validity.valid ? this.setCustomValidity('') : this.setCustomValidity('入力内容が空です')
   "
/>

つまり判定処理を入れる前に必ず this.setCustomValidity('') で初期化する必要がありました・・・

See the Pen html output 3 error by Hideto (@HidetoNagamatsu) on CodePen.

複数のバリデーションエラー

まぁ、ただ単にinputとoutputを増やしただけですw
でも一番見るパターンがこれなので一応載せておきます
formの配列を回して作成するとか色々考えましたが多分、これが一番無難な作り方です

See the Pen html output 4 errors by Hideto (@HidetoNagamatsu) on CodePen.

おまけ

ちなみにCodePenでタブなどの自動整列をしたい場合は全選択したのち shift + tab とかで綺麗になるのでオススメです

1516958381.gif