#動作の流れ
まず今回実現したい動作について説明します。
#フォームの内容を入力したときのイベント
1のフォームに入力してEnterキーを押したときのイベント処理を考えていきます。
##onメソッド
セレクタ.on('イベント',関数);
とすると、
セレクタで指定したHTML要素に第1引数のイベントが発生したときに、第2引数の関数が実行されます。
セレクタ.イベント(関数);
で、
clickイベントなどはonとだいたい同じように使うことができます。
しかし、このようなイベント名のメソッドは、onメソッドと違って、jQueryなどで動的に作成したHTMLタグに対しては動作してくれません。
今回はフォームの内容をリスト上で動的に追加するので、onメソッドで統一しておきます。
##changeとsubmit
入力フォームに内容を入力してEnterキーを押したときに、2~4の処理を実行したいわけですが、どのイベントを使ったらいいのでしょうか。
フォームに関するイベントには
・changeイベント
・submitイベント
があります。
changeイベントはフォーム部品の状態が変化したときに発生します。
一方submitはフォームが送信されたときに発生します。
今回のページでは入力フォームが1つだけなので、Enterを押したらフォームが送信されます。
ですから、submitイベントがよさそうです。
##ページ遷移したくない!
とりあえず、onメソッドでsubmitイベントがちゃんと発生するか調べてみます。
但し、"#new_todo_form"はform要素につけたIDです。
$('#new_todo_form').on('submit', function(){
console.log("success");
/* 2~4の処理 */
});
↓
ページが更新されてしまいました!
formタグでページの遷移先は指定していないので、同じページが再読み込みされたのでしょう。
「新しいページにしなくていいから、そのままでいて・・・。」
そう思って、私はchangeメソッドでもいろいろ試したりしていたわけですが、実はたった1行書き加えるだけでよかったんですよね・・・。
return false;
これをonメソッドの第2引数の関数の末尾に書けば、ページ遷移を防ぐことができるのです。
#データベースに挿入
onメソッドの第2引数の関数を作っていきます。
サーバーのデータベースに非同期でアクセスしたいので,
Ajax処理を利用していきます。
$('#new_todo_form').on('submit', function(){
// idを取得
var title = $('#new_todo').val();
//ajax処理
$.post('_ajax.php',{
title: title,
mode: 'create',
token: $('#token').val()
},function(res){
/*3の処理*/
});
});
$.post(’データの送信先’,{key:data},functoin(res){});
とすると、formタグのmethod属性をpostにしたときと同じように
’データの送信先に’dataを送れます。
また、送信先の_ajax.phpで、echoなどで出力された内容が、送信先の処理が終わった後に実行される関数の引数resで受け取ることができます。
##_ajax.phpの作成
$todoApp = new \MyApp\Todo();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
try {
$res = $todoApp->post();
header('Content-Type: application/json');
echo json_encode($res);
exit;
} catch (Exception $e) {
header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error', true, 500);
echo $e->getMessage();
exit;
}
}
Todo.phpに記述したTodoクラスのメソッドpost()を呼び出すと、mode:createの場合に、データベースに新しくデータを挿入するcreateメソッドを呼ぶようにしています。
返す値は扱いやすいようにjsonコードにしておきます。
##createメソッドの作成
private function _create(){
if(!isset($_POST['title'])|| isset($_POST['title']) === ''){
throw new \Exception('[create] title not set!');
}
$sql = "insert into todos (title) values (:title)";
$stmt = $this->_db->prepare($sql);
$stmt->execute([':title' => $_POST['title']]);
return ['id' => $this->_db->lastInsertId()];
}
postで送信したデータを$_POST['key']
で呼び出します。
フォームの内容が空じゃないかどうか調べて、throwで例外処理を発生させます。
フォームから受信したデータが空じゃなかったら、
insert文を使ってデータを挿入していきます。
プレースホルダーを使って出力します。
これはSQLインジェクション対策なのですが、XSS対策とSQLインジェクション対策で少し説明しているので、参考にしていただければ幸いです。
最後に追加した内容のIDを取得して、連想配列で返します。
これは_ajax.php上でjson形式に変換されます。
#テンプレートをcloneメソッドで複製
入力データをHTML要素として挿入する時には、テンプレートがあって、属性値や、タグの中身にデータを入れるだけにしておくと便利そうですよね。
そこで、idex.php上にこのようなテンプレートを作っておきます。
<li id="todo_templete" data-id="">
<input type="checkbox" class="update_todo">
<span class="todo_title"></span>
<div class="delete_todo">x</div>
</li>
テンプレートをセレクタで指定して、cloneメソッドを使うと、複製することができます。
複製した要素にattrメソッドやdataメソッド、textメソッドなどをデータを挿入していきます。
そして、prependメソッドでリストの先頭に複製した要素を挿しこみます。
function(res){
//liを追加 index.phpのテンプレ―を複製
var $li = $('#todo_templete').clone();
$li
.attr('id','todo_' + res.id)
.data('id',res.id)
.find('.todo_title').text(title);
$('#todos').prepend($li.fadeIn());
$('#new_todo').val('').focus(); //空にしてfocusを当てて連続で入力可能に
}
フォームに連続して入力できるようにしたいので、val('')でフォームの中身を空にして、focusを当てておきました。