【Rails5】Ajaxでビューに要素を追加する方法と、それに対してjQueryでイベントハンドラを設定する方法

【Rails5】Ajaxでビューに要素を追加する方法と、それに対してjQueryでイベントハンドラを設定する方法:


概要

以下の項目について、Rails初心者の私が躓いた部分がいくつかあったので、

備忘録を兼ねて、シンプルなコードを例に知見を共有します。

  • Rails5系でAjaxを使用する方法
  • 動的に生成したDOM要素に対してjQueryでイベントハンドラを設定する方法


目標とする動作



824cb2b7a55ed598b5cb1363455f3dc6.gif



Rails5系でAjaxを使用する方法

先程のgifでいうところの、各ニュースタイトルの横にある『あとで読む』ボタン押下後、

『あとで読むリスト』にその項目をAjaxで追加する部分について解説します。


ビュー

こちらが、ビューのソースコードです。

(erbはQiita側のシンタックスハイライトが上手く効かなかった:sob:)

home.html.erb
#読売新聞の記事一覧を表示するテーブル。 
        #@all_newsには最新のニュースに関する全てのレコードが入っている。 
         <table class="latest_news_table"> 
      <thead> 
        <tr> 
          <th>タイトル</th> 
          <th></th> 
        </tr> 
      </thead> 
      <tbody> 
        <% @all_news.each do |news| %> 
        <tr> 
          <td><%= link_to  news.title, news.link %></td> 
          #あとで読むボタンには、各ニュースに対応したidが付与されている 
          <td><span class="btn btnAtode" id=<%= news.id %>>あとで読む</span></td> 
        </tr> 
        <% end %> 
      </tbody> 
    </table> 
 
    #あとで読む記事を表示するテーブル。 
    #all_atodesにはあとで読む予定のニュース記事に関する全てのレコードが入っている。 
        <table class="atode_news_table"> 
      <thead> 
        <tr> 
          <th>タイトル</th> 
          <th></th> 
        </tr> 
      </thead> 
      <tbody> 
        <% @all_atodes.each do |atode| %> 
        <tr> 
          <td><%= link_to  atode.title, atode.link %></td> 
          <td><span class="btn btnDokuryo" id=<%= atode.id %> method: :delete>読了</span></td> 
        </tr> 
        <% end %> 
      </tbody> 
    </table> 


Ajax処理を行うjsファイル

app/assets/javascripts配下に作成しました。

Ajax.js
$(function () { 
   //あとで読むボタンに対するイベントハンドラ 
   $(".btnAtode").click(function() { 
    //ボタンのidを取得し、後述するatodeアクションに渡す。 
    return $.ajax({ 
      url: 'ajax/atode',//routes.rbの記述で、このurlとコントローラーのアクションを対応付ける 
      type: 'post', 
      data: { set_id: $(this).attr('id') },//アクションに渡したいデータ 
      dataType: 'json', 
      async: true, 
    //コントローラーから無事にjsonが帰ってきた際の動作 
    }).done(function(response) { 
      //atodeアクション終了後の動作。あとで読むリストに項目を追加 
      //response[0]にニュースのタイトル、[1]にurl、[2]にidが格納されている 
      $(".atode_news_table").append( 
        "<tr><td><a href="  
                    + response[1] + ">" + response[0] 
          + "</a></td><td><span class='btn btnDokuryo' id=" 
          + response[2] + " method: :delete>読了</span></td></tr>" 
      ) 
    //コントローラーからjsonが帰ってこなかった時の動作 
    }).fail(function() { 
        alert("失敗しました"); 
    }); 
  }); 
 }); 


コントローラー

あとで読むボタンのクリックに対応したアクションです。

home_controller.rb
def atode 
        #あとで読むボタンが押された場合、ボタンに付与されたidをもとにNewsテーブルからニュースを取得 
    @cheked_news = News.find(params[:set_id]) 
    #取得したニュースと同じ内容をAtodeテーブルに記録 
    @atode_news = Atode.create(source: @cheked_news.source, title: @cheked_news.title,  
                                link: @cheked_news.link, checked: true) 
    #各値をjsonに格納して、ajax.jsに返却 ajax.jsではresponse[0]〜[2]として扱われる 
    render json: [@cheked_news.title, @cheked_news.link, @atode_news.id] 
  end 


動的に生成したDOM要素に対して、jQueryでイベントハンドラを設定する方法

先程のgifでいうところの、Ajaxで『あとで読むリスト』に追加された項目の『読了』ボタンを押すと

記事が消えていく動作について解説します。

方法としてはajax.jsの『あとで読むリスト』に各値を追加

イベントハンドラを設定するだけです。

以下、先程のajas.jsに一部加筆

Ajax.js
//略 
}).done(function(response) { 
      $("#atode-table").append( 
        "<tr>" + 
          "<td><a href=" + response[1] + ">" + response[0] 
          + "</a></td>" 
          + "<td><span class='btn btn-info btn-sm btnDokuryo' id=" 
          + response[2] + " method: :delete>読了</span></td></tr>" 
      ) 
      //以下加筆箇所 
            //読了ボタンに対するイベントハンドラ 
      $(".btnDokuryo").click(function(){ 
        let set_id = Number( $(this).attr('id') ) 
        return $.ajax({ 
          url: 'ajax/done', 
          type: 'delete', 
          data: { set_id }, 
          dataType: 'json', 
          async: true, 
        //response[0]に削除したい項目のidが格納されている 
        }).done(function(response) { 
          //あとで読むリストの項目を削除 
          var done_article = $("#" + response[0]).closest("tr").remove(); 
          $(done_article).remove(); 
        }).fail(function() { 
        }); 
      }) 
//略 
 


まとめ

Ajaxの使い方については、シンプルなコードを載せてみました。

必要箇所をコピペしてお使い下さい。

また、Ajaxで動的に生成したDOM要素に対しては、

その要素を追加にイベントハンドラを設定する所がポイントです。

私は別のjsファイルを作成し、そちらでイベントハンドラを設定していましたが、

Ajaxで追加した項目についてはclickイベントが拾えず悩んでしまいました...。

同様の悩みを抱えている方の助けになれば幸いです。

コメント

このブログの人気の投稿

投稿時間:2021-06-17 22:08:45 RSSフィード2021-06-17 22:00 分まとめ(2089件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)