LoginSignup
33
33

More than 5 years have passed since last update.

RailsでAjaxによる非同期通信を実装する練習 ~超簡易Todoアプリの作成~

Last updated at Posted at 2017-05-19

Railsを勉強して早6週間。
Ajaxによる非同期通信???な状況をようやく少し抜け出したため、復習も兼ねて学習した超簡易Todoアプリに機能を追加をしてみました。

Todoアプリ概要

https://gyazo.com/4ef1ee434093b6c44a68a0e04ef11b33
テキストフィールドに入力し「Create Todo」ボタンを押すとTodoリストが作成できます。これを非同期通信で行っていて、JavaScriptは以下の通りです。

todo.js
$(function() {

  //todoのcontentをliタグでhtmlに追加
  function buildHTML(todo) {
    var html = $('<li class="todo">').append(todo.content);
    return html;
  }

  // CreateTodoボタンが押されたら発火
  $('.js-form').on('submit', function(e) {
    e.preventDefault();  // submitによるフォームの送信を中止
    // テキストフィールドの中身を取得
    var textField = $('.js-form__text-field');
    var todo = textField.val();
    // Ajax発動!!
    $.ajax({
      type: 'POST',
      url: '/todos.json',  //createアクションへ
      data: {
        todo: {
          content: todo  //取得したテキストフィールドの中身をcontentとして送る
        }
      },
      dataType: 'json'  //もちろんjson形式で!!
    })
    .done(function(data) {
      var html = buildHTML(data);  //返ってきたデータをbuildHTMLに渡す↑↑
      $('.todos').append(html);  //作成したhtmlをビューに追加
      textField.val('');  //テキストフィールドを空に
    })
    .fail(function() {
      alert('error')
    });
  });
});

ビューとコントローラーはざっくり以下です。

index.html.erb
<div class="contents">
  <%= form_for @todo, html: { class: 'form js-form' } do |f|%>
    <%= f.text_field :content, class: 'form__text-field js-form__text-field' %>
    <%= f.submit class: 'form__submit js-submit' %>
  <% end %>
  <ul class="todos">
  </ul>
</div>
todos_controller.rb
class TodosController < ApplicationController
  def index
    @todo = Todo.new
    @todos = Todo.order('created_at ASC')
  end

  def create
    @todo = Todo.new(todo_params)
    if @todo.save
      respond_to do |format|
        format.html { redirect_to :root }
        format.json { render json: @todo }  #jsonで送られてきたら@todoをjsonで返す
      end
    else
      render :index
    end
  end

  private
  def todo_params
    params.require(:todo).permit(:content)
  end
end

doneボタンの追加

追加機能として、todoリストの横にdoneボタンを追加し、doneボタンを押すと「todoリストが青色に変化」+「doneボタンが削除」されるようにしました。

todo.js
$(function() {

  //idをtodoレコードのidで指定
  function buildHTML(todo) {
    var html = $(`<li class=todo id=${todo.id}>`).append(todo.content);
    return html;
  }

  $('.js-form').on('submit', function(e) {
    //中略
    $.ajax({
    //中略
    })
    .done(function(data) {
      var html = buildHTML(data);
      $('.todos').append(html);
      //doneボタンをaタグで追加(この時data-idにtodoレコードのidを指定)
      var button = $(`<a href="" class="done-button" data-id=${data.id}>`).append('done');
      $('.todos').append(button);
      textField.val('');
    })
    .fail(function() {
      alert('error');
    });
  });

  //doneボタンをクリックで発火
  $('.todos').on('click', '.done-button', function(e) {
    e.preventDefault();  //aタグのリンクを中止
    $(this).remove();  //doneボタンを削除
    var id = $(this).data('id');  //セットしたtodo.idを取り出す
    $(`#${id}`).addClass('blue');  //関連するtodoリストを青色に変更
  })
});

blueクラスの文字色は青で指定

todos.scss
.blue {
  color: blue;
}

ポイント

簡単にポイントをおさらいしておきます。

動的な要素にイベントを設定する

今回appendで追加したa要素をクリックした時にイベントを設定しました。
このような場合は親要素にイベントを設定する必要があります!
参照サイト

カスタムデータ属性

html要素にdata-*の形で任意の属性を追加できる!
設定した値はjQueryでdata(),attr()で取得できる!
参照サイト

テンプレートレテラル記法

JavaScriptで文字列をバックオート(`)で囲むと、${}内で変数や計算式が使える!
参照サイト

完成!!

それでは動きをみてみます。
https://gyazo.com/0c62664efda19ec385eac78a4ab87cc9
できました!これで夕飯にありつけそうです。
ありがとうございました。

33
33
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
33
33