force.comのVisualforceページにおいてajaxを行う方法について書いてみる。
1. <apex:commandButton>等のrerender
<apex:commandButton>
等のコントローラのメソッドを呼び出す処理を行うタグに対して
rerender属性(メソッド呼び出しの結果、再描画するエリア指定)を設定することで、メソッド呼び出し部分をsubmitではなくajaxで処理するというもの。
apexタグで記載された表示を再描画する場合には有効。
例えば、<apex:pageBlockTable>
で一覧表示したデータをメソッド呼び出し後に再描画するとか。
コールバック処理はoncomplete属性に書き込むことになる。
2. <apex:actionFunction>
コントローラのあるメソッドの呼び出しをJavaScript関数の呼び出しで実現できるようにするためのタグ。
1と同様にrerender,oncomplete属性を持たすことが可能。
1の場合はapexタグで指定されたボタンやリンクのクリックと自動的に関連付けられてajax処理が行われるが、
<apex:actionFunction>
の場合は、グローバルスコープにJavaScript関数が定義されることにより、
任意のJavaScript処理内にコントローラのメソッド呼び出し(ajax)処理を埋め込むことが出来るのが利点。
1,2ともにメリット、デメリットは以下の通り
メリット
- インスタンスメソッドの呼び出しなので、コントローラの状態(ViewState)を変更することが出来る
- 再描画処理を自動的にSalesforceが行ってくれる(JSオンリーの場合はajaxによるデータ取得→取得したら自前DOM操作という流れ)
デメリット
- 任意の引数を渡し辛い(
<apex:inputHidden>
などを利用すれば行けるが、コントローラにインスタンス変数が増える) - 任意の返り値を返す処理が書きづらい(非表示にしたタグで返り値実装できるが、コントローラにインスタンス変数が増える)
- oncomplete属性によるコールバックで、通常のajax的な書き方とは異なり、jQuery deffered等の技術が使いづらそう(出来ないことは無さそうだけど…)
3. @RemoteAction
メソッドに@RemoteActionアノテーションを付与して、静的メソッドとすることで
VisualforceページのJavaScriptによる呼び出し(ajax)ができる仕組み。
こちらはVFページのコントローラのインスタンスと紐付いていないため、
- 再描画処理などが出来ない→再描画する場合は自前DOM操作 * コントローラの状態(ViewState)の変更ができない→更新する必要がある場合は、別途仕組みを作らないとダメ。
というデメリットが有る一方、
* メソッドに渡せるパラメータをJavaScript側で自由にコントロールできる * コールバックを含む一連の処理が普通に書ける。(oncomplete属性による擬似的な?コールバックではないのでdefferedが使える!) * メソッドの返り値が自由にコントロールできる。
というメリットが有るため、
apexタグなんかに頼らずに自前JavaScriptで実装するぜ!
っていうタイプには向いている方法。
4. 自前ajax(jQueryの$.ajax等)
Visualforceページに自前RESTページを作成し、自前RESTページにhttpリクエストをajaxで投げて実装する方法。
例えば、REST.pageというVFページを作成し、コントローラ(REST.cls)のコンストラクタあるいは初期処理(apex:pageのaction属性)で URLパラメータに応じたデータ操作を行うように実装して、呼び出し元のVFページ内で
$.ajax({
url: "/apex/REST",
data: {
action : "select",
name : "test"
}
})
ってな感じで呼び出せばOK。
メリット・デメリットは3と同様。
3との違いは完全に自由なAPIを設計できる一方で、CSRFを自前で対策しないといけないところ。
(1, 2, 3はSalesforceが自動的にCSRFトークンを生成・送信してくれます)
まとめ
- 処理実行→実行結果を元に再描画等の処理であれば1,2
- JavaScript処理の為のデータ取得・SFDCをDBとしたJavaScriptゴリゴリのアプリを作る場合は3,4
って感じでしょうかね。
VFのViewState突破するとかで3,4を利用するのも有りかもしれないけど、それなりのコストは掛かるかと思います。