LoginSignup
6
10

More than 3 years have passed since last update.

Ajaxを使った要素の追加と自動更新

Last updated at Posted at 2019-10-15

概要

Jqueryで要素の追加と自動更新

開発環境

2019/10/16

macOs 10.14.6
ruby 2.5.1p57
Rails 5.0.7.2
mysql Ver 14.14 Distrib 5.6.43

gemfile
source 'https://rubygems.org'

git_source(:github) do |repo_name|
  repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
  "https://github.com/#{repo_name}.git"
end


# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.0.7', '>= 5.0.7.2'
gem 'mysql2', '>= 0.3.18', '< 0.6.0'
gem 'puma', '~> 3.0'
gem 'sass-rails', '~> 5.0'
gem 'uglifier', '>= 1.3.0'
gem 'coffee-rails', '~> 4.2'
gem 'jquery-rails'
gem 'turbolinks', '~> 5'
gem 'jbuilder', '~> 2.5'
gem 'devise'
gem 'rails-i18n', '~> 5.1'
gem 'carrierwave'
gem 'mini_magick'
gem 'pry-rails'

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platform: :mri
  gem 'spring'
  gem 'compass-rails'
  gem 'sprockets'
  gem 'kaminari'
  gem 'rspec-rails'
  gem 'factory_bot_rails'
  gem 'rails-controller-testing'
  gem 'faker'
  gem 'capybara'
end

group :development do
  # Access an IRB console on exception pages or by using <%= console %> anywhere in the code.
  gem 'web-console', '>= 3.3.0'
  gem 'listen', '~> 3.0.5'
  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'
  gem 'haml-rails', ">= 1.0", '<= 2.0.1'
  gem "font-awesome-rails"
end

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

要素を追加・削除するためのコード

message.js
$(document).on("turbolinks:load", function() {

    var buildMessageHTML = function(message) {
      var content = message.content                                    //jbuilderの値から追加する要素を宣言
        ? `<p class="lower-message__content">${message.content}</p>`   //リテラルテンプレート記法で+などの演算子を減らし、変数も使えるようにしている
        : ``;                                                          //三項演算子を使いデータがなかった場合は空文字をいれる
      var image = message.image.url
        ? `<img src="${message.image.url}"class="lower-message__image">`
        : ``;
      var html = `<div class="message" data-id=${message.id}>         
                    <div class="upper-message"> 
                      <div class="upper-message__user-name"> 
                        ${message.user_name} 
                      </div> 
                      <div class="upper-message__date"> 
                        ${message.created_at} 
                      </div> 
                    </div> 
                    <div class="lower-message"> 
                      ${content}
                      ${image}
                    </div>
                  </div>`;
      return html;                                                 //jsではrubyと違ってreturnで返り値を示さないといけない
    };

    var reloadMessages = function() {
      last_message_id = $(".message:last").data("id");            //:lastで指定してる要素の最後を取得          
      group_id = $(".chat-main").data("id");                      //カスタムデータ属性からdataメソッドを使ってpathに必要なidを取得
      $.ajax({                         
        url: `/groups/${group_id}/api/messages`,
        type: "get",
        dataType: "json",
        data: { id: last_message_id }
      })
        .done(function(messages) {
          var insertHTML = "";
          messages.forEach(function(message) {
            insertHTML = buildMessageHTML(message                 //要素を追加するメソッドを呼んでforEachで取得したデータの分だけ繰り返す
          });
          $(".messages").append(insertHTML);                     //appendで指定したクラスの下に要素を追加
          $(".messages").animate({ scrollTop: $(".messages")[0].scrollHeight }); //メッセージ画面を下までスクロール//animatメソッドで引数によって、スクロールのコントロールできる
        })
        .fail(function() {
          alert("更新に失敗しました");
        });
    };

   if ($(".chat-main").length) {
    autoReload = setInterval(reloadMessages, 5000); //5秒毎にメソッドを発火
   } else {
    clearInterval(autoReload);                   //メソッドの繰り返しをストップ
   }
});

説明

細かい説明はコメントでしています

今回はクラス名の要素の有無で発火を分岐させていたがURlでも指定できる

特定のページでのみjsを発火させる方法

removeメソッドを使えば要素の削除もできます。
jsで追加した動的要素に対してイベントを発火させたいときは 下記を使うらしいです!!
$(document).on("turbolinks:load", function() { 

参考ページ

Rails + jQueryでインクリメンタルサーチ(基礎)
RubyOnRails/インクリメンタルサーチの実装

最後に

少しでも学習の助けになればいいなと思います
ミスや間違いがあった場合はすみません!!

6
10
0

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
6
10