概要
こんな感じのItemモデルへの投稿フォームの作りました。
画像を押すと選択され、もう一度押すと選択が解除されます。
投稿すると送られるパラメーター
Parameters: {"item"=>{"title"=>"青い玉", "ball_id"=>"2"}, "commit"=>"投稿"}
各モデルの構成
Itemモデル
タイトルとball_idを登録するテーブルです。
belongs_to :ball
Ballモデル
3種類のボールが画像と共に既にデータベースに登録済みとします。
has_many :items
ID | NAME | IMAGE |
---|---|---|
1 | Red | Red.png |
2 | Blue | Blue.png |
3 | Green | Green.png |
コード
application_helper.rb
module ApplicationHelper
#引数(モデル名とnameカラム)をもとに、idを返すメソッド
def return_id_by_model_and_name(model, name)
model.constantize.find_by(name: name).id
end
end
html.erb
HTMLにonclick属性を使うのはあまり良くありませんが、実験ということで。
本当はイベントリスナーやイベントハンドラを使った方が良いです。
<h1>新規投稿</h1>
<%= form_with model: @item, local: true do |f| %>
<h4 class="text-xl font-bold">タイトル</h4>
<%= f.text_field :title %>
<h4 class="text-xl font-bold">カラー</h4>
<div class="boxContainer">
<div class="text-center">
<%= f.radio_button :ball_id, return_id_by_model_and_name("Ball", "Red"),{class:"radio_btn_to_image Red",
onclick: "ballDeselection(this, #{return_id_by_model_and_name("Ball", "Red")})"} %>
<%= f.label "ball_id_#{return_id_by_model_and_name("Ball", "Red")}", class:"remove_inner_html" %>
<p>Red</p>
</div>
<div class="text-center">
<%= f.radio_button :ball_id, return_id_by_model_and_name("Ball", "Blue"), {class:"radio_btn_to_image Blue",
onclick: "ballDeselection(this, #{return_id_by_model_and_name("Ball", "Blue")})"} %>
<%= f.label "ball_id_#{return_id_by_model_and_name("Ball", "Blue")}", class:"remove_inner_html" %>
<p>Blue</p>
</div>
<div class="text-center">
<%= f.radio_button :ball_id, return_id_by_model_and_name("Ball", "Green"), {class:"radio_btn_to_image Green",
onclick: "ballDeselection(this, #{return_id_by_model_and_name("Ball", "Green")})"} %>
<%= f.label "ball_id_#{return_id_by_model_and_name("Ball", "Green")}", class:"remove_inner_html" %>
<p>Green</p>
</div>
</div>
<%= f.submit '投稿', class:"px-2 bg-blue-600 text-white" %>
<% end %>
CSS
.boxContainer{
display: flex;
}
.radio_btn_to_image+label:before{
content: "";
display: inline-block;
background-size: contain;
width: 80px;
height: 80px;
}
.radio_btn_to_image:checked+label::before{
border: 3px solid #000;
box-sizing: border-box;
}
.radio_btn_to_image{
display: none;
}
.radio_btn_to_image[class="radio_btn_to_image Red"]+label:before{
background-image: url(/images/balls/Red.png); /*画像は/public/images/balls/に置いている*/
background-repeat: no-repeat;
}
.radio_btn_to_image[class="radio_btn_to_image Blue"]+label:before{
background-image: url(/images/balls/Blue.png);
background-repeat: no-repeat;
}
.radio_btn_to_image[class="radio_btn_to_image Green"]+label:before{
background-image: url(/images/balls/Green.png);
background-repeat: no-repeat;
}
JavaScript
let ball_remove = 0;
function ballDeselection = (self, value) => {
if(ball_remove == value) {
self.checked = false;
ball_remove = 0;
} else {
ball_remove = value;
}
};
参考にさせていただいたサイト