右脳系エンジニアのブログ

エンジニアとしての生き方のプロトタイピング、新しい社会のプロトタイプづくりをしています。

Play!frameworkでpjaxを使ってみた

Play!framework でpjaxを使って見ました。

pushslate とはなんぞや

pjax こそが pushState + Ajax の本命 - punitan (a.k.a. punytan) のメモ
http://d.hatena.ne.jp/punitan/20110404/1301895279

こちらのサイトが大変参考になりました。
要するに

  • 非同期通信なんだけど、パーマリンクを持ってて進むとか戻るとかのボタンが使えるよ!

という非常に抽象的な解釈をしておきます。

上記のpunitan 氏のページでは、perlで実装していましたが、
これをPlay!frameworkで上手いことやってみよう!というものです。

pjaxを使えるようにするまで

pjaxを追加する

defunkt/jquery-pjax - GitHub
https://github.com/defunkt/jquery-pjax
からjquery.pjax.jsをダウンロードし、
/public/javascripts
以下に追加しますi

HTMLヘッダー(main.html)

以下の文章を追記。

<script src="@{'/public/javascripts/jquery.pjax.js'}" type="text/javascript" charset="utf-8"></script>
リンク部分(main.html)

イメージとしては何かの一覧がナビにあって、それをクリックすると
詳細の内容を表示するようなページを想定しています。

以下の文章を追記。

<ul>
#{list items:hoges ,as:'hoge'}
	<li><a class="pjax" href="/Application/show/${hoge.id}">PJAX!</a></li>
#{/list}
</ul>
<div id="main">
    #{doLayout /}
</div>
javascript
$(function(){
       $('a.pjax').pjax('#main');
})
routesファイル(conf/routes)
*    /Application/show/{id}			Application.show

としてやると、アンカーのhrefで指定した結果を#mainに描画してくれます。

java(app/controllers/Application.html)
public static void show(Long id){
     //処理内容
    render();
}

pjaxとplayのテンプレートをうまいこと使う

RESTfulなアプリケーションを考えた時このままだと、pjaxを使って非同期に読み込むまでは良いとして、このまま更新を行うとpjaxを使って描画した内容しか表示されません。

同じURLだとしても・・・

  • 直接アクセスしたらナビゲーションなどの他のHTMLも取ってくる
  • pjaxで非同期にアクセスしたらナビゲーションなどのHTMLを取得せず、内容部分だけを描画

というようにしたいはず・・・!

以下のようにしました

show.htmlを作成する

ここでは、show.htmlはmain.htmlを継承して描画する関係になっているとします。
main.htmlはヘッダーとかナビゲーションメニューとかを持っているイメージだと思ってください。普通だとこうなります

#{extends 'main.html' /}
その他の内容

pjaxを利用するとヘッダー情報にx-pjax :true という情報が追加されるので、
これがTrueだったら側の部分(main.html)を描画せず、falseだったら描画するような指定の仕方をしてやります

#{ifnot request.headers.containsKey("x-pjax")}
#{extends 'main.html' /}
#{/ifnot}その他の内容

これで、

  • URL直叩き:ヘッダーやナビゲーションメニューも一緒に描画
  • pjaxでのアクセス:mainコンテンツのみ描画

というようなことができると思います。

まとめ

いろいろ考えた結果、
Play!のフレームワーク上で実装する場合はjavaの実装部分で切り分けるより
htmlのテンプレートに記述してやるほうがごちゃごちゃしなくてよいかな〜と思い、
このような方法をとってみました。

もっとこうしたらいいよ!という方法をご存知のかたがいたら、ぜひお伺いしたいです。