1
1

More than 1 year has passed since last update.

【rails入門】javascriptを用いてリロードしてもチェックボックスの値を維持する(本題)

Last updated at Posted at 2022-04-13

やりたいこと

リロードしてもチェックボックスの値を維持する

実装したらこんな感じ

F6A423F6-1560-42D2-BB05-C1124C3AB16E_1_105_c.jpeg

仕組み(ゴリ押し)

  1. javascriptで全てのcheckboxのtrue/falseをリストに格納
  2. そのリストを「次へ」ボタンが押されたときにコントローラに送り、保存する
  3. 「次へ」ボタンを押したらリロードするので、その時にデータベースから最新のcheckbox情報が入ったレコードをviewに渡す
  4. 受け取ったリストに基づいてjavascriptを用いてチェックをつけていく

実装

checkboxがtrueかfalse保存する用のモデル作成!
1行ずつ実行してください

ターミナル
rails g model Check list:string
rails db:migraate

コントローラ変えていきます

tweets_controller.rb
# 省略

def gatya

# 省略

    check = Check.new #新しいCheck
    check.list = params[:check] #checksテーブルのlistカラムにviewから受け取ったparamsを代入
    check.save #データベースに保存
    @checks = Check.order(created_at: :desc).limit(1) #checksテーブルから最新のレコードを取得
end

# 省略

リロード前後で値を保持したいcheckboxにclass名を付けます

gatya.html.erb
<%= form_tag({controller:"tweets",action:"gatya"}, method: :get) do %>
    <div class="game">
        <% if !@tweet.nil? %>
            <h1><%= @tweet.name %></h1>
        <% else %>
            <h1>no hit</h1>
        <% end %>
        <button type="submit" id="submit">
            <i class="fa-solid fa-arrows-rotate"></i>
            次へ
        </button>
    </div>
    ジャンル:
    <% Genre.all.each do |g| %>
        <%= check_box :genre_ids, g.name, checked:true, class:"check" %><%= g.name %> # class:"check"を追加
    <% end %><br>
    機種:
    <% Console.all.each do |t| %>
        <%= check_box :console_ids, t.name, checked:true, class:"check" %><%= t.name %> # class:"check"を追加
    <% end %><br>
   <input type="hidden" name="check" id="check"> #ここにcheckboxのtrue/falseの配列が代入され、コントローラに渡される
<% end %>
<% @checks.each do |c| %>
    <input type="hidden" id="list" value=<%= c.list %>>
<% end %>

また、同じページにjavascriptを書いていきます

gatya.html.erb
    
<%= form_tag({controller:"tweets",action:"gatya"}, method: :get) do %>

    # 省略

<% end %>

<script>
    var box = document.querySelectorAll('.check');
    function check(){
        let check_list = [];
        for (let i = 0;i < box.length;i++){
            check_list.push(box[i].checked);
        }
        document.querySelector('#check').value = check_list;
    }
    document.querySelector('#submit').addEventListener("click", check);
    var count = 0;
    for (let j = 0;j < box.length;j++){
        box[j].addEventListener("click", check);
        let check_list = document.querySelector('#list').value.split(',');
        if (check_list[j] == "true"){
            box[j].checked = true;
        }else {
            box[j].checked = false;
            count += 1;
        }
    }
    if (count == box.length){
        for (let k = 0;k < box.length;k++){
            box[k].checked = true;
        }
    }
</script>

終わりいいいいいい!!!!!!!!!!:mushroom::mushroom::mushroom::mushroom::mushroom::mushroom::mushroom::mushroom::mushroom::mushroom::mushroom::mushroom::mushroom::mushroom::mushroom::mushroom::mushroom::mushroom::mushroom::mushroom::mushroom::mushroom::mushroom::mushroom::mushroom::mushroom::mushroom:






ここまで読んでいただいてありがとうございます!!他の記事より圧倒的にわかりにくかったと思うので、全体像載せときます↓↓

gatya.html.erb
<div class="all-container">
    <h1>次やるゲームはこれだああ!!!!</h1>
    
    <%= form_tag({controller:"tweets",action:"gatya"}, method: :get) do %>
        <div class="game">
            <% if !@tweet.nil? %>
                <h1><%= @tweet.name %></h1>
            <% else %>
                <h1>no hit</h1>
            <% end %>
            <button type="submit" id="submit">
                <i class="fa-solid fa-arrows-rotate"></i>
                次へ
            </button>
        </div>
        ジャンル:
        <% Genre.all.each do |g| %>
            <%= check_box :genre_ids, g.name, checked:true, class:"check" %><%= g.name %>
        <% end %><br>
        機種:
        <% Console.all.each do |t| %>
            <%= check_box :console_ids, t.name, checked:true, class:"check" %><%= t.name %>
        <% end %><br>
        <input type="hidden" name="check" id="check">
    <% end %>
    <% @checks.each do |c| %>
        <input type="hidden" id="list" value=<%= c.list %>>
    <% end %>
</div>

<script>
    var box = document.querySelectorAll('.check');
    function check(){
        let check_list = [];
        for (let i = 0;i < box.length;i++){
            check_list.push(box[i].checked);
        }
        document.querySelector('#check').value = check_list;
    }
    document.querySelector('#submit').addEventListener("click", check);
    var count = 0;
    for (let j = 0;j < box.length;j++){
        box[j].addEventListener("click", check);
        let check_list = document.querySelector('#list').value.split(',');
        if (check_list[j] == "true"){
            box[j].checked = true;
        }else {
            box[j].checked = false;
            count += 1;
        }
    }
    if (count == box.length){
        for (let k = 0;k < box.length;k++){
            box[k].checked = true;
        }
    }
</script>
tweets_controller
class TweetsController < ApplicationController
    before_action :authenticate_user!

    def index
        if params[:search] == nil
            @tweets= Tweet.all
        elsif params[:search] == ''
            @tweets= Tweet.all
        else
            @tweets = Tweet.where("body LIKE ? ",'%' + params[:search] + '%')
        end
        if params[:genre_ids]
            if params[:genre_ids]
                @tweets = []
                params[:genre_ids].each do |key, value|
                    if value == "1"
                        tag_tweets = Genre.find_by(name: key).tweets
                        @tweets = @tweets.empty? ? tag_tweets : @tweets & tag_tweets
                    end
                end
            end
        end
        if params[:console_ids]
            @tweets = []
            params[:console_ids].each do |key, value|
                if value == "1"
                    tag_tweets = Console.find_by(name: key).tweets
                    @tweets = @tweets.empty? ? tag_tweets : @tweets & tag_tweets
                end
            end
        end
        if params[:genre]
            Genre.create(name: params[:genre])
        end
        if params[:console]
            Console.create(name: params[:console])
        end
    end
    def new
        @tweet = Tweet.new
    end
    def create
        tweet = Tweet.new(tweet_params)
        tweet.user_id = current_user.id
        if tweet.save
            redirect_to :action => "index"
        else
            redirect_to :action => "new"
        end
    end
    def show
        @tweet = Tweet.find(params[:id])
        @comments = @tweet.comments
        @comment = Comment.new
    end
    def edit
        @tweet = Tweet.find(params[:id])
    end
    def update
        tweet = Tweet.find(params[:id])
        if tweet.update(tweet_params)
            redirect_to :action => "show", :id => tweet.id
        else
            redirect_to :action => "new"
        end
    end
    def destroy
        tweet = Tweet.find(params[:id])
        tweet.destroy
        redirect_to action: :index
    end

    def gatya
        if params[:genre_ids] or params[:console_ids]
            @tweets = []
            params[:genre_ids].each do |key, value|      
                @tweets += Genre.find_by(name: key).tweets if value == "1"
            end
            params[:console_ids].each do |key, value|      
                @tweets += Console.find_by(name: key).tweets if value == "1"
            end
            @tweets.uniq!
        else
            @tweets = Tweet.all
        end
        num = @tweets.length
        @tweet = @tweets[rand(num)]

        check = Check.new
        check.list = params[:check]
        check.save
        @checks = Check.order(created_at: :desc).limit(1)
    end

    private
    def tweet_params
        params.require(:tweet).permit(:name, :image, genre_ids: [], console_ids: [])
    end
end
1
1
1

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