เนื้อหานี้จะเป็นแนวทางการใช้งาน jquery ในการนำข้อมูลมาแสดงในรูปแบบลูปข้อมูล
เช่น นำข้อมูลที่ได้จากการเรียกใช้ API ซึ่งมีรูปแบบเป็น json string object มาใช้งาน
วนลูปแสดงในตารางเป็นต้น
ตัวอย่างเช่น ข้อมูลที่ได้จากใช้งาน ajax ด้วย jQuery getJSON() ตามบทความต่อไปนี้
การสร้าง json ไฟล์ จากฐานข้อมูล ด้วย php และการใช้งานด้วย jQuery getJSON()
https://www.ninenik.com/content.php?arti_id=373 via @ninenik
แต่ในที่นี้เราจะสมมติข้อมูลอย่างง่าย ด้วยชุดข้อมูลต่อไปนี้
// array ของ object ข้อมูลตัวอย่าง var data = [ {id:1,name:'Linda',age:27}, {id:2,name:'Manop',age:32}, {id:3,name:'Jubjang',age:24}, {id:4,name:'Adam',age:25}, {id:5,name:'June',age:21} ];
โดยเราต้องการข้อมูลข้างต้นมาแสดงในตารางในรูปแบบดังรูปด้านล่างนี้
วิธีการ เริ่มต้น ให้เราวางรูปแบบการแสดงผลข้อมูลที่ต้องการของตารางขึ้นมาก่อน ซึ่งก็จะประกอบไปด้วย
คอลัมน์ข้อมูลที่ต้องการและสอดคล้องกับข้อมูลที่จะแสดง และก็ส่วนของแถวของลูปข้อมูล โดยให้เราสร้างมา
แค่แถวเดียว รูปแบบก็จะเป็นดังรูปด้านล่าง (ในตัวอย่างเราใช้ร่วมกับ bootstrap css )
โค้ด HTML ตามรูปด้านบน
<table class="table table-bordered table-striped"> <tr> <td>#</td> <td>ID</td> <td>Name</td> <td>Age</td> </tr> <tr class="list-data"> <td></td> <td></td> <td></td> <td></td> </tr> </table>
โดย tr ของแถวที่เราจะทำเป็นลูป ให้เรากำหนด css class เข้าไป เพื่อใช้อ้างอิงการใช้งาน ในที่นี้
เราใช้ชื่อเป็น list-data และเนื่องจากตัวอย่างการแสดงข้อมูลของเรา ยังไม่ได้ซับซ้อนอะไร เป็นการ
แทรกข้อมูลเข้าไปใน td ตามลำดับ โดยการอ้างอิงลำดับคอลัมน์หรือ td ใน css หรือ javascript จะนับ
เริ่มต้นที่ 0,1,2,3.... ไปเรื่อย ดังนั้นคอลัมน์แรกจึงเริ่มต้นที่ 0
สำหรับตัวอย่างของเรา จะใช้การแสดงข้อมูลเมื่อผ่านมาแล้ว 3 วินาที ตามโค้ดด้านล่างดังนี้
โค้ดตัวอย่าง ทั้งหมด จะเป็นดังนี้
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Document</title> <link rel="stylesheet" href="https://unpkg.com/bootstrap@3.3.7/dist/css/bootstrap.min.css"> </head> <body> <br> <br> <div class="container" style="width:600px;"> <br><br> <table class="table table-bordered table-striped"> <tr> <td>#</td> <td>ID</td> <td>Name</td> <td>Age</td> </tr> <tr class="list-data"> <td></td> <td></td> <td></td> <td></td> </tr> </table> </div> <script src="https://unpkg.com/jquery@3.2.1"></script> <script type="text/javascript"> $(function(){ // array ของ object ข้อมูลตัวอย่าง var data = [ {id:1,name:'Linda',age:27}, {id:2,name:'Manop',age:32}, {id:3,name:'Jubjang',age:24}, {id:4,name:'Adam',age:25}, {id:5,name:'June',age:21} ]; // กำหนดการหน่วงเวลาแสดงข้อมูลหลังผ่าน 3 วินาทีแล้ว setTimeout(function(){ var loopTag = $(".list-data").clone(true); // clone แถวที่ทำการลูปไว้ในตัวแปร var newTag =""; // สร้างตัวแปรไว้เก็บ html tags ที่สร้างมาใหม่ $.each(data,function(i,k){ // วนลูปข้อมูล array ของ object var objHTML = loopTag; // ใช้ตัวแปร object ที่ clone มา objHTML.find("td:eq(0)").html(i+1).end() .find("td:eq(1)").html(data[i].id).end() .find("td:eq(2)").html(data[i].name).end() .find("td:eq(3)").html(data[i].age).end(); newTag += $(objHTML)[0].outerHTML; // สร้าง tags ข้อมูลใหม่แต่ละแถว }); $(".list-data").replaceWith(newTag); // แทนที่แถวที่จะทำการลูปด้วยข้อมูลใหม่ },3000); }); </script> </body> </html>
จะขออธิบายโค้ดเพิ่มเติม เริ่มต้น เราได้วางส่วนของ tr ที่มี class ชื่อ list-data ไว้ในตาราง table
แล้วเราใช้คำสั่ง clone ใน jquery clone ในส่วนของ tr นั้น มาไว้ในตัวแปร loopTag ด้วยคำสั่ง
var loopTag = $(".list-data").clone(true);
ตัวแปร loopTag จะเป็น jquery object ที่มีเฉพาะ tag tr ที่เรา clone มา หรือก็คือส่วนของ tag
<tr class="list-data"> <td></td> <td></td> <td></td> <td></td> </tr>
และเมื่อเราใช้คำสั่งลูปข้อมูลมาใช้งานด้วย $.each() เราเรียกใช้ ตัวแปร loopTag โดยเอาค่ามาเก็บไว้ในตัวแปร
objHTML ในแต่ละลูปข้อมูล
$.each(data,function(i,k){ // วนลูปข้อมูล array ของ object var objHTML = loopTag; });
ตัวแปร i จะหมาย key ของ array ข้อมูลนั้นๆ จะเริ่มต้นที่ 0 ส่วน ตัวแปร k จะหมายถึง value ของแต่ละ ข้อมูล
อย่างเช่น ถ้า i เท่ากับ 0 ค่า k ก็จะเท่ากับ ค่าของชุอข้อมูล object {id:1,name:'Linda',age:27} นั่นเอง
ดังนั้น data[i] จึงหมายถึงขุดข้อมูลในแต่ละแถว ตามค่า key ค่า i
การอ้างอิง object ชุดข้อมูล เช่น id ก็จะอ้างอิงผ่านตัวแปร data[i].id แบบนี้เป็นต้น
ต่อไปมาดูในส่วนของคำสั่ง
objHTML.find("td:eq(0)").html(i+1).end() .find("td:eq(1)").html(data[i].id).end() .find("td:eq(2)").html(data[i].name).end() .find("td:eq(3)").html(data[i].age).end();
คำสั่งนี้หมายถึง jquery object ที่ชื่อ objHTML ที่เป็นค่าที่เรา clone มานั้น ให้ทำการหา find()
td:eq(0) ก็คือหาคอลัมน์แรก แล้วกำหนดค่าภายใน td ด้วยคำสั่ง html() ในที่นี้ คอลัมน์แรกของ
เราก็คือลำดับที่ของข้อมูล ก็จะเริ่มนับที่ 1,2,3.... ไปเรื่อยๆ ดังนั้นเราจึงใช้ค่า i ที่เป็น 0 บวกด้วย 1
ดังนั้นเมื่อเข้าไปในแถวที่ 2 ค่า i ก็จเพิ่มเป็น 1 พอบวกอีก 1 ก็จเป็นข้อมูลลำดับที่สอง แบบนี้ไปเรื่อยๆ
สุดท้ายจบการทำงานด้วยคำสั่ง end() เพื่อให้เราสามารถเรียกใช้คำสั่ง find() ต่อเนื่องได้ โดยในบรรทดัต่อมา
.find("td:eq(1)").html(data[i].id).end()
คำสั่ง find() ก็จะหมายถึง objHTML ค้นหาต่อ เพราะยังไม่จบการทำงาน แต่บรรทัดนี้เป็นการค้นหา td:eq(1)
หรือก็คือคอลัมน์ที่ 2 จากนั้นก็แทรกค่าด้วย id ทำในลักษณะเช่นนี้ไปเรื่อย จนครบตามต้องการ อย่างในคอลัมน์สุดท้าย
เราทำการแทรกอายุ age และปิดด้วย ( ; ) semicolon เพื่อจบการทำงาน
ดังนั้นตัวแปร objHTML ในแต่ละแถว จะมี tag html เริ่มต้นเป็น
<tr class="list-data"> <td></td> <td></td> <td></td> <td></td> </tr>
และหลังนำค่าข้อมูลมาแทนกด้วยคำสั่ง find() html() และ end()
ค่าสุดท้ายหลังแทรกข้อมูลในแต่ละแถวก็จะมีข้อมูลเข้ามาด้วย อย่างแถวแรก ก็จะได้เป็น
<tr class="list-data"> <td>1</td> <td>1</td> <td>Linda</td> <td>27</td> </tr>
อย่างที่เราทราบกันแล้วว่าตัวแปร objHTML นั้นเป็น jquery object ซึ่งมี tag html อยู่ด้านใน
แต่ทีเราต้องการค่า tag html ด้านในของ jquery object ดังนั้นเราจึงทำการแปลงเป็น dom object
ด้วยคำสั่ง
newTag += $(objHTML)[0].outerHTML;
โดย $(objHTML)[0].outerHTML จะทำการแปลง jquery object เป็น dom object หรือ string tag html
ของแต่ละแถว เอามาต่อๆ กันไว้ในตัวแปร newTag ด้วยตัวจัดการ +=
เมื่อ newTag วนลูปเก็บรูปแบบ tag html ที่แทรกค่าครบหมดแล้ว ก็ออกนอกลูปข้อมูล
เราก็นำค่า newTag นี้ไปแทนที่ tr เดิมที่มี class ชื่อ list-data ด้วยคำสั่ง
$(".list-data").replaceWith(newTag);
ผลลัพธ์ที่ได้คือมีการแทรก tr class="list-data" วนลูปข้อมูลแสดงในตาราง ตามโครงสร้างดังรูป
ทีนี้เรามาดูกรณีสมมติว่า ข้อมูลการแสดงมีความซับซ้อนมากขึ้น เช่น เราอยากจัดรูปแบบของข้อมูล
ที่แสดงในแต่ละ td ตัวอย่าง อยากให้ id แสดงก่อนชื่อ ไม่ต้องแยก คอลัมน์ และมีแสดงตามต้องการ
ดังนี้
ตามรูปแบบโค้ด
<style type="text/css"> .my_red{color:red;} .my_blue{color:blue;} .my_green{color:green;} </style> <table class="table table-bordered table-striped"> <tr> <td>#</td> <td>Name</td> <td>Age</td> </tr> <tr class="list-data"> <td> <span class="my_green"></span> </td> <td> <span class="my_red"></span> <span class="my_blue"></span> </td> <td> <span class="my_green"></span> </td> </tr> </table>
จะเห็นว่าตอนนี้เราไม่สามารถอ้างอิงจาก td ได้แล้วเพราะ บางคอลัมน์มีการนำข้อมูลมาแสดงสองครั้ง
วิธีแก้ไขคือ เราสามารถใช้ css class ของ ส่วนข้อมูลในที่นี้คือ span มาใช้ได้ แต่เพื่อไม่ให้สับสน
ให้ใช้วิธีเพิ่ม css class ใหม่เข้าไป แล้ว อ้างอิงข้อมูลตามลำดับ key ที่เริ่มจาก 0 เหมือนที่ใช้ใน td
เป็นดังนี้แทน สมมติเพิ่ม my_cssdata class เข้าไป
<style type="text/css"> .my_red{color:red;} .my_blue{color:blue;} .my_green{color:green;} </style> <table class="table table-bordered table-striped"> <tr> <td>#</td> <td>Name</td> <td>Age</td> </tr> <tr class="list-data"> <td> <span class="my_cssdata my_green"></span> </td> <td> <span class="my_cssdata my_red"></span> <span class="my_cssdata my_blue"></span> </td> <td> <span class="my_cssdata my_green"></span> </td> </tr> </table>
หมายเหตุ: css class ใช้รวมกันมากกว่าหนึ่งให้เว้นวรรคค่าแต่ละตัว
จากนั้นในส่วนของ javascript เราก็สามารถกำหนดเป็นดังนี้ได้
objHTML.find(".my_cssdata:eq(0)").html(i+1).end() .find(".my_cssdata:eq(1)").html(data[i].id).end() .find(".my_cssdata:eq(2)").html(data[i].name).end() .find(".my_cssdata:eq(3)").html(data[i].age).end();
ผลลัพธที่ได้ ก็จะเป็นดังนี้
ต่อไป สมมติกรณีว่ามีการใช้งาน form element ในลูปข้อมูล เราจะกำหนดค่ายังไง ยกตัวอย่างเช่น
ให้แสดงอายุใน input type text หรือ number ดังนี้
ตามรูปแบบโค้ด
<style type="text/css"> .my_red{color:red;} .my_blue{color:blue;} .my_green{color:green;} .my_inputtext{width:50px;} </style> <table class="table table-bordered table-striped"> <tr> <td>#</td> <td>Name</td> <td>Age</td> </tr> <tr class="list-data"> <td> <span class="my_cssdata my_green"></span> </td> <td> <span class="my_cssdata my_red"></span> <span class="my_cssdata my_blue"></span> </td> <td> <input type="text" class="my_inputtext" name="age[]" value="" /> </td> </tr> </table>
วิธีการก็คล้ายกับตัวอย่างกรณีก่อนหน้า คือให้เราเพิ่ม css class เข้าไปใน input text ก็จะได้เป็น
<style type="text/css"> .my_red{color:red;} .my_blue{color:blue;} .my_green{color:green;} .my_inputtext{width:50px;} </style> <table class="table table-bordered table-striped"> <tr> <td>#</td> <td>Name</td> <td>Age</td> </tr> <tr class="list-data"> <td> <span class="my_cssdata my_green"></span> </td> <td> <span class="my_cssdata my_red"></span> <span class="my_cssdata my_blue"></span> </td> <td> <input type="text" class="my_cssdata my_inputtext" name="age[]" value="" /> </td> </tr> </table>
จากนั้นส่วนของ javascript ก็ปรับนิดหน่อยดังนี้
objHTML.find(".my_cssdata:eq(0)").html(i+1).end() .find(".my_cssdata:eq(1)").html(data[i].id).end() .find(".my_cssdata:eq(2)").html(data[i].name).end() .find(".my_cssdata:eq(3)").attr("value",data[i].age).end();
จะเห็นว่า css class ที่ชื่อ my_cssdata ตัวสุดท้ายอ้างอิง key ที่เท่ากับ 3 จะเป็น input text
การกำหนดค่า เราจะใช้วิธีกำหนด attribute ให้กับ input text นั้น ในที่นี้คือกำหนด value ให้เท่ากับ
age
หมายเหตุ: เราไม่สามารถใช้คำสั่ง val() เพื่อกำหนดค่าให้กับตัวแปร objHTML เหมือนการอ้างอิงปกติได้
กล่าวคือ เราไม่สามารถกำหนดค่าโดยใช้คำสั่ง
.find(".my_cssdata:eq(3)").val(data[i].age).end(); // ไม่สามารถกำหนดในรูปแบบนี้ได้
มาดูผลลัพธ์ที่ได้ จะได้เป็นดังนี้
เราสามารถนำแนวทางนี้ไปประยุกต์ใช้งาน ในการวนลูปแสดงข้อมูลเพิ่มเติมได้ อย่างไรก็ตาม
รูปแบบวิธีข้างต้น เหมาะสำหรับรายการข้อมูลที่มีจำนวนไม่มากนัก หรือข้อมูลที่ไม่ได้มีหลายๆ หน้า