Ajaxサポート
イントロダクション
Ajaxは、Asynchronous Javascript and XMLの略語であり、リッチウェブアプリケーションへの移行を支える原動力となっています。一般に、このようなタイプのアプリケーションは、Rubyや Groovyのような言語でかかれたアジャイルで、ダイナミックなframeworkによく合います。Grailsは、Ajaxタグライブラリを通して、 Ajaxアプリケーションの開発をサポートします。Ajaxタグライブラリ詳細については、タグライブラリリファレンスを参照してください。
Rails開発者は、ほとんどのGrailsのAjaxタグがRailsのヘルパーメソッドに等しいので、そのタグライブラリに精通しているでしょう。
適応性のあるAjaxタグ
GrailsのタグのRailsとの大きな違いの一つは、Prototypeライブラリに縛られないことです。GrailsのAjaxタグを機能させるには、HTMLドキュメントの"head"タグ内にサポートするAjaxライブラリを指定する必要があります。
PrototypeのAjaxは:
<g:javascript library="prototype" />
Yahoo UIのAjaxは:
<g:javascript library="yahoo" />
DojoのAjaxは:
<g:javascript library="dojo" />
そして、基本的な実装の詳細を知らなくても以下のドキュメントで説明されるようにタグを使用することができます。このことは、必要な機能を提供するのはどのライブラリがもっとも適切かを選択することを可能にします。
Dojoのインストール
もしdojoの利用を選択するのであれば、大きなフレームワークであるため、Grailsにバンドルすることはできないのでインストールが必要で す。幸いGrailsはdojoをインストールするためのantのtargetを提供します。Grailsプロジェクトのルートから以下のようにタイプす ると、自動的にdojoはダウンロードされ設定されます:
grails install-dojo
リモートコンテントのロード
リモートコンテントはいくつかの方法でロードすることができ、もっとも一般的方法は"remoteLink"タグを使うことです。このタグは非同期 なリクエストを実行して、任意のエレメントにレスポンスをはめ込むHTMLアンカータグの作成を可能にします。最も簡単なリモートリンクを生成する方法は 以下の通りです:
<g:remoteLink action="delete" id="1">Delete Book</g:remoteLink>
上記リンクは、現在のコントローラの"delete"アクションに引数id="1"として非同期リクエストを送信します。これはすばらしいのですが、通常何が起こったかに関して、ある種のフィードバックをユーザに提供したいでしょう:
def delete = {
def b = Book.get( params.id )
b.delete()
render "Book ${b.id} was deleted"
}
<div id="message"></div> <g:remoteLink action="delete" id="1" update="message">Delete Book </g:remoteLink>
上の例は、actionをcallして、この場合"Book 1 was deleted"というレスポンスを"message"というdivのコンテンツに設定するでしょう。このタグの"update"属性には、更新が失敗し た場合どこに表示するかを示すマップを指定することも可能です:
<div id="message"></div> <div id="error"></div> <g:remoteLink action="delete" id="1" update="[success:'message',failure:'error']">Delete Book </g:remoteLink>
ここでは、リクエストが失敗した場合、error divに表示されるでしょう。
イベントのハンドリング
あるイベントが発生した場合、特定のjavascriptをコールすることが可能です、ここですべてのイベントには頭に"on"が付いています。そしてユーザーを相応しい場所にフィードバックさせたり他のアクションに移動させたりすることが可能です:
<g:remoteLink action="show" id="1" update="sucess" onLoading="showProgress();">Show Book 1 </g:remoteLink>
上記コードはプログレスバーを表示するあるいはそれに相当するような関数"showProgress()"を実行するでしょう:
- onSuccess (オプション) - 成功の場合に呼び出されるjavascript関数
- onFailure (オプション) - 失敗の場合に呼び出されるjavascript関数
- on_ERROR_CODE (オプション) - 指定のエラーコードに対処するためによばれるjavascript関数 (例えば on404="alert('not found!')")
- onUninitialized (オプション) - ajaxエンジンが初期設定に失敗した場合に呼ばれるjavascript関数
- onLoading (オプション) - リモート関数がレスポンスをロードする時に呼ばれるjavascript関数
- onLoaded (オプション) - リモート関数がレスポンスのロードを終了する時に呼ばれるjavascript関数
- onComplete (オプション) - リモート関数が更新を含むいかなる処理も終了する時に呼ばれるjavascript関数
リモートからフォームをサブミット
また、HTMLフォームを非同期にサブミットするには2つの方法があります。最初は"formRemote"タグを使う方法で、"remoteLink"タグと同じ属性で利用できるでしょう:
<g:formRemote url="[controller:'book',action:'delete']" update="[success:'message',failure:'error']"> <input type="hidden" name="id" value="1" /> <input type="submit" value="Delete Book!" /> </g:formRemote >
あるいはリモートからサブミットできアクションに依存しないような"submitToRemote"ボタンを使用することができます:
<form action="delete"> <input type="hidden" name="id" value="1" /> <g:submitToRemote action="delete" update="[success:'message',failure:'error']" /> </form>
AjaxとRenderメソッド
Grailsのrenderメソッドは、多くの場合Ajax応答を生成ための最も適切な手法です。例として現在の日付と時間を表示するものを見てみましょう:
...
// controller action
def time = {
render "${new Date()}"
}
...
<g:remoteLink action="time" update="time">Get Time</g:remoteLink>
<div id="time">Time to be displayed here</div>
ここではrednerメソッドが現在の時刻を"time" divに表示させます。しかしrenderメソッドはマークアップを表示させることもできます:
...
// controller action
def time = {
render(contentType:'text/xml') {
time(new Date())
}
}
...
// resulting response
<time>(the current time)</time>
また同じビルダーシンタックスを使ってJSONレスポンスを表示させることにより、さらによくなります:
...
// controller action
def time = {
render(builder:'json') {
time(new Date())
}
}
...
// resulting JSON response
{ time: "..." }
もしOpenRicoフレームワークを利用したいのであれば、OpenRiceレスポンスを生成できます:
...
// controller action
def time = {
render(builder:'rico') {
element(id:'time') {
new Date()
}
}
}
...
// resulting Rico response
<ajax-response>
<response type="element" id="time">
... // current time here
</response>
</ajax-response>