「CFDIV」というのはバージョン8で追加された新しいタグです。今までにもあったような「CFINPUT」と同様にHTML的な要素とは別の機能を持っています。「DIV」と名前が付いているのでもちろんHTMLと同じようにボックス(領域)と同じような挙動をします。但し、「tagName」という属性がありこの属性に他のHTMLタグ名をセットすることでDIV以外のHTMLでも使用可能です。
さて、前述の「HTML的な要素とは別の機能」というのが本題のタイトルにもあります「Ajax」の機能です。「bind」という属性があり、この属性に設定したCFM/CFCのレスポンス結果が非同期にロードされます。図1を観ていただくと想像できると思います。
図1:CFDIVの挙動
このように一度ページを表示した後に非同期にページの一部分を別途ロードできますので、重たい処理をページ処理とは別に実行するなどの用途も考えられます。
また、「bind」属性にはサーバーサイドのURLやCFCだけでなくJavaScriptを指定することもできます。JavaScriptを指定する場合は戻り値に文字列を返す必要があります。サーバーにコンテンツをリクエストするのではなく、ブラウザ上のJavaScriptでコンテンツを動的に生成して表示することも可能です。
では、このCFDIVのキー要素である「bind」属性の各パターンにおける使い方を観てみましょう。
まずはこちらのサンプルをご覧下さい。コンボボックスの選択項目を変更するとコンテンツの内容も変更されます。では、ソースを見てみましょう(サンプルページの「view source」ボタンをクリックするとソースが表示されます)。
bind="JavaScript:divSource({itemSelection.value})"
「bind」属性にJavaScriptを指定するには上記のように「bind="JavaScript:関数名"」とします。ここで注目すべきは「{itemSelection.value}」という記述です。{}(中括弧)で囲んでいるのがポイントです。囲まなくても一応機能します。「一応」というのはロード時にはコンテンツは表示されるのですが、コンボボックスの内容が変化してもコンテンツは変化しません。この{}記述はDOMの「change」イベントに対応させるものです。つまり、HTMLのSELECTタグ(idが「itemSelection」)の「value」属性が変化した時にも「bind」の内容を実行するということを意味します。
「divSource」というのはJavaScriptで定義した関数です。ここで一つ注意点として、Ajaxを利用するJavaScriptの関数定義の仕方は下記のようにする必要があります。
divSource = function(item)
「function 関数名(引数)」という記述ではなく「関数名 = function(引数)」とする必要があります。これはCFでAjax系コンポーネントを利用する場合の決まり事です。
「divSource」というJavaScript関数は「return outputHTML;」のように文字列を返しています。この戻り値はDOMでいう「innerHTML」にセットされると思ってください。
まずはこちらのサンプルをご覧下さい。コンボボックスの選択項目を変更するとコンテンツの内容も変更されます。では、ソースを見てみましょう(サンプルページの「view
source」ボタンをクリックするとソースが表示されます)。
bind="JavaScript:divSource({itemSelection.value})"
「bind」属性にJavaScriptを指定するには上記のように「bind="JavaScript:関数名"」とします。ここで注目すべきは「{itemSelection.value}」という記述です。{}(中括弧)で囲んでいるのがポイントです。囲まなくても一応機能します。「一応」というのはロード時にはコンテンツは表示されるのですが、コンボボックスの内容が変化してもコンテンツは変化しません。この{}記述はDOMの「change」イベントに対応させるものです。つまり、HTMLのSELECTタグ(idが「itemSelection」)の「value」属性が変化した時にも「bind」の内容を実行するということを意味します。
「divSource」というのはJavaScriptで定義した関数です。ここで一つ注意点として、Ajaxを利用するJavaScriptの関数定義の仕方は下記のようにする必要があります。
divSource = function(item)
「function 関数名(引数)」という記述ではなく「関数名 = function(引数)」とする必要があります。これはCFでAjax系コンポーネントを利用する場合の決まり事です。
「divSource」というJavaScript関数は「return outputHTML;」のように文字列を返しています。この戻り値はDOMでいう「innerHTML」にセットされると思ってください。
まずはこちらのサンプルをご覧下さい。白い枠がCFDIVの領域です。で、コンボボックスの内容を変更すると領域の文字が変更されます。では、ソースを観てみましょう。
bind="url:#baseURL#divsource.cfm?item={itemSelection}"
「bind」属性にWebページを指定する場合は上記のように「bind="url:WebページのURL"」とします。サンプルのように「?」の後にURL変数を付加することができます。そしてここでも{
}(中括弧)が出てきます。これもJavaScriptの場合と同様にSELECタグの「value」属性が変更された場合にも「bind」の内容が実行され、コンテンツ領域だけがリロードされます。このサンプルでは「value」を省略していますが、「change」イベントを検知する属性を省略するとデフォルトで「value」が参照されます。
まずはこちらのサンプルをご覧下さい。白い枠がCFDIVの領域です。で、コンボボックスの内容を変更すると領域の文字が変更されます。先ほどのURLの場合と全く同じですがFireFoxで表示した場合は若干挙動が違います。先のほどのURLの場合はコンボボックスの内容を変更したときに一瞬、白い枠が消え、また表示されますが、こちらは何事も無かったかのようにコンテンツが変更されます。これは明らかにURLの場合とCFCの場合でロード⇒コンテンツ表示のシーケンスが違うからですが、HTTPのリクエストを投げていることには変わりません。では、ソースを観てみましょう。
bind="cfc:#dotPath#.divsource.setItem({itemSelection.value})"
「bind」属性にCFCを指定する場合は上記のように「bind="cfc:CFCのパス"」とします。但し、「CFCのパス」の表記方法はURLと異なり、「ドット表記」になります。サンプルでは「dotPath」と変数になっていますが、実際は
bind="cfc:cf_samples.samples.cfdiv.cfdiv02.divsource.setItem
と、WebルートからのWebパスをドット表記に変更したものです(ですが、「/」表記でも動作することがあります)。注意点としてはAjax機能で使用されるCFCは必ずWebからアクセスできる位置に配置しなければならないということです。つまり、「マッピング」や「classes」フォルダにあるCFCを参照したりはできないということです。
最後にCFDIVを使用したAjaxフォームのサンプルをご紹介いたします。ソースを見ていただくとお分かりになると思いますが、フォーム機能をCFDIVを使用してロードしています。
<cfdiv id="div04" bind="url:#baseURL#form.cfm" />
ロードされたフォームに適当な値を入力し「submit」ボタンを押下してみて下さい。
いかがでしょうか、ページ全体はリフレッシュされずフォーム、つまりCFDIVの領域だけがリフレッシュされました。但し、これにはCFDIV以外のトリックがあります。それはフォームに「CFFORM」を使用していることです。HTMLの「form」タグではどうでしょうか。実はページ全体がリフレッシュされてしまいます。また、データをPOSTした後に表示されるページの「Back」ボタンですがこちらも実は「CFFORM」で囲み「POST」メソッドを使用しています。コメントにあるように「GET」メソッドを使用するとページ全体がリフレッシュされてしまいます。また、当然のことながらブラウザの「バック」ボタンやJavaScriptの「window.history.back()」関数も使用できません。この辺りの制限もよく理解した上でシステムやWebページに製作する必要があります。
以上で【簡単Ajaxフォーム「CFDIV」】は終了です。