前回は、ToDo項目にチェックすると、AJAXでサーバーにデータを送信して、完了日時をエンティティに登録し、データベースを更新するところまで実装した。
この状態でToDo項目の画面にアクセスすると、完了済みの項目が未完了に表示されてしまう。
未完了のToDo項目と、完了済みのToDo項目をそれぞれの領域に表示するよう修正する。
<!DOCTYPE html> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>ToDoアプリ</title> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <script type="text/javascript"> $(function(){ $('input[name="item"]').change(function(){ console.log($(this).parent()); $('#done').append($(this).parent()); $.post('done', 'id=' + $(this).val()); }); }) </script> </head> <body> <h1>ToDo項目</h1> <form method="post" action="input"> <input type="text" name="item"> <input type="submit" value="登録"> </form> <c:if test="${list != null}"> <form method="post" action="check"> <c:forEach var="t" items="${list}"> <c:if test="${t.done == null}"> <div id="check${t.id}"> <input type="checkbox" name="item" value="${t.id}" />${t.item} </div> </c:if> </c:forEach> </form> </c:if> <hr /> <h3>完了済み</h3> <div id="done"> <c:if test="${list != null}"> <c:forEach var="t" items="${list}"> <c:if test="${t.done != null}"> <div id="check${t.id}"> <input type="checkbox" name="item" value="${t.id}" checked="checked" />${t.item} </div> </c:if> </c:forEach> </c:if> </div> </body> </html>
テキストフィールドに入力して「登録」ボタンを押すと、テキストフィールドが完了済みに移動してしまう問題を解決する。
jQueryで input[name=”item”] というセレクタを指定していると、これがテキストフィールドにも該当してしまう。
チェックボックスのnameをitemsに変更してchangeイベントを拾うところもinput[name=”items”]とする。
<!DOCTYPE html> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>ToDoアプリ</title> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <script type="text/javascript"> $(function(){ $('input[name="items"]').change(function(){ console.log($(this).parent()); $('#done').append($(this).parent()); $.post('done', 'id=' + $(this).val()); }); }) </script> </head> <body> <h1>ToDo項目</h1> <form method="post" action="input"> <input type="text" name="item"> <input type="submit" value="登録"> </form> <c:if test="${list != null}"> <form method="post" action="check"> <c:forEach var="t" items="${list}"> <c:if test="${t.done == null}"> <div id="check${t.id}"> <input type="checkbox" name="items" value="${t.id}" />${t.item} </div> </c:if> </c:forEach> </form> </c:if> <hr /> <h3>完了済み</h3> <div id="done"> <c:if test="${list != null}"> <c:forEach var="t" items="${list}"> <c:if test="${t.done != null}"> <div id="check${t.id}"> <input type="checkbox" name="items" value="${t.id}" checked="checked" />${t.item} </div> </c:if> </c:forEach> </c:if> </div> </body> </html>
pom.xmlにJSONを扱うためのライブラリを追加する。
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.8.8</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.8.9</version> </dependency>
追加したら、[maven]-[プロジェクトの更新]と[実行]-[maven install]を実行する。
ToDo項目を更新するための /done に対してPOST送信したら、その応答で、JSONデータを返すようにする。
@RequestMapping(value = "/done", method = RequestMethod.POST) @ResponseBody @ResponseStatus(value = HttpStatus.OK) public List<ToDo> done(@RequestParam(value = "id") String id, Model model) { ToDoDao<ToDo> dao = new ToDoDaoImpl(); ToDo todo = dao.findById(Long.parseLong(id)); todo.setDone(new Date()); dao.update(todo); List<ToDo> list = dao.getAll(); return list; }
jQueryでPOSTしたときに応答を受信してJavaScriptコンソールにデータを出力してみる。
<script type="text/javascript"> $(function(){ $('input[name="items"]').change(function(){ console.log($(this).parent()); $('#done').append($(this).parent()); $.post( 'done', 'id=' + $(this).val(), function(data) { console.log(data); }); }); }) </script>
チェックして、サーバーからデータを受け取ったら、受け取ったデータに基づいてToDo項目を更新する。
まずは、既存の項目をすべて削除する。
<script type="text/javascript"> $(function(){ $('input[name="items"]').change(function(){ console.log($(this).parent()); $('#done').append($(this).parent()); $.post( 'done', 'id=' + $(this).val(), function(data) { console.log(data); $('#todo form').children().remove(); $('#done').children().remove(); }); }); }) </script>
受信したJSONデータにもとづいてdiv要素を作り直す。
完了日時が設定されていなければ未完了側に、設定されていれば完了側にdiv要素を追加する。
$(function(){ $('input[name="items"]').change(function(){ console.log($(this).parent()); $('#done').append($(this).parent()); $.post( 'done', 'id=' + $(this).val(), function(data) { console.log(data); $('#todo form').children().remove(); $('#done').children().remove(); for (var i = 0; i < data.length; i++) { var div = $('<div>'); div.attr('id', 'check' + data[i].id); var cb = $('<input>') .attr('type', 'checkbox') .attr('name', 'items') .attr('value', data[i].id); div.append(cb).append(data[i].item); if (data[i].done == null) { $('#todo form').append(div); } else { cb.attr('checked', 'checked'); $('#done').append(div); } } }); }); }) </script>