Railsを勉強して早6週間。
Ajaxによる非同期通信???な状況をようやく少し抜け出したため、復習も兼ねて学習した超簡易Todoアプリに機能を追加をしてみました。
Todoアプリ概要
テキストフィールドに入力し「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で文字列をバックオート(`)で囲むと、${}内で変数や計算式が使える!
参照サイト