1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【JavaScript】 料金の自動計算を非同期でActiveHash(アクティブハッシュ )のプルダウン選択をして表示させる。

Posted at

#はじめに

javascriptとプルダウンの選択方式で(アクティブハッシュ)非同期的に表示を変える方法を紹介します。
具体的には、予め決められた「料金」に対して、アクティブハッシュ内からdate属性で「数列」を取得し、計算をする実装をします。
要するに、「料金」X「人数」です。

ezgif.com-gif-maker.gif

前提
基本的なMVCとアクティブハッシュは既に実装済みです。
こちらを参考にしてください。

【Rails】ActiveHash(アクティブハッシュ)の導入と「確認」→「保存」→「表示」
https://qiita.com/AKI3/items/022ad68e22f798d40ad9

###目次

  1. date属性の付与
  2. javascrip

#開発環境
ruby 2.6.5
rails 6.0.0

#実装
それでは実装していきます〜

#1. date属性の付与

###マイグレーションファイルの編集

db/migrate/2020XXXXXXXX_create_event.rb
class CreateEvents < ActiveRecord::Migration[6.0]
  def change
    create_table :events do |t|
      t.string    :price
      t.integer   :num_id

      t.timestamps
    end
  end
end

保存で必要なカラムpricenum_id(ActiveHashのid)を記述します。

rails db:migrate

###モデル作成・編集

そして、ActiveHashモデルを作成します。
作成したActiveHashモデルの記述を編集します。

app/models/num.rb
class Num < ActiveHash::Base
  self.data = [
    { id: 0, name: '--' },
    { id: 1, name: '1', multiple:1 },
    { id: 2, name: '2', multiple:2 },
    { id: 3, name: '3', multiple:3 },
    { id: 4, name: '4', multiple:4 },
    { id: 5, name: '5', multiple:5 },
    { id: 6, name: '6', multiple:6 },
    { id: 7, name: '7', multiple:7 },
    { id: 8, name: '8', multiple:8 },
    { id: 9, name: '9', multiple:9 },
    { id: 10, name: '10', multiple:10 },
    { id: 11, name: 'お問い合わせください' },
  ]
end

name属性の後にdeta属性multiple:1と数列で数字を入れて追記します。
今回はmultipleをdeta属性を使用してますが、お好みで編集できます。
またmultiple:1の数列「1」も変更可能です。
例えば、こんな感じです。

id: 1, name: '1', multiple:1 
 #下記に様に編集できます
id: 1, name: 'コーラ', multiple:150 

とする事もできます。通常のActiveHashではname属性しか扱いませんが、date属性を使う事で様々な値を取得できます。
このdate属性は、データを取得際JavaScriptで取得します。

次にビューで入力フォームを作ります。

###ビューの作成

app/events/viwes/index.erb
<h1>Events#new</h1>
<p>Find me in app/views/events/new.html.erb</p>

<div class="#">
  <div class="#">
    <P>一人あたりの値段</P>
      <div class="#" >
        <p>¥<span id="one_price">10,000</span></p>
      </div>
    <P>合計金額</P>  
      <div class="#" id="total_price">
        <p>¥0</p>
      </div>
  </div>

  <div class="#">
    <%= form_with(model: @event, url:confirm_events_path, local: true) do |f| %> #←ここは注意

      <div>
        <%= f.hidden_field :price, id: "f_price"  %> #←ここはhidden
      </div>

      <div class="#">
        <%= f.label :num, '参加人数' %>
          #ここからプルダウンにする記述#
          <% num_options = Num.order(:id).map { |c| [c.name, c.id, data: { multiple: c.multiple }] } %>
          <%= f.select(:num_id, num_options, {}, {class:"#", data:{select:0}, id:"num" }) %>
          #ここまで#
      </div>
      <div class="submit">
        <%= f.submit "submit", class:"#" %>
      </div>
    <% end %>
  </div>
</div>

<%= form_with(model: @event, url:confirm_events_path, local: true) do |f| %>
pathはrails routesで調べてください。今回は確認画面を挟んだ実装をしているので上記の様なpathになってます。

ポイントはプルダウンのoptionsデータ属性です。

項目 名前
変数名 num_options
data属性名 multiple
id num

としました。
ここまでが下地で続いてJavaScriptです。

#2. javascrip

最初javascriptのapplication.jsファイルを編集します。

app/javascript/packs/application.js
//省略

require("@rails/ujs").start()
// require("turbolinks").start() ←ここをコメントアウト
require("@rails/activestorage").start()
require("channels")
require("../price") //←ここに追記

//省略

javascript配下新しいファイルを作成します。
今回はpriceという名前にします。

スクリーンショット 2020-12-02 12.59.16.png

まず型枠を記述します。

app/javascript/price.js
const price = function () {
  const onePrice = document.getElementById("one_price");
  const totalPrice = document.getElementById("total_price");
}

window.addEventListener("load", price);

一人当りの料金をone_price合計をtotal_priceとしてます。

ビューのプルダウンで人数を選択するとJavaScriptが発火する様に記述します。

app/javascript/price.js
  const selectNum = document.getElementById("num");
    selectNum.addEventListener('change', function (){

idがnumのdata属性multipleの値を取る。

app/javascript/price.js
      // numのdata属性の値を取る
      const numSelectBox = document.getElementById("num");
      const dataNum = numSelectBox.options[ numSelectBox.selectedIndex].getAttribute("data-multiple");

細かくなりますが、一人料金のidを取得したあと値を数列に変換して、さらにカンマを除去します。

app/javascript/price.js
      // 一人料金のidを取得
      const priceOne = document.getElementById("one_price");
      //値を数列にする
      const displayPriceOne = priceOne.innerHTML;
      //カンマを除去する
      const displayPriceOneInteger = Number( displayPriceOne.replace(/,/, '') );

計算して、表示ように変換して、表示します。

app/javascript/price.js
      // 計算する
      const total = (displayPriceOneInteger*dataNum);
      // 正規表現でカンマ区切りに直して日本円に変換する
      const totalComma = total.toLocaleString('ja-JP', { style: 'currency', currency: 'JPY'});
      // 表示する
      totalPrice.innerHTML = totalComma;

最後、ビューで表示した値をvalueプロパティでtextarea(今回はhidden_field)要素に値を代入します。

app/javascript/price.js
      // ----<フォームに入力>
      // 合計金額の値を取得 
      const displayPriceTotal = totalPrice.innerHTML;
      // 取得した合計金額をフォームに入力
      document.getElementById("f_price").value = displayPriceTotal;
    });

つなげると以下の様になります。

app/javascript/price.js
const price = function () {
  const totalPrice = document.getElementById("total_price");
  const onePrice = document.getElementById("one_price");

  // ------<人数を選択した時の計算>
  const selectNum = document.getElementById("num");
    selectNum.addEventListener('change', function (){
      // numのdata属性の値を取る
      const numSelectBox = document.getElementById("num");
      const dataNum = numSelectBox.options[ numSelectBox.selectedIndex].getAttribute("data-multiple");
      // 一人料金のidを取得
      const priceOne = document.getElementById("one_price");
      //値を数列にする
      const displayPriceOne = priceOne.innerHTML;
      //カンマを除去する
      const displayPriceOneInteger = Number( displayPriceOne.replace(/,/, '') );
      // 計算する
      const total = (displayPriceOneInteger*dataNum);
      // 正規表現でカンマ区切りに直して日本円に変換する
      const totalComma = total.toLocaleString('ja-JP', { style: 'currency', currency: 'JPY'});
      // 表示する
      totalPrice.innerHTML = totalComma;
      // ----<フォームに入力>
      // 合計金額の値を取得 
      const displayPriceTotal = totalPrice.innerHTML;
      // 取得した合計金額をフォームに入力
      document.getElementById("f_price").value = displayPriceTotal;
    });
}

window.addEventListener("load", price);

完成です!!

#まとめ
以上、 JavaScriptとActiveHash(アクティブハッシュ )を使って、非同期で料金の自動計算をする方法でした。

最後に
私はプログラミング初学者ですが、同じ様に悩んでる方々の助けになればと思い、記事を投稿しております。
それでは、また次回お会いしましょう〜

#参考
https://www.sejuku.net/blog/23998
https://techacademy.jp/magazine/22426
https://lealog.hateblo.jp/entry/2013/02/28/005010
https://lab.syncer.jp/Web/JavaScript/Snippet/29/

【Rails】ActiveHash(アクティブハッシュ)の導入と「確認」→「保存」→「表示」
https://qiita.com/AKI3/items/022ad68e22f798d40ad9

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?