Wednesday, August 03, 2005

AJAX with Ruby on Rails

ใน package ของ Rails จะมี Helper ที่ชื่อ JavaScriptHelper
ที่ช่วยให้เราใช้ AJAX Feature ของ Prototype และ script.aculo.us ใน view ของเราได้ง่ายขึ้น

ตัวอย่างการใช้งาน
เริ่มต้นด้วยการ copy javascript ที่ต้องใช้ไปไว้ที่
directory project/public/javascripts
โดยมี javascript ทั้งหมด 4 ตัว
  • prototype
    • prototype.js (จาก prototype)
  • script.aculo.us
    • effects.js
    • dragdrop.js
    • controls.js

ใน view ที่ต้องการใช้ AJAX Feature ก็ให้ทำการ
include ด้วยคำสั่ง javascript_include_tag
<head>
<%= javascript_include_tag "prototype" %>
<%= javascript_include_tag "effects" %>
<%= javascript_include_tag "dragdrop" %>
<%= javascript_include_tag "controls" %>
</head>

Note: กรณีที่ใช้ script.aculo.us จำเป็นต้องมีการ
patch prototype.js เสียก่อน (ตัว patch หาได้ใน web site ของ script.aculo.us)


ใน prototype จะมี feature หนึ่งที่น่าสนใจ ก็คือ
กรณีที่เรา click link แล้ว prototype จะใช้ xmlhttprequest
เรียกไปที่ server จากนั้นก็จะเอาผลลัพท์ที่ได้ มา render
บนหน้าจอตรงบริเวณที่เรากำหนด (partial render)
โดยเราสามารถใช้งาน โดยใช้ method ของ JavaScriptHelper ที่ชื่อ link_to_remote

<body>  
<%= link_to_remote ("get time",
:update => "time_div",
:url => {:action => "getTime" },
:complete => visual_effect(:highlight, "time_div", :duration => 1.5 )) %>
<div id="time_div">
</div>
</body>

ซึ่ง render ได้หน้าจอดังนี้



เมื่อ user click ที่ "get time" เจ้า prototype ก็จะทำการ call
ไปยัง action ที่ชื่อ getTime ใน Controller ของเรา
ผลลัพท์ที่ได้จาก action ก็จะถูก replace ไปบน <div id="time_div">
class AjController < ApplicationController
...

def getTime
render_text "<p>The Time is " + DateTime.now.to_s + "</p>"
end
end

ผลลัพท์ที่ได้จากการ click ที่ user เห็นก็เป็นแบบนี้



Note: visual_effect จะเป็นการเรียกใช้ script.aculo.us effect
โดยกรณีของเราเรียกใช้ Highlight Effect ซึงจะทำการ เน้นสีเหลือง
บริเวณ <div id="time_div"> เป็นเวลา 1.5 วินาที
แล้วค่อยๆ fade หายไป
ส่วน complete: คือการระบุ callback ที่จะถูกเรียกใช้
หลังจากที่ prototype ทำการ replace DOM element สำเร็จแล้ว


มีบางกรณีที่เราต้องการให้ insert หรือ append ผลลัพท์
แทนที่จะเป็นการ replace
กรณีนี้เราสามารถกำหนดเป็น parameter ให้กับ link_to_remote ได้
<%= link_to_remote ("get time",
:update => "time_div",
:url => {:action => "getTime" },
:position => "after") %>


Method ที่น่าสนใจอีกอันก็คือ form_remote_tag
อันนี้ต่างกับ link_to_remote ตรงที่ว่าเป็นการ submit
form แทน
<body>  
<p>Test Add Item</p>
<%= form_remote_tag(:update => "list_div",
:url => { :action => "addItem" },
:position => "top" ) %>
new Item :
<%= text_field_tag :newItem %>
<%= submit_tag "Add" %>
<%= end_form_tag %>
<ul>
<div id="list_div">
</div>
</body>

ซึ่ง render ได้ผลลัพท์ดังนี้



เมื่อมีการ submit ก็จะเกิดการเรียกใช้ method ที่ชื่อ addItem
class AjController < ApplicationController
...

def addItem
render_text "<li>" + params[:newItem] + "</li>"
end
end

ผลลัพท์ที่ได้ก็จะทำการ insert ลงส่วนบนสุดของ <div id="list_div">



จะเห็นได้ว่า rails integrate AJAX feature ได้อย่างกลมกลืนน่าใช้มาก

เพิ่มเติม: อ่านภาคภาษาอังกฤษ (ต้นฉบับ)

Related link from Roti

1 comment:

iake said...

Cool เยี่ยมครับ