จากเนื้อหาในตอนที่ 4 เราได้ให้แนวทางการสร้าง และ
บันทึกข้อมูลกิจกรรมลงในฐานข้อมูล และได้พูดถึงการ
กำหนดฟิลด์พิเศษเพิ่มเติม ในกรณืที่เราต้องการให้
กิจกรรมนั้น มีรายละเอียดเพิ่มเติม หรือมีฟิลด์ข้อมูลนอกเหนือ
จากฟิลด์ข้อมูลหลักแล้ว ทบทวนตอนที่แล้วได้ที่
บักทึก และสร้าง event ใน fullcalendar อัพเดทปี 2020 ตอนที่ 4 http://niik.in/977
https://www.ninenik.com/content.php?arti_id=977 via @ninenik
เนื้อหาตอนต่อไปนี้ เราจะให้แนวทาง การใช้งานข้อมูลเพิ่มเติมนั้น โดยจะประยุกต์ใช้งานกับ
modal ของ bootstrap เพื่อแสดงรายละเอียดของกิจกรรมเพิ่มเติม เมื่อคลิกที่ กิจกรรมนั้นๆ
ในปฏิทินกิจกรรม ทำตามแนวทางต่อไปนี้ตามลำดับ
การใช้งานฟิลด์เพิ่มเติมในไฟล์ json
จะขอยกโครงสร้าง ไฟล์ events.php จากตอนที่แล้วมาประกอบการอธิบาย
ไฟล์ events.php
<?php header("Content-type:application/json; charset=UTF-8"); header("Cache-Control: no-store, no-cache, must-revalidate"); header("Cache-Control: post-check=0, pre-check=0", false); // โค้ดไฟล์ dbconnect.php ดูได้ที่ http://niik.in/que_2398_5642 require_once("dbconnect.php"); $json_data = array(); $sql =" SELECT * FROM tbl_event WHERE event_startdate>='".$_GET['start']."' AND event_enddate<='".$_GET['end']."' "; $result = $mysqli->query($sql); if(isset($result) && $result->num_rows>0){ while($row = $result->fetch_assoc()){ $_start_date = $row['event_startdate']; $_end_date = false; $_start_time = false; $_end_time = false; $_repeat_day = false; $_all_day = ($row['event_allday']!=0)?true:false; if($row['event_starttime']!="00:00:00"){ $_start_date = $row['event_startdate']."T".$row['event_starttime']; if($row['event_endtime']!="00:00:00" && ($row['event_starttime']==$row['event_enddate'] || $row['event_enddate']=="0000-00-00") ){ $_end_date = $row['event_startdate']."T".$row['event_endtime']; } } if($row['event_enddate']!="0000-00-00"){ $_end_date = $row['event_enddate']; if($row['event_endtime']!="00:00:00"){ $_end_date = $row['event_enddate']."T".$row['event_endtime']; }else{ $_end_date = date("Y-m-d",strtotime($row['event_enddate']." +1 day")); } } if($row['event_enddate']!="0000-00-00" && $row['event_enddate']!=$row['event_startdate'] && $row['event_starttime']!="00:00:00" && $row['event_endtime']!="00:00:00" ){ $_start_date = $row['event_startdate']; $_end_date = $row['event_enddate']; $_start_time = $row['event_starttime']; $_end_time = $row['event_endtime']; $_all_day = false; } // ทำการเปลี่ยน หรือกำหนดการใช้งาน url หรือลิ้งค์ เป็นการเรียกใช้งาน javascript ฟังก์ชั่น $row['event_url'] = "javascript:viewdetail('{$row['event_id']}');"; // ส่งค่า id ไปในฟังก์ชั่น $arr_eventData = array( "id" => $row['event_id'], "groupId" => str_replace("-","",$row['event_startdate']), "allDay" => $_all_day, "start" => $_start_date, "end" => $_end_date, "startTime" => $_start_time, "endTime" => $_end_time, "title" => $row['event_title'], "url" => $row['event_url'], "textColor" => $row['event_color'], "backgroundColor" => $row['event_bgcolor'], "borderColor" => "transparent", "detail" => $row['event_detail'],// กำหนดฟิลด์เพิ่มเติมที่จะใช้งานข้อมูล ); if($row['event_repeatday']!=""){ $arr_eventData['daysOfWeek'] = explode(",",$row['event_repeatday']); } if($row['event_enddate']!="0000-00-00" && $row['event_enddate']!=$row['event_startdate'] && $row['event_starttime']!="00:00:00" && $row['event_endtime']!="00:00:00" ){ $arr_eventData['startRecur'] = $_start_date; $_end_date = date("Y-m-d",strtotime($row['event_enddate']." +1 day")); $arr_eventData['endRecur'] = $_end_date; } if(!$_all_day){unset($arr_eventData['allDay']);} if(!$_end_date){unset($arr_eventData['end']);} if(!$_start_time){unset($arr_eventData['startTime']);} if(!$_end_time){unset($arr_eventData['endTime']);} $json_data[] = $arr_eventData; } } // แปลง array เป็นรูปแบบ json string if(isset($json_data)){ $json= json_encode($json_data); if(isset($_GET['callback']) && $_GET['callback']!=""){ echo $_GET['callback']."(".$json.");"; }else{ echo $json; } } ?>
ดูบรรทัดที่เราได้ทำการเพิ่ม ตามที่ได้ highlight ไว้ 45 46 60
หากเป็นแนวทางอย่างง่าย ในการแสดงข้อมูลเพิ่มเติม เราก็แค่อาจจะใส่ลิ้งค์ หรือกำหนด url เป็นไฟล์ข้อมูลใหม่ โดยส่ง
event_id แล้วไปทำการคิวรี่แสดงข้อมูลก็ได้ เช่น เรากำหนด url เป็นดังนี้
$row['event_url'] = "http://www.mywebsite.com/viewevent.php?id=".$row['event_id'];
แล้วใช้ไฟล์หน้า viewevent.php คิวรี่ดึงข้อมูลจาก event ของ id นั้นมาแสดง
แต่ในที่นี้ เราจะทำการแสดงข้อมูลในหน้าเดียวกับปฏิทิน จึงใช้วิธีเรียกใช้งาน คำสั่ง javascript ชื่อฟังก์ชั่นว่า viewdetail()
$row['event_url'] = "javascript:viewdetail('{$row['event_id']}');"; // ส่งค่า id ไปในฟังก์ชั่น
ซึ่งเราจะต้องไปสร้างฟังก์ชั่นนี้ในไฟล์ที่เรียกใช้งาน fullcalendar ในฟังก์ชั่น เราทำการส่งค่า event_id เข้าไป เพื่อใช้สำหรับ
ดึงข้อมูลกิจกรรมมาแสดงอีกที
นอกจากกำหนดในส่วนของ url แล้ว เราก็มีการกำหนด property เพิ่มเติม ซึ่งจะเพิ่มกี่ property ก็ได้ ในที่นี้เราเพิ่มมาแค่
อันเดียวเป็นแนวทาง ชื่อว่า detail โดยใช้ข้อมูลจากฐานข้อมูลที่เราเพิ่มในตอนต้นชื่อฟิลด์ว่า event_detail ข้อมูลส่วนนี้ จะเป็น
รายละเอียดเพิ่มเติมที่แราจะแสดงใน modal
การแสดงข้อมูลเพิ่มเติมของ fullcalendar ใน modal
ก่อนไปดูการเพิ่มโค้ดเพิ่มเติม เพื่อแสดงข้อมูล modal จะขอยกโค้ดไฟล์ ตัวอย่าง ในบทความก่อนหน้าก่อนปรับแต่ง
มาอธิบายเพิ่มเติมดังนี้
ไฟล์ demo.php
<?php $fullcalendar_path = "fullcalendar-4.4.2/packages/"; ?> <!DOCTYPE html> <html lang='en'> <head> <meta charset='utf-8' /> <link href='<?=$fullcalendar_path?>/core/main.css' rel='stylesheet' /> <link href='<?=$fullcalendar_path?>/daygrid/main.css' rel='stylesheet' /> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css"> <!-- ส่วนที่เพิ่มเข้ามาใหม่--> <link href='<?=$fullcalendar_path?>/timegrid/main.css' rel='stylesheet' /> <link href='<?=$fullcalendar_path?>/list/main.css' rel='stylesheet' /> <script src='<?=$fullcalendar_path?>/core/main.js'></script> <script src='<?=$fullcalendar_path?>/daygrid/main.js'></script> <!-- ส่วนที่เพิ่มเข้ามาใหม่--> <script src='<?=$fullcalendar_path?>/core/locales/th.js'></script> <script src='<?=$fullcalendar_path?>/timegrid/main.js'></script> <script src='<?=$fullcalendar_path?>/interaction/main.js'></script> <script src='<?=$fullcalendar_path?>/list/main.js'></script> <style type="text/css"> #calendar{ width: 800px;margin: auto; } </style> </head> <body> <div id='calendar'></div> <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha256-4+XzXVhsDmqanXGHaHvgh1gMQKX40OUvDEBTu8JcmNs=" crossorigin="anonymous"></script> <script type="text/javascript"> $(function(){ // กำหนด element ที่จะแสดงปฏิทิน var calendarEl = $("#calendar")[0]; // กำหนดการตั้งค่า var calendar = new FullCalendar.Calendar(calendarEl, { plugins: [ 'interaction','dayGrid', 'timeGrid', 'list' ], // plugin ที่เราจะใช้งาน defaultView: 'dayGridMonth', // ค้าเริ่มร้นเมื่อโหลดแสดงปฏิทิน header: { left: 'prev,next today', center: 'title', right: 'dayGridMonth,timeGridWeek,timeGridDay,listMonth' }, events: { // เรียกใช้งาน event จาก json ไฟล์ ที่สร้างด้วย php url: 'events.php?gData=1', error: function() { } }, eventLimit: true, // allow "more" link when too many events locale: 'th', // กำหนดให้แสดงภาษาไทย firstDay: 0, // กำหนดวันแรกในปฏิทินเป็นวันอาทิตย์ 0 เป็นวันจันทร์ 1 showNonCurrentDates: false, // แสดงที่ของเดือนอื่นหรือไม่ eventTimeFormat: { // รูปแบบการแสดงของเวลา เช่น '14:30' hour: '2-digit', minute: '2-digit', meridiem: false } }); // แสดงปฏิทิน calendar.render(); }); </script> </body> </html>
สิ่งที่เราจะจัดการก็คือ เรียกใช้ css และ js ไฟล์ของ bootstrap เพราะเราจะมีการใช้งาน modal เป็น component หนึ่งของ
boostrap และจำเป็นต้องใช้งาน bootstrap js ด้วย
ต่อด้วยย้ายการประกาศตัวแปรที่เป้น instant ของ fullcalendar ที่ชื่อ calendar ให้มาอยู่ด้านนอก ขอบเขตของ jquery เพื่อให้
สามารถเรียกใช้งานหน้าเว็บได้ทุกส่วน จะอธิบายต่อด้านล่าง
ต่อด้วยกำหนด modal component หรือ โครงสร้าง html ของ modal ที่เราจะใช้งาน หลักๆ จะเน้นไปที่กำหนดกำหนด id ให้กับ
ส่วนที่เราจะแสดงข้อมูล ก็จะมี id ของ modal , id ของหัวข้อ และ id ของรายละเอียด เพิ่มเติมได้ตามต้องการ
และส่วนสุดท้ายก็คือ ฟังก์ชั่น javascript ที่ชื่อ viewdetail() ฟังก์ชั่นนี้จะรับค่า id มา เราจะเอา id นี้ไปดึงข้อมูลจาก calendar
ผ่าน api แล้วนำมาแสดงใน modal
ดูโค้ดที่มีการปรับใช้งานแล้วได้ดังต่อไปนี้
<?php $fullcalendar_path = "fullcalendar-4.4.2/packages/"; ?> <!DOCTYPE html> <html lang='en'> <head> <meta charset='utf-8' /> <link href='<?=$fullcalendar_path?>/core/main.css' rel='stylesheet' /> <link href='<?=$fullcalendar_path?>/daygrid/main.css' rel='stylesheet' /> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css"> <!-- ส่วนที่เพิ่มเข้ามาใหม่--> <link href='<?=$fullcalendar_path?>/timegrid/main.css' rel='stylesheet' /> <link href='<?=$fullcalendar_path?>/list/main.css' rel='stylesheet' /> <script src='<?=$fullcalendar_path?>/core/main.js'></script> <script src='<?=$fullcalendar_path?>/daygrid/main.js'></script> <!-- ส่วนที่เพิ่มเข้ามาใหม่--> <script src='<?=$fullcalendar_path?>/core/locales/th.js'></script> <script src='<?=$fullcalendar_path?>/timegrid/main.js'></script> <script src='<?=$fullcalendar_path?>/interaction/main.js'></script> <script src='<?=$fullcalendar_path?>/list/main.js'></script> <style type="text/css"> #calendar{ width: 800px;margin: auto; } </style> </head> <body> <div id='calendar'></div> <!-- Modal --> <div class="modal fade" id="calendarmodal" tabindex="-1" role="dialog" > <!--กำหนด id ให้กับ modal--> <div class="modal-dialog modal-dialog-centered" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="calendarmodal-title">Modal title</h5> <!--กำหนด id ให้ส่วนหัวข้อ--> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body" id="calendarmodal-detail"> ก<!--ำหนด id ให้ส่วนรายละเอียด--> Modal detail </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> </div> </div> </div> </div> <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha256-4+XzXVhsDmqanXGHaHvgh1gMQKX40OUvDEBTu8JcmNs=" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/js/bootstrap.bundle.min.js"></script> <script type="text/javascript"> var calendar; // สร้างตัวแปรไว้ด้านนอก เพื่อให้สามารถอ้างอิงแบบ global ได้ $(function(){ // กำหนด element ที่จะแสดงปฏิทิน var calendarEl = $("#calendar")[0]; // กำหนดการตั้งค่า calendar = new FullCalendar.Calendar(calendarEl, { plugins: [ 'interaction','dayGrid', 'timeGrid', 'list' ], // plugin ที่เราจะใช้งาน defaultView: 'dayGridMonth', // ค้าเริ่มร้นเมื่อโหลดแสดงปฏิทิน header: { left: 'prev,next today', center: 'title', right: 'dayGridMonth,timeGridWeek,timeGridDay,listMonth' }, events: { // เรียกใช้งาน event จาก json ไฟล์ ที่สร้างด้วย php url: 'events.php?gData=1', error: function() { } }, eventLimit: true, // allow "more" link when too many events locale: 'th', // กำหนดให้แสดงภาษาไทย firstDay: 0, // กำหนดวันแรกในปฏิทินเป็นวันอาทิตย์ 0 เป็นวันจันทร์ 1 showNonCurrentDates: false, // แสดงที่ของเดือนอื่นหรือไม่ eventTimeFormat: { // รูปแบบการแสดงของเวลา เช่น '14:30' hour: '2-digit', minute: '2-digit', meridiem: false } }); // แสดงปฏิทิน calendar.render(); }); </script> <script type="text/javascript"> function viewdetail(id){ // ก่อนที่ modal จะแสดง $('#calendarmodal').on('show.bs.modal', function (e) { var event = calendar.getEventById(id) // ดึงข้อมูล ผ่าน api $("#calendarmodal-title").html(event.title); $("#calendarmodal-detail").html(event.extendedProps.detail);// ข้อมูลเพิ่มเติมจะเรียกผ่าน extendedProps }); $("#calendarmodal").modal();// แสดง modal } </script> </body> </html>
บรรทัดที่ 11 และ 59 เราเรียกใช้งาน css และ js ของ bootstrap
บรรทัดที่ 61 เราประกาศตัวแปร calendar ไว้นอก jquery จากเดิมที่ประกาศ และกำหนดค่าทันทีด้านในขอบเขตของ jquery
ก็เปลี่ยนมาประกาศตัวแปรด้านนอกก่อน เพื่อให้เป็น global แล้วค่อยกำหนดค่าอีกทีด้านใน โดยมีมีคำว่า var ในบรรทัด 67
ตัวแปร calendar จะเป็นเหมือน instnant object หรือตัวแทนของ fullcalendar ที่เราจะอ้างอิงการใช้งาน
บรรทัดที่ 36 - 53 เป็นส่วนของการกำหนด modal component ในส่วนนี้ เรากได้กำหนดค่า id ต่าง เพื่อใช้อ้างอิงการแสดงค่า
ในบรรทัดที่ 36 40 และ 45 ข้อมูล Modal Title และ Modal detail จะถูกแทนที่ด้วยข้อมูลใหม่ เมื่อเราทำการโหลด modal
และสุดท้าย บรรทัดที่ 98 จนถึง 106 เราสร้างฟักง์ชั่นไว้ด้านนอกของ jquery เพื่อเรียกใช้งานจากการกดลิ้งค์ในปฏิทิน โดยส่งค่า
id ของ event เข้ามา โดยก่อนที่แสดง modal เราได้ทำการเรียก fullcalendar api ผ่านตัวแปร instant ที่ชื่อ calendar ตรงนี้จะเห็น
ว่าเพราะ ตัวแปร calendar เป้นแบบ global เราจึงสามารถเรียกใช้งานในนี้ได้ ตามเหตุผลที่พยายามอธิบายไปแล้วในตอนต้น
ตัว fullcalendar api มีคำสั่งที่ชื่อว่า getEventById ที่สามารถเรียกข้อมูล event object มาใช้งานได้ ซึ่งในที่นี้เราจะใช้แค่สองค่า
คือค่า title ซึ่งป็น property หลักของ event object อยู่แล้ว และอีกอันคือ detail
สำหรับ detail นั้นเป็น ค่า property เพิ่มเติมที่เรากำหนดเอง ดังนั้น เวลาอ้างอิงการเรียกใช้ จึงใช้เป็น event.extendedProps.detail
แทนที่จะเป้น event.detail แนวทางนี้ใช้กับ property เพิ่มเติมอื่นๆ ถ้ามี
เมื่อเราได้ค่า event.title และ event.extendedProps.detail ก็นำค่าทั้งสองนี้ไปแสดงใน modal ตามตำแหน่ง id ที่เรากำหนดไว้
และ เมื่อ modal โชว์ขึ้นมา ค่าต่างๆ ก็จะแสดงใน modal ตามที่เรากำหนดนั่นเอง
สามารถดู demo แนวทางผลลัพธ์ได้จากด้านล่าง โดยคลิกกิจกรรม ที่ต้องการแสดงข้อมูลเพิ่มเติม