You are hereBlogs > jittat's blog > include tag และ ajax

include tag และ ajax


By jittat - Posted on 11 October 2008

วันก่อนโน้นเขียนเรื่อง partials ใน rails66 ใน Django ก็มีความสามารถคล้าย ๆ กันอยู่ คือ include tag ซึ่งนอกจากจะทำให้ template เราอ่านง่ายแล้วหลายครั้งยังทำให้เขียน ajax ได้ง่ายด้วย

วิธีการใช้ก็ไม่ยาก สมมติว่าเรามี template index.html ที่แสดงรายการพนักงาน เช่นด้านล่าง

{% for employee in employees %}
  <ul>
    <li>Name: {{ employee.name }}</li>
    <li>Status:
      {% if employee.status %}
        is in
      {% else %}
        is out
      {% endif %}
    </li>
  </ul>
{% endfor %}

เราสามารถแยกส่วนแสดงผลของพนักงานแต่ละคนออกมาเป็นอีก template หนึ่ง เช่น ให้ชื่อว่า employee.html ดังด้านล่าง

<ul>
  <li>Name: {{ employee.name }}</li>
  ... ที่เหลือละไว้ ...
</ul>

จากนั้นค่อย include เข้ามาใน index.html ด้วย include tag

{% for employee in employees %}
    {% include "employee.html" %}
{% endfor %}

โดย context ในการแสดงผล template ที่ถูก include เข้ามาจะเป็น context เดียวกับจุดที่เรียก include tag ซึ่งทำให้ในการแสดงผล employee.html มีตัวแปร employee ให้ใช้

ในกรณีที่ template ย่อยใช้ตัวแปรคนละชื่อ เราสามารถเปลี่ยนชื่อตัวแปรใน context ได้ด้วย tag with เช่นบังเอิญใน template หลักเราใช้ตัวแปรชื่อ emp แทนที่จะเป็น employee เวลาเราเรียก template ย่อยเราจะสั่ง

{% with emp as employee %}
    {% include "employee.html" %}
{% endwith %}

แล้วมันเกี่ยวอะไรกับ ajax?

การแบบหน้าเว็บเป็นส่วน ๆ แล้วใช้ include tag ในการแสดงนั้น นอกจากจะทำให้ template อ่านง่ายแล้ว ยังทำให้การเขียน ajax สะดวกขึ้นมาก เพราะว่าเราสามารถโยนบางส่วนของหน้าจอที่ render แล้วกลับมาแทนที่ส่วนที่ต้องการ update ในหน้าเว็บได้เลย (ซึ่งอันนี้เป็นท่าที่ผมจำมาจากใน rails --- คาดว่าน่าจะเป็นท่าพื้นฐานในการเขียน ajax อยู่แล้ว)

เช่นในตัวอย่างข้างต้นถ้าต้องการให้มีปุ่ม toggle ที่สลับ status ของพนักงานได้ เราก็ไปปรับ template โดยนำ tag div มาครอบพร้อมกับระบุ id แล้วก็เพิ่มปุ่มเข้าไป ดังด้านล่าง

{% for employee in employees %}
  <div id="employee-{{ employee.id }}">
    {% include "employee.html" %}
  </div>
  <input type="submit"
         value="toggle"
         onclick="toggle_status({{ employee.id }});"/>
{% endfor %}

ส่วน toggle_status ก็จะทำ request ไปที่ url ที่เราเขียนไว้เพื่อปรับสถานะพนักงาน เช่น /toggle/4/ ถ้าปรับพนักงานที่มี id=4 แล้วรับผลลัพธ์มาแทนที่ div id="employee-4" โปรแกรมส่วนนี้ถ้าใช้พวก javascript framework ก็เขียนค่อนข้างง่ายทีเดียว (โปรแกรมแสดงตอนท้ายครับ)

ส่วนใน view ที่รับ request นั้นมาก็จัดการปรับค่าสถานะแล้วก็สั่ง render template ย่อยส่วนนั้นกลับไปได้เลย

def toggle(request,employee_id):
    employee_id = int(employee_id)
    employee = Employee.objects.get(id=employee_id)
    employee.status = not employee.status
    employee.save()
    return render_to_response("employee.html",
                              { 'employee' : employee })

ส่วน javascript ที่ใช้เรียก request และปรับค่าแสดงด้งด้านล่างนะครับ ผมใช้ prototype เพราะว่าเป็นตัวเดียวที่ใช้เป็นครับ

<script type="text/javascript" src="/site-media/js/prototype.js"></script>
<script type="text/javascript">
function toggle_status(id) {
  url = "/toggle/" + id + "/";
  div_id = "employee-" + id;
  new Ajax.Request(url,
    {
      method: "get",
      onComplete: function(xhr) {
        $(div_id).innerHTML = xhr.responseText;
      }
    }
  );
}
</script>
tonkla's picture

ผมเพิ่งได้ใช้ inclusion tag ไปวันก่อนครับ สวยงามไปอีกแบบ อ่านหัวข้อบันทึกนึกว่าเป็นเรื่องเดียวกัน ชื่อมันคล้ายๆ กันครับ include tag vs. inclusion tag :-P

ผมก็งง ๆ เหมือนกันอ่ะครับ ;)

แต่ผมยังไม่เคยใช้เลยครับ (มันต้องนิยาม tag ใหม่เอาใช่ป่ะครับ?)

tonkla's picture

แทบจะเหมือนกับ simple tag เลยครับ เพียงแต่มัน include template อื่นมา render สรุปคือ simple tag + include tag = inclusion tag ครับ ฮา ฮา