search
LoginSignup
0

posted at

updated at

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

やりたいこと

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

実装したらこんな感じ

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

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
What you can do with signing up
0