#はじめに
javascriptとプルダウンの選択方式で(アクティブハッシュ)非同期的に表示を変える方法を紹介します。
具体的には、予め決められた「料金」に対して、アクティブハッシュ内からdate属性で「数列」を取得し、計算をする実装をします。
要するに、「料金」X「人数」です。
前提
基本的なMVCとアクティブハッシュは既に実装済みです。
こちらを参考にしてください。
【Rails】ActiveHash(アクティブハッシュ)の導入と「確認」→「保存」→「表示」
https://qiita.com/AKI3/items/022ad68e22f798d40ad9
###目次
- date属性の付与
- javascrip
#開発環境
ruby 2.6.5
rails 6.0.0
#実装
それでは実装していきます〜
#1. date属性の付与
###マイグレーションファイルの編集
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
保存で必要なカラムprice
とnum_id
(ActiveHashのid)を記述します。
rails db:migrate
###モデル作成・編集
そして、ActiveHashモデルを作成します。
作成したActiveHashモデルの記述を編集します。
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で取得します。
次にビューで入力フォームを作ります。
###ビューの作成
<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ファイルを編集します。
//省略
require("@rails/ujs").start()
// require("turbolinks").start() ←ここをコメントアウト
require("@rails/activestorage").start()
require("channels")
require("../price") //←ここに追記
//省略
javascript配下新しいファイルを作成します。
今回はpriceという名前にします。
まず型枠を記述します。
const price = function () {
const onePrice = document.getElementById("one_price");
const totalPrice = document.getElementById("total_price");
}
window.addEventListener("load", price);
一人当りの料金をone_price
合計をtotal_price
としてます。
ビューのプルダウンで人数を選択するとJavaScriptが発火する様に記述します。
const selectNum = document.getElementById("num");
selectNum.addEventListener('change', function (){
idがnum
のdata属性multiple
の値を取る。
// numのdata属性の値を取る
const numSelectBox = document.getElementById("num");
const dataNum = numSelectBox.options[ numSelectBox.selectedIndex].getAttribute("data-multiple");
細かくなりますが、一人料金のidを取得したあと値を数列に変換して、さらにカンマを除去します。
// 一人料金の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;
最後、ビューで表示した値をvalueプロパティでtextarea(今回はhidden_field)要素に値を代入します。
// ----<フォームに入力>
// 合計金額の値を取得
const displayPriceTotal = totalPrice.innerHTML;
// 取得した合計金額をフォームに入力
document.getElementById("f_price").value = displayPriceTotal;
});
つなげると以下の様になります。
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