Riot.js + WP REST API コメントフォーム
Posted by admin at 20:24 日時 2015/12/31
最近、私の身の回りで、メガネさんがWP REST APIをAjaxで利用するコメントフォームについてブログに書いていたり、太鼓の人がそれに反応していたり、Reactで書けよオラオラしたら反応してくれたりという動きがありまして、二人とも楽しそうだなと思ったのでRiot.jsで便乗してみました。所要時間1時間半のやっつけなので、実装が微妙な点はご容赦を。
ソースはGitHubからダウンロードできます。
https://github.com/hissy/wp-commentform-riot
カスタムタグ(仮想DOM)ってやっぱり見通しいいよね
フロントエンド界隈ではReactが流行っていますが、RiotもReact的なユーザーインターフェイスのためのライブラリです。Reactっぽい発想でありつつ、できることが少ないマイクロライブラリーのため、初心者にはオススメです。
RiotはカスタムタグというHTMLとJavascriptの塊を一つにまとめる方法を提供します。それにより、ソースの見通しが大変良くなります。今回のHTMLはこんな感じになりました。
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>Commentform Demo</title>
</head>
<body>
<comment></comment>
<script src="./src/comment.tag" type="riot/tag"></script>
<script src="./node_modules/riot/riot+compiler.min.js"></script>
<script src="./bundle.js"></script>
<script>
var request = require('superagent');
riot.mount('comment', {
endpoint: 'http://wordpress.example.com/wp-json/wp/v2/comments',
post_id: 1747,
form: {
title: 'Comment',
default_message: 'Leave your comment.'
},
list: {
title: 'Comments',
}
});
</script>
</body>
</html>
comment というタグがポンと置いてあるだけ、この分かりやすさがコンポーネント化の魅力ですよね。
comment タグの中身は、さらに2つのタグに分かれています。
<comment>
<commentform name="form" />
<commentlist name="list" />
</comment>
Riot.js では、このようにタグの入れ子もできます。
commentform タグは、コメントの投稿フォームです。superagentでWP REST APIにリクエストを投げています。リクエストボディがJSONじゃないのがWP REST APIのイケてないところです。
<commentform>
<h3>{ title }</h3>
<p>{ message }</p>
<form onsubmit="{ add }">
<div>
<label for="author_name">Author Name</label>
<input id="author_name" name="author_name" type="text" />
</div>
<div>
<label for="author_email">Author Email</label>
<input id="author_email" name="author_email" type="text" />
</div>
<div>
<label for="content">Comment</label>
<textarea id="content" name="content" />
</div>
<button>Submit</button>
</form>
<hr />
var self = this
self.title = self.parent.opts.form.title
self.message = self.parent.opts.form.default_message
self.post_id = self.parent.opts.post_id
self.endpoint = self.parent.opts.endpoint
add(e) {
request
.post(self.endpoint)
.type('form')
.withCredentials()
.send({
post: self.post_id,
author_name: self.author_name.value,
author_email: self.author_email.value,
content: self.content.value
})
.end(function(err, res){
console.log('Successfully post new comment to post ' + self.post_id)
self.parent.tags.list.add(res.body)
self.author_name.value = self.author_email.value = self.content.value = ''
self.message = 'Thanks!'
self.update()
})
}
</commentform>
commentlist タグは、コメント一覧部分になります。こちらは初期化のタイミングでAPIからコメント一覧を取得して表示しています。また、add() メソッドでコメントを追加することもでき、フォームから投稿した際の返り値を一覧に追加するのに使っています。
<commentlist>
<h3>{ title }</h3>
<div each={ items }>
<h4>{ author_name }</h4>
<commentbody content="{ content.rendered }" />
<hr />
</div>
var self = this
self.title = self.parent.opts.list.title
self.post_id = self.parent.opts.post_id
self.endpoint = self.parent.opts.endpoint
request
.get(self.endpoint)
.withCredentials()
.query({ post: self.post_id })
.end(function(err, res){
console.log('Successfully retreive comments from post ' + self.post_id)
self.items = res.body
self.update()
})
add(item) {
self.items.unshift(item)
self.update()
}
</commentlist>
ということで、さくっと作ってみた実装例でした。まだあまり実務では使っていませんが、カスタムタグと処理の関係性が至極単純に書けるので、大規模なアプリケーションを作るわけでもない限り、Riot.jsは楽でいいなと思います。
ただ、今回の実装の問題点として、Ajax処理がタグに紛れてしまっているので、できれば外出ししたいところです。commentlist タグの初期化時に必ずAjaxが走るのもイケてません。その辺りのベストプラクティスは、公式のApplication Designのページに解説がありますので、時間があれば手直ししようと思います。
ということで、脱線はこのくらいにして仕事に戻ろうかと。皆様良いお年を!