Author: assadayut.s

  • เทคนิคการเลื่อนสลับแถว (Drag & Drop) ใน Table ด้วย JavaScript

    บล็อกนี้น่าจะเป็น EP สุดท้ายของซีรี่ส์ Drag & Drop row ใน HTML Table แล้ว จากบล็อกที่ผ่านๆ มา ผู้เขียนได้ใช้เทคนิคต่างๆ โดยพึ่งพา framework ที่ใช้ในการพัฒนาโปรแกรม เช่น ASP.NET, Blazor หรือ jQuery แต่สำหรับบล็อกนี้เราจะเขียนโดยใช้ JavaScript ล้วนๆ บวกกับ CSS จาก Bootstrap อีกนิดหน่อยเพื่อความสวยงามของ Table และเพื่อไม่ให้เป็นการเสียเวลา เรามาลุยกันเลยครับ

    1. เริ่มต้นด้วยการเตรียมไฟล์ HTML ดังโค้ดด้านล่าง

    <!DOCTYPE html>
    <html lang="en">
    	<head>
    		<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    		<title>Drag & Drop Table Row</title>
    		
    		<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css">
    	</head>
    	<body style="padding:10px">
    		
    		<table style="width:90%;" class="table table-striped">
    			<thead>
    				<tr >
    					<th>ลำดับ</th>
    					<th>จังหวัด</th>
    				</tr>
    			</thead>
    			<tbody id="provinceList">
    			</tbody>
    		</table>
    		
    	</body>
    </html>

    2. เพิ่ม code JavaScript สำหรับเพิ่มข้อมูลลงใน Table ใน event window.onload โดยเราจะเพิ่มแท็ก <tr> ใน element tbody ที่มี id=”provinceList” และระบุ class=”prv-item” สำหรับใช้ในการอ้างถึงจากโค้ด JavaScript

    <script>
    
    window.onload = async () => {
    
    	const provinces = ['สงขลา','ปัตตานี','ยะลา','นราธิวาส','สตูล'];
    	for (let i = 0; i < provinces.length; i++) {
    		provinceList.innerHTML += "<tr class='prv-item' data-value=" + i + "><td> " + (i + 1) + "</td><td>" + provinces[i] + "</td></tr>";
    	};
    
    };
    
    </script>

    ซึ่งจะได้ผลลัพธ์หน้าจอดังรูป และเป้าหมายของเราก็คือสามารถคลิกเลือกจังหวัด จากนั้นลากและวางไปยังตำแหน่งที่ต้องการได้

    3. และเพิ่มโค้ด JavaScript สำหรับผูก event ต่างๆ เข้ากับแต่ละ <tr> ที่เพิ่มเข้าไป ใน event window.onload เพื่อให้สามารถลากและวางได้

    let listPrvItems = document.querySelectorAll(".prv-item");
    listPrvItems.forEach((element) => {
    	element.draggable = true;
    	element.addEventListener("dragstart", dragStart, false);
    	element.addEventListener("dragover", dragOver, false);
    	element.addEventListener("drop", drop, false);
    });

    4. เพิ่มโค้ด JavaScript ส่วนควบคุม event ต่างๆ คือ เมื่อเริ่มกดลาก เมื่อกดวาง และฟังก์ชันสำหรับหาตำแหน่งของแถว (<tr>) ที่เริ่มกดลาก ดังนี้

    //หาลำดับของ tr จาก value ที่ส่งมา ทำการวนลูปเทียบกับ data-value ใน tr ของตารางทั้งหมด
    const getPosition = (value) => {
    	let elementIndex;
    	let listPrvItems = document.querySelectorAll(".prv-item");
    	listPrvItems.forEach((element, index) => {
    		let elementValue = element.getAttribute("data-value");
    		if (value == elementValue) {
    			elementIndex = index;
    		}
    		});
    	return elementIndex;
    };
    
    //เก็บตำแหน่ง x,y และ element ที่เริ่มคลิกลาก
    function dragStart(e) {
    	initialX = e.clientX;
    	initialY = e.clientY;
    	//Set current Element
    	currentElement = e.target;
    }
    
    function dragOver(e) {
    	e.preventDefault();
    }
    
    //เหตุการณ์วาง
    const drop = (e) => {
    	e.preventDefault();
    
        // เก็บตำแหน่ง x, y ที่วาง
    	let newX = e.clientX;
    	let newY = e.clientY;
    
    	//Set targetElement(where we drop the picked element).It is based on mouse position
        // เก็บ element ที่จะถูกวางแทนที่
    	let targetElement = document.elementFromPoint(newX, newY);
    
        // ตรวจสอบว่า element ที่ถูกวาง เป็น TD หรือไม่ ถ้าใช่ จะเปลี่ยนให้เป็น TR ที่เป็น parent ของ TD นั้น
        // เนื่องจากการลากวาง จะเป็นการลากวางและแทนที่ทั้งแถว ซึ่งก็คือ TR
    	if(targetElement.nodeName == "TD")
    	{
    		targetElement = targetElement.parentNode;
    	}
    
        // เก็บ value จาก element ต้นทางและปลายทาง
    	let currentValue = currentElement.getAttribute("data-value");
    	let targetValue = targetElement.getAttribute("data-value");
    
    	//หาตำแหน่ง TR จาก value
    	let [currentPosition, targetPosition] = [
    		getPosition(currentValue),
    		getPosition(targetValue),
    	];
    	initialX = newX;
    	initialY = newY;
    
    	try {
    
    	if (currentPosition < targetPosition) {
          
          // ถ้าแถวที่เริ่มลาก น้อยกว่าแถวที่จะวาง จะทำการแทรกในตำแหน่งด้านล่างของแถวที่จะวาง
    	  targetElement.insertAdjacentElement("afterend", currentElement);
    	} else {
    
          // ถ้าแถวที่เริ่มลาก มากกว่าแถวที่จะวาง จะทำการแทรกในตำแหน่งด้านบนของแถวที่จะวาง
    	  targetElement.insertAdjacentElement("beforebegin", currentElement);
    	}
    	} catch (err) {}
    }; 

    4. เมื่อทดสอบการทำงาน รายชื่อจังหวัดในตารางจะสามารถคลิก ลาก และวางไปยังตำแหน่งที่ต้องการได้

    5. และเมื่อ drop ลงไปยังตำแหน่งที่ต้องการ จังหวัดที่ลากมาก็จะแทรกเข้าไปยังตำแหน่งที่ drop

    จากซีรี่ส์ Drag & Drop Row ใน Table อันยาวนานนี้ ผู้เขียนหวังเป็นอย่างยิ่งว่าจะมีประโยชน์กับผู้อ่านไม่มากก็น้อยที่จะนำไปประยุกต์ใช้กับงานของตัวเอง แล้วเจอกันใหม่โอกาสหน้า เมื่อผู้เขียนจะมีเหตุให้ต้องเข้ามาอีก สวัสดีครับ


    แหล่งข้อมูลอ้างอิง

  • ฟังก์ชัน array_agg และ array_to_string ใน PostgreSQL 

    ผู้เขียนได้มีโอกาสพัฒนาโปรเจ็คใหม่ที่จะต้องไปใช้งานฐานข้อมูล PostgreSQL ซึ่งไม่เคยใช้งานมาก่อน โดยคำสั่งพื้นฐานทั่วไปก็จะเหมือนๆ กัน ตามมาตรฐานคำสั่ง SQL แต่ก็มีบางฟังก์ชันที่มีเฉพาะเจาะจงแตกต่างกันไปในแต่ละฐานข้อมูล อย่างเช่นที่จะกล่าวถึงในบล็อกนี้

    โดยโจทย์ก็คือ ต้องการรวมข้อมูลในฟิลด์เดียวกันที่อยู่กันคนละเรคคอร์ด ให้มาเชื่อมต่อกัน เช่น

    มีตารางข้อมูลจังหวัด และอำเภอ ความต้องการก็คือ นำชื่ออำเภอทั้งหมดภายในจังหวัดเดียวกันมาแสดงเรียงต่อ ดังตัวอย่าง

    “ปัตตานี” “หนองจิก, โคกโพธิ์”
    “ยะลา”“เบตง, ธารโต, รามัน”
    “สงขลา”“กระแสสินธุ์, หาดใหญ่, คลองหอยโข่ง”

    ซึ่งภายใน PostgreSQL เราจะใช้งานฟังก์ชัน array_agg และ array_to_string

    array_agg(expression [order by [sort_expression {asc | desc}], [...])

    โดย

    expression จะเป็นฟิลด์ หรือกลุ่มฟิลด์ที่จะดึงมารวมเข้าไว้ด้วยกัน

    sort_expression ฟิลด์ที่จะใช้ในการเรียง

    array_to_string(anyarray, delimeter [, null_string])

    โดย

    anyarray ข้อมูลในรูปแบบ array

    delimeter ตัวอักษรหรือสัญลักษณ์ที่ใช้คั่นระหว่างข้อมูลที่มาเชื่อมต่อกัน

    null_string ตัวอักษรหรือสัญลักณ์ที่จะใช้แสดงเมื่อ element ใน array มีค่าเป็น null

    ตัวอย่างคำสั่ง

    select province, array_agg (amphoe) amphoe
    from test
    group by province

    ซึ่งจะได้ผลลัพธ์ดังรูป

    เนื่องจากจะเป็นการรวมข้อมูลในแต่ละจังหวัด เราก็เลยจะต้องใช้ฟังก์ชัน group by ร่วมด้วย

    จากผลลัพธ์จะเห็นว่าเราจะได้ข้อมูลที่ใกล้เคียงกับที่เราต้องการแล้ว เพียงแต่ข้อมูลอำเภอจะยังอยู่ในรูปแบบ array เพราะฉะนั้น เราจะต้องใช้ฟังก์ชัน array_to_string มาช่วยแปลงข้อมูล array มาอยู่ในรูปแบบ string ตามที่เราต้องการ ดังตัวอย่าง

    select province, array_to_string(array_agg(amphoe), ', ') amphoe
    from test
    group by province

    จะได้ผลลัพธ์ดังภาพ

    ซึ่งบทความนี้เป็นเพียงหนึ่งตัวอย่างของฟังก์ชันของ PostgreSQL ที่แตกต่างจากฐานข้อมูลอื่นๆ ซึ่งเราก็จะต้องศึกษาเรียนรู้กันต่อไป ถ้าผู้เขียนมีโอกาสได้ใช้งานฟังก์ชันหรือฟีเจอร์อะไรแปลกใหม่ ก็จะพยามนำมาบันทึกไว้ ในโอกาสต่อๆ ไป

    ขอบคุณครับ


    ข้อมูลอ้างอิง

  • เทคนิคการขยับแถวขึ้นลงใน Table ด้วยวิธี Drag & Drop ใน Blazor

    สำหรับ blog นี้ของผู้เขียน ถือว่าเป็นซีรี่ส์ที่ต่อเนื่องมาจาก https://sysadmin.psu.ac.th/2021/05/25/ขยับแถว-row-ขึ้น-ลง-ใน-asp-net-gridview-ด้วย-j/ และ https://sysadmin.psu.ac.th/2021/05/27/ขยับแถว-row-ขึ้น-ลง-ใน-asp-net-gridview-ด้วย-c/ ก็คือผู้เขียนจะนำเสนอวิธีการขยับแถวอีกวิธีหนึ่ง ที่น่าจะเฟรนด์ลี่ต่อผู้ใช้มากกว่า นั่นก็การ Drag & Drop ก็คือผู้ใช้งานสามารถเลือกคลิก ลาก และวาง เพื่อจัดลำดับได้ตามความต้องการ ซึ่งเมื่อผู้เขียนมาทำงานบน Blazor พบว่าการ implement เรื่องนี้สามารถทำได้ง่ายมาก โดยไม่ต้องพี่งพา javascript แต่อย่างใด เรามาดูกันเลยครับ

    1. เพิ่มโค้ด HTML ในส่วนของการแสดงผลข้อมูลในรูปแบบ Table

    @if (provinces != null)
    {
        <table class="table table-striped" >
            <thead>
                <tr >
                    <th>ลำดับ</th>
                    <th>จังหวัด</th>
                </tr>
            </thead>
            <tbody>
                @foreach (var pr in provinces)
                {
                    <tr role="button" class="cursor-pointer"  >
                        <td>@pr.ID</td>
                        <td>@pr.Name</td>
                    </tr>
                }
            </tbody>
        </table>
    }

    2. เพิ่มโค้ด C# ในส่วนที่ควบคุมการทำงานและจำลองข้อมูล

    private List<Province> provinces = new List<Province>();
    
    protected override void OnInitialized()
    {
    
    	provinces.AddRange(new List<Province> {
    		new Province(1,"สงขลา"),
    		new Province(2,"ปัตตานี"),
    		new Province(3,"ยะลา"),
    		new Province(4,"นราธิวาส"),
    		new Province(5,"สตูล")
    	});
    
    }
    
    public class Province
    {
    	public Int32 ID;
    	public string Name;
    	public Province(int id, string name)
    	{
    		ID = id;
    		Name = name;
    	}
    }

    ซึ่งจะได้ผลลัพธ์หน้าจอดังรูป และเป้าหมายของเราก็คือสามารถคลิกเลือกจังหวัด จากนั้นลากและวางไปยังตำแหน่งที่ต้องการได้

    3. จากนั้นเพิ่มโค้ดส่วนที่ควบคุมการ Drag และ Drop ทั้งใน HTML และ C#

    @if (provinces != null)
    {
        <table class="table table-striped" ondragover="event.preventDefault();">
            <thead>
                <tr >
                    <th>ลำดับ</th>
                    <th>จังหวัด</th>
                </tr>
            </thead>
            <tbody>
                @foreach (var pr in provinces)
                {
                    <tr role="button" class="cursor-pointer" draggable="true"
                @ondrop="@(()=> Drop(pr))" @ondrag="@(e => StartDrag(pr))" >
                        <td>@pr.ID</td>
                        <td>@pr.Name</td>
                    </tr>
                }
            </tbody>
        </table>
    }
    • ondragover=”event.preventDefault();” เป็นการขัดขวางการทำงานปกติของการ drag บน object เพื่อให้สามารถ drop ได้
    • @ondrop=”@(()=> Drop(pr))” เรียกฟังก์ชัน Drop พร้อมกับส่ง pr (จังหวัด) เมื่อมีเหตุการณ์ drop เกิดขึ้น
    • @ondrag=”@(e => StartDrag(pr))” เรียกฟังก์ชัน StartDrage พร้อมกับส่ง pr เมื่อมีเหตุการณ์ drag เกิดขึ้น
    /// <summary>
    /// เก็บตำแหน่งของจังหวัดที่คลิกเลือก เมื่อเริ่ม drag
    /// </summary>
    /// <param name="province"></param>
    private void StartDrag(Province province)
    {
    	currentIndex = GetIndex(province);
    }
    
    /// <summary>
    /// หาตำแหน่งของจังหวัดที่อยู่จาก list
    /// </summary>
    /// <param name="province"></param>
    /// <returns></returns>
    int GetIndex(Province province)
    {
    	return provinces.FindIndex(p => p.ID == province.ID);
    }
    
    /// <summary>
    /// เมื่อ Drop จังหวัดที่ drag มาลงในตำแหน่งที่ต้องการ
    /// </summary>
    /// <param name="province"></param>
    void Drop(Province province)
    {
    	if (province != null)
    	{
    		// หาตำแหน่งของจังหวัดที่ถูก drop
    		var index = GetIndex(province);
    
    		// หาจังหวัดที่ถูก drag มา จาก index ที่เก็บไว้ตั้งแต่เริ่ม drag
    		var current = provinces[currentIndex];
    
    		// ลบจังหวัดที่ถูก drag มา ออกจาก list
    		provinces.RemoveAt(currentIndex);
    
    		// แทรกจังหวัดที่ถูก drag มา ลงในตำแหน่งที่ drop
    		provinces.Insert(index, current);
    
    		StateHasChanged();
    	}
    }

    4. เมื่อทดสอบการทำงาน รายชื่อจังหวัดในตารางจะสามารถคลิก ลาก และวางไปยังตำแหน่งที่ต้องการได้

    5. และเมื่อ drop ลงไปยังตำแหน่งที่ต้องการ จังหวัดที่ลากมาก็จะแทรกเข้าไปยังตำแหน่งที่ drop

    ขั้นตอนถัดไป ท่านผู้อ่านก็แค่ทำการบันทึกตำแหน่งใหม่ของจังหวัดลงในฐานข้อมูลหรือทำอย่างอื่นได้ต่อไป ซึ่งวิธีการนี้เราสามารถนำไปประยุกต์ใช้กับคอมโพเน้นอื่นๆ ได้ เช่น li, div หรืออย่างอื่นที่ผู้ใช้ในการนำเสนอข้อมูลในรูปแบบรายการ

    ผู้เขียนหวังเป็นอย่างยิ่งว่าบทความนี้น่าจะมีประโยชน์ต่อผู้อ่านไม่มากก็น้อย แล้วเจอกันใหม่โอกาสหน้า สวัสดีครับ


    แหล่งข้อมูลอ้างอิง

  • เทคนิคการดึงข้อมูล Youtube Video ผ่าน Youtube API

    กลับมาพบกับท่านผู้อ่านอีกครั้งหนึ่ง หลังจากห่างหายกันไปนาน เนื่องจากผู้เขียนได้รับโจทย์ที่ทำให้ต้องทำการ research เล็กน้อย จึงขอนำมาบันทึกไว้กันลืมสำหรับตัวเอง และเผื่อท่านผู้อ่านแวะเข้ามาจะสามารถนำไปประยุกต์ใช้ได้

    โจทย์ที่ว่าก็คือ จะต้องดึงข้อมูลรายละเอียดต่างๆ ของ Youtube จาก URL ที่ระบุ ไม่ว่าจะเป็น Thumbmail, Title, Description ซึ่งจากการไปศึกษา API ที่ Youtube ได้จัดเตรียมไว้ให้ ก็พบว่าสามารถใช้งานได้อย่างไม่ยุ่งยากแต่อย่างใด เพียงแต่เราจะต้องมี API Key ที่ต้องใช้ในการเข้าถึงข้อมูลต่างๆ ของ Youtube ดังนั้นเริ่มต้นเราจะไปดูวิธีการให้ได้มาซึ่ง API Key ก่อน

    1. เข้าไปที่ https://console.cloud.google.com/cloud-resource-manager และ login ด้วย google account ให้เรียบร้อย จากนั้นทำการสร้าง Project ใหม่

    2. ป้อนชื่อโปรเจ็ค ในที่นี้สมมติเป็น Sample Project กด CREATE

    3. จากนั้นให้ทำการ Enable API เพื่อให้โปรเจ็คที่เราสร้างสามารถใช้งานได้ โดยให้ไปที่เมนูแฮมเบอร์เกอร์ -> APIs & Services -> Enabled APIs & services

    4. กด + ENABLE APIS AND SERVISES

    5. ค้น Youtube Data API

    6. เลือก YouTube Data API v3 และกด Enable

    7. กด Enable

    8. กลับไปที่ Enable APIS And Services และเลือก YouTube Data API v3

    9. เลือก CREATE CREDENTIALS

    10. เลือก Public data และกด NEXT

    11. จะได้ API Key ที่จะนำไปใช้ในการเขียนโปรแกรมเพื่อดึงข้อมูลจาก Youtube API ให้สำเนาเก็บไว้ใช้งานในขั้นตอนต่อไป

    เมื่อเราได้ API Key มาแล้ว เราก็จะมาถึงขั้นตอนในการเขียนโปรแกรมกันต่อ เนื่องจากในตอนนี้ผู้เขียนพัฒนาโปรเจ็คต่างๆ ด้วย Blazor ซึ่งเป็นเฟรมเวิร์คปัจจุบันของ ASP.NET ตัวอย่างโค้ดผู้เขียนก็จะขอเขียนด้วย Blazor ซึ่งในส่วนของการติดต่อ API ก็น่าจะพอเป็นแนวทางให้กับการพัฒนาด้วยเฟรมเวิร์คอื่นหรือภาษาอื่นได้ และเพื่อไม่ให้บล็อกนี้ยาวเกินไป ผู้เขียนขอข้ามขั้นตอนการสร้างโปรเจ็คไปเลย

    1. เริ่มต้นเพื่อให้โปรเจ็คของเราสามารถใช้งาน Youtube API ได้ เราจะต้องติดตั้ง Library ที่จำเป็นก่อน โดยเราจะติดตั้งผ่านเครื่องมือที่เรียกว่า Nuget โดยคลิกขวาที่โปรเจ็ค เลือก Manage Nuget Packages…

    2. ค้น Youtube เลือก Google.Apis.Youtube.v3 และ Install

    3. และเพื่อให้ page ที่เราจะเขียนโปรแกรมติดต่อกับ Youtube API สามารถใช้งาน Library ดังกล่าวได้ เราจะต้องเพิ่ม using Library นั้นๆ เข้ามาก่อน

    @using Google.Apis.Services
    @using Google.Apis.YouTube.v3
    @using Google.Apis.YouTube.v3.Data
    

    4. สร้าง YoutubeService เพื่อใช้ในการติดต่อ API และเราจะกำหนด API Key ใน object นี้ ดังโค้ดตัวอย่าง

    var youtubeService = new YouTubeService(new BaseClientService.Initializer()
    {
        ApiKey = "XXxxXxXxXXX0xxxxXXxxxXxXXxxxxXXxX0XX0x0",
        ApplicationName = this.GetType().ToString()
    });

    5. สร้าง object ListRequest และกำหนดข้อมูลที่ต้องการเป็น snippet ผ่านเมทธอด List ซึ่ง snippet จะเป็น object ที่บรรจุข้อมูลต่างๆ ของวิดีโอยูทูปนั้นๆ

    VideosResource.ListRequest req = youtubeService.Videos.List("snippet");

    6. กำหนดค่าแปรวิดีโอที่เราต้องการดึงข้อมูล ซึ่งจะเป็น parameter ที่อยู่หลังตัวแปร v เช่น https://www.youtube.com/watch?v=4VTx7oIzv_8 ค่าที่เราต้องการคือ 4VTx7oIzv_8

    req.Id = "4VTx7oIzv_8";

    7. จากนั้นทำการดึงข้อมูลจาก Youtube โดยเรียกเมทธอด Execute และดึงข้อมูลที่ต้องการจาก property ต่างๆ ที่อยู่ใน object Snippet

    VideoListResponse resp = req.Execute();
    if (resp.Items.Count > 0)
    {
    	title = resp.Items.ElementAt(0).Snippet.Title;
    	description = resp.Items.ElementAt(0).Snippet.Description;
        ThumbnailDetails tmb = resp.Items.ElementAt(0).Snippet.Thumbnails;
        thumbnail = tmb.Default__.Url;
    }

    8. และโด้ด HTML ส่วนแสดงผล

    <p><b>URL : </b> @url</p>
    <p><b>Title : </b> @title</p>
    <p><b>Description : </b> @title</p>
    <p><b>Thumbnail : </b> </p>
    <img src="@thumbnail" />

    9. จะได้ผลลัพธ์ดังตัวอย่าง

    10. นอกจากนี้ผู้อ่านสามารถดึงข้อมูลอื่นๆ ที่เกี่ยวข้องกับ video นั้นๆ ได้ผ่าน object Snippet รวมทั้งมี object ย่อยๆ อีกมากมายอย่างเช่น Thumbnails เป็นต้น หรือผู้อ่านจะทดสอบการทำงานได้ง่ายๆ ผ่าน query string โดยให้แทนที่ API Key ด้วยคีย์ของท่านเอง และ Video ID ด้วย ID ของ Video ที่ต้องการได้เลย ดังตัวอย่าง

    https://www.googleapis.com/youtube/v3/videos?part=snippet&id={video IDs}&key={API key}

    สุดท้ายนี้ผู้เขียนหวังเป็นอย่างยิ่งว่าบทความนี้จะมีประโยชน์กับท่านผู้อ่านได้ไม่มากก็น้อย ขอบคุณสำหรับการแวะเข้ามาอ่าน และสวัสดีครับ


    แหล่งข้อมูลอ้างอิง

  • ขยับแถว (row) ขึ้น/ลง ใน ASP.NET Gridview ด้วย Code Behind

    เช่นเคยครับ จากบล็อก ขยับแถว (row) ขึ้น/ลง ใน ASP.NET Gridview ด้วย jQuery เป็นการเพิ่มฟีเจอร์ให้กับ ASP.NET Gridview ด้วยการประยุกต์ใช้ jQuery บทความต่อมา ก็จะเป็นการเพิ่มฟีเจอร์เดียวกัน แต่จะเป็นการพัฒนาด้วยโค้ดฝั่ง code behind

    เนื่องจากการทำงานฝั่ง code behind จะไม่สามารถเคลื่อนย้ายเร็คคอร์ดของ gridview ได้โดยตรง ดังนั้นเราจะทำทางอ้อม ด้วยการใช้ฟิลด์ในตารางฟิลด์หนึ่งมาเป็นข้อมูลสำหรับเรียงใน Gridview เมื่อต้องการย้ายเร็คคอร์ด เราก็จะเปลี่ยนตัวเลขในฟิลด์นี้ แล้วทำการเรียงข้อมูลใหม่ และแสดงผลข้อมูลใน Gridview อีกครั้ง ไปดูขั้นตอนต่างๆ กันเลยครับ

    1. ในส่วนของโค้ด HTML จะมีการปรับปรุงเพิ่มเล็กน้อยเฉพาะในส่วนของปุ่ม UP/DOWN ซึ่งเราจะเปลี่ยนไปใช้ปุ่มที่เป็นคอนโทรลของ ASP.NET เพื่อให้สามารถเขียนโปรแกรมควบคุมจากฝั่ง code behind ได้

    <asp:GridView ID="gvBib" runat="server" AutoGenerateColumns="False" OnRowCommand="gvBib_RowCommand" >
        <Columns>
            <asp:BoundField DataField="BIB_NO" HeaderText="Bib#" />
            <asp:BoundField DataField="TITLE" HeaderText="Title" />
            <asp:BoundField DataField="AUTHOR" HeaderText="Author" />
            <asp:BoundField DataField="CALL_NO" HeaderText="CallNo" />
            <asp:BoundField DataField="ISBN" HeaderText="ISBN" />
            <asp:TemplateField>
                <ItemTemplate>
                    <asp:Button ID="btnUp" runat="server" Text="UP" CommandName="up" CommandArgument="<%# ((GridViewRow) Container).RowIndex %>"></asp:Button>
                    <asp:Button ID="btnDown" runat="server" Text="DOWN" CommandName="down" CommandArgument="<%# ((GridViewRow) Container).RowIndex %>"></asp:Button>
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>

    โดย

    • CommndName ใช้สำหรับตรวจสอบว่าเป็นการเลือก up หรือ down
    • CommandArgument ใช้สำหรับระบุแถวที่คลิกเลือก

    2. ในส่วนของโค้ดที่ใช้สร้างข้อมูลเพื่อแสดงใน Gridview เราจะเพิ่มฟิลด์ขึ้นมาอีก 1 ฟิลด์ เพื่อใช้กำหนดลำดับการแสดงผล จากตัวอย่างโค้ด ก็คือฟิลด์ SEQ

    DataTable dt = new DataTable();
    dt.Columns.AddRange(new DataColumn[6] { new DataColumn("BIB_NO"), 
                                            new DataColumn("TITLE"), 
                                            new DataColumn("AUTHOR"),
                                            new DataColumn("CALL_NO"),
                                            new DataColumn("ISBN"),
                                            new DataColumn("SEQ")});
    dt.Rows.Add("001", "1 ทศวรรษ ดัชนีสุขภาพคนไทย", "สำนักงานคณะกรรมการสุขภาพแห่งชาติ (สช.)", "WA13 ห159 2556", "9786160822258", 1);
    dt.Rows.Add("002", "ความลับในร่างกายมนุษย์ที่เราไม่เคยรู้", "ฟรานซิส, เกวิน", "QS4 ฟ133a 2560", "9786168022887", 2);
    dt.Rows.Add("003", "The best ICU", "ดุสิต สถาวร", "WX218 B561 2560", "9786168122020", 3);
    dt.Rows.Add("004", "COVID-19 โรคระบาดแห่งศตวรรษ", "นำชัย ชีววิวรรธน์", "QW168.5.C8 น515c 2563", "9789740217060", 4);
    dt.Rows.Add("005", "Good health & smart life ในวัย 40+", "ไวต์, จอห์น", "WT104 ว967g 2560", "9786160827237", 5);
    gvBib.DataSource = dt;
    gvBib.DataBind();
    
    //เก็บข้อมูล
    ViewState["dtBook"] = dt;

    3. เพิ่มโค้ดในส่วนของ gvBib_RowCommand ซึ่งเป็น event ที่จะเกิดเมื่อมีการคลิกปุ่ม UP หรือ DOWN

    protected void gvBib_RowCommand(object sender, GridViewCommandEventArgs e)
    {
    	DataTable dt = (DataTable)ViewState["dtBook"];
    
            //เก็บแถวที่คลิกเลือก
    	int curIdx = Convert.ToInt32(e.CommandArgument);
    
    	if(e.CommandName == "up")   //ถ้ากดปุ่ม UP
    	{
    		//กำหนดลำดับใหม่ให้กับแถวก่อนหน้ากับแถวปัจจุบันให้สลับกัน
    		dt.Rows[curIdx - 1]["SEQ"] = curIdx;
    		dt.Rows[curIdx]["SEQ"] = curIdx - 1;
    	}
    	else if (e.CommandName == "down")   //ถ้ากดปุ่ม DOWN
    	{
    		//กำหนดลำดับใหม่ให้กับแถวถัดไปกับแถวปัจจุบันให้สลับกัน
    		dt.Rows[curIdx + 1]["SEQ"] = curIdx;
    		dt.Rows[curIdx]["SEQ"] = curIdx + 1;
    	}
    	dt.AcceptChanges();
    
    	//กำหนดให้ข้อมูลเรียงตามฟิลด์ SEQ
    	dt.DefaultView.Sort = "SEQ";
    
    	//เซ็ตข้อมูลที่มีการเรียงลำกับแล้วกลับไปให้ DataTable
    	dt = dt.DefaultView.ToTable();
    
    	//กำหนดข้อมูลที่เรียงลำดับใหม่แล้วให้กับ Gridview และแสดผล
    	gvBib.DataSource = dt;
    	gvBib.DataBind();
    
    	//เก็บข้อมูลกลับเข้า ViewState
    	ViewState["dtBook"] = dt;
    }

    เมื่อทดลองรัน จะปรากฏผลลัพธ์ดังรูปด้านล่าง

    เมื่อทดลองคลิกปุ่ม UP หรือ DOWN ระบบก็สามารถย้ายแถวที่ต้องการไปยังตำแหน่งที่ก่อนหน้าหรือถัดไปได้อย่างถูกต้อง ยกเว้นการคลิก UP ที่แถวแรก และ DOWN ที่แถวสุดท้าย จะเกิด Error ดังภาพ

    และ
    ซึ่งเกิดจากการเลื่อนไปยังตำแหน่งที่ไม่มีในข้อมูล จึงจะต้องปรับแก้โค้ดอีกเล็กน้อยดังนี้
    //เก็บแถวที่คลิกเลือก
    int curIdx = Convert.ToInt32(e.CommandArgument);
    
    if(e.CommandName == "up")   //ถ้ากดปุ่ม UP
    {
        //ตรวจสอบว่าไม่ใช่แถวแรกหรือไม่
        if (curIdx != 0)
        {
            //กำหนดลำดับใหม่ให้กับแถวก่อนหน้ากับแถวปัจจุบันให้สลับกัน
            dt.Rows[curIdx - 1]["SEQ"] = curIdx;
            dt.Rows[curIdx]["SEQ"] = curIdx - 1;
        }
    }
    else if (e.CommandName == "down")   //ถ้ากดปุ่ม DOWN
    {
        //ตรวจสอบว่าไม่ใช่แถวสุดท้ายหรือไม่
        if (curIdx != dt.Rows.Count - 1)
        {
            //กำหนดลำดับใหม่ให้กับแถวถัดไปกับแถวปัจจุบันให้สลับกัน
            dt.Rows[curIdx + 1]["SEQ"] = curIdx;
            dt.Rows[curIdx]["SEQ"] = curIdx + 1;
        }
    }

    โดยเราจะต้องตรวจสอบเพิ่มเติมก่อนว่า เมื่อคลิกปุ่ม UP จะต้องไม่ใช่แถวแรก และคลิกปุ่ม DOWN จะต้องไม่ใช่แถวสุดท้าย เมื่อทดสอบรันอีกครั้ง ก็พบว่าสามารถทำงานได้ปกติ เมื่อคลิกปุ่ม UP ที่แถวแรก หรือปุ่ม DOWN ที่แถวสุดท้าย ก็จะไม่เกิด Error

    ผู้เขียนหวังเป็นอย่างยิ่งว่าบทความนี้จะมีประโยชน์ไม่มากก็น้อย ที่ผู้อ่านน่าจะสามารถนำไปประยุกต์ใช้ในงานของตัวเอง

    จนกว่าจะพบกันใหม่ สวัสดีครับ


    แหล่งข้อมูลอ้างอิง

  • ขยับแถว (row) ขึ้น/ลง ใน ASP.NET Gridview ด้วย jQuery

    บางครั้งการแสดงผลข้อมูลใน Gridview จะมีความต้องการให้ผู้ใช้งานสามารถกำหนดลำดับข้อมูลได้ ในบทความนี้ผู้เขียนจะยกตัวอย่างการประยุกต์ใช้ jQuery มาเพิ่มความสามารถให้กับ Gridview ให้สามารถขยับแถวที่ต้องการไปอยู่ในตำแหน่งที่ต้องการได้

    โดยมีขั้นตอนดังต่อไปนี้

    1. เพิ่มโค้ด HTML สำหรับแสดงผลข้อมูล Gridview

    <asp:ScriptManager runat="server"></asp:ScriptManager>
    
    <asp:GridView ID="gvBib" runat="server" AutoGenerateColumns="False">
        <Columns>
    
            <asp:BoundField DataField="BIB_NO" HeaderText="Bib#" />
            <asp:BoundField DataField="TITLE" HeaderText="Title" />
            <asp:BoundField DataField="AUTHOR" HeaderText="Author" />
            <asp:BoundField DataField="CALL_NO" HeaderText="CallNo" />
            <asp:BoundField DataField="ISBN" HeaderText="ISBN" />
            <asp:TemplateField>
                <ItemTemplate>
                    <asp:UpdatePanel runat="server">
                        <ContentTemplate>
                            <button class="up">UP</button>
                            <button class="down">DOWN</button>
                        </ContentTemplate>
                    </asp:UpdatePanel>
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>

    จะสังเกตว่าจะมีฟิลด์ที่เป็น ItemTemplate สำหรับแสดงผลปุ่ม UP และปุ่ม DOWN สำหรับใช้ในการเลื่อน row นั้นๆ ขึ้นหรือลง

    และเหตุผลที่จะต้องมี UpdatePanel ครอบปุ่มไว้ เพราะทุกครั้งที่มีการกด จะเกิดการ Postback ทำให้ข้อมูลจะถูก Bind ซ้ำ การเรียงลำดับก็จะกลับคืนไปเหมือนเดิม จึงจำเป็นต้องทำ Partial Load เพื่อป้องกันการ Bind ข้อมูลซ้ำ

    2. เพิ่มโค้ดใน event Page_Load ในหน้า code behind เพื่อจำลองข้อมูลที่จะใช้แสดงใน GridView

    protected void Page_Load(object sender, EventArgs e)
    {
        if(!IsPostBack)
        {
            DataTable dt = new DataTable();
            dt.Columns.AddRange(new DataColumn[5] { new DataColumn("BIB_NO"), 
                                                    new DataColumn("TITLE"), 
                                                    new DataColumn("AUTHOR"),
                                                    new DataColumn("CALL_NO"),
                                                    new DataColumn("ISBN")});
            dt.Rows.Add("001", "1 ทศวรรษ ดัชนีสุขภาพคนไทย", "สำนักงานคณะกรรมการสุขภาพแห่งชาติ (สช.)", "WA13 ห159 2556", "9786160822258");
            dt.Rows.Add("002", "ความลับในร่างกายมนุษย์ที่เราไม่เคยรู้", "ฟรานซิส, เกวิน", "QS4 ฟ133a 2560", "9786168022887");
            dt.Rows.Add("003", "The best ICU", "ดุสิต สถาวร", "WX218 B561 2560", "9786168122020");
            dt.Rows.Add("004", "COVID-19 โรคระบาดแห่งศตวรรษ", "นำชัย ชีววิวรรธน์", "QW168.5.C8 น515c 2563", "9789740217060");
            dt.Rows.Add("005", "Good health & smart life ในวัย 40+", "ไวต์, จอห์น", "WT104 ว967g 2560", "9786160827237");
            gvBib.DataSource = dt;
            gvBib.DataBind();
        }
        
    }

    เนื่องจากโค้ดตัวอย่างมีการใช้งาน class DataTable และ DataColumn ซึ่งอยู่ใน namespace System.Data เพราะฉะนั้นจะต้อง Import namespace นี้ด้วย

    using System.Data;

    3. เพิ่มโค้ด jQuery สำหรับควบคุมการทำงานปุ่ม UP/DOWN โดยหลักการทำงานคือ เมื่อคลิกปุ่ม UP หรือ DOWN แถวที่เลือก จะถูกขยับหรือลง 1 เรคคอร์ด

    //เมื่อคลิกปุ่ม UP
    $(document).on("click", ".up", function () {
    
        //เก็บเร็คคอร์ดที่ถูกคลิกเอาไว้
        var curRow = $(this).closest('tr');
    
    
        //ย้ายเร็คคอร์ดปัจจุบัน ไปอยู่ในตำแหน่งก่อนหน้า เร็คคอร์ดที่อยู่ก่อนหน้า
        curRow.insertBefore(curRow.prev());
    
    });
    
    //เมื่อคลิกปุ่ม DOWN
    $(document).on("click", ".down", function () {
        var curRow = $(this).closest('tr');
        curRow.insertAfter(curRow.next());
    });

    เมื่อทดลองรัน จะปรากฏผลลัพธ์ดังรูปด้านล่าง

    เมื่อทดลองกดปุ่ม UP ในช่อง Bib#005 เรคคอร์ดนั้นก็จะขยับขึ้นไปอยู่บน Bib#004 ดังรูป
    แต่ถ้าทดลองกดปุ่ม UP ในเรคคอร์ด Bib#001 เรคคอร์ดนี้จะถูกเลื่อนขึ้นไปอยู่เหนือเรคคอร์ดที่เป็น Header ของตารางซึ่งไม่ถูกต้อง
    4. เราจะต้องแก้ไขโค้ด jQuery เพิ่มเติม โดยแก้ไขเฉพาะกรณีคลิกปุ่ม UP เพื่อตรวจสอบก่อนว่า เรคคอร์ดที่คลิกเป็นเรคคอร์ดบนสุด (ยกเว้น header) หรือยัง
    //เมื่อคลิกปุ่ม UP
    $(document).on("click", ".up", function () {
    
        //เก็บเร็คคอร์ดที่ถูกคลิกเอาไว้
        var curRow = $(this).closest("tr");
    
        //เก็บเร็คคอร์ดแรกสุดของตารางเอาไว้ ซึ่งก็คือเรคคอร์ดหัวตาราง 
        //ที่เราจะไม่อนุญาตให้เอาเรคคอร์ดอื่นมาแทรก
        var firstRow = $("[id*=gvBib] tr:first");
    
        //ตรวจสอบว่าเร็คอคอร์ดก่อนหน้าของเร็คคอร์ดที่เรากดปุ่ม คือเร็คคอร็ดที่เป็นหัวตารางหรือไม่
        //ถ้าไม่ใช่ก็จะทำการย้ายเร็คคอร์ด
        if (curRow.prev().html() != firstRow.html() ) {
    
            //ย้ายเร็คคอร์ดปัจจุบัน ไปอยู่ในตำแหน่งก่อนหน้า เร็คคอร์ดที่อยู่ก่อนหน้า
            curRow.insertBefore(curRow.prev());
        }
    });

    เมื่อทดสอบอีกครั้ง ก็จะพบว่า ไม่สามารถกด UP เรคคอร์ดที่อยู่ใต้ Header ได้อีกแล้ว

    ก็หวังเป็นอย่างยิ่งว่าบทความนี้จะมีประโยชน์ไม่มากก็น้อยต่อผู้อ่าน ที่สามารถนำไปประยุกต์ใช้กับงานของตัวเองได้ สวัสดีครับ


    แหล่งข้อมูลอ้างอิง

    • https://stackoverflow.com/questions/16524497/jquery-to-move-row-up-and-down
    • https://stackoverflow.com/questions/36243730/jquery-to-compare-rows-in-two-tables
  • ซ่อน/แสดง คอลัมน์ใน ASP.NET GridView จาก Code Behind

    จากบทความ ซ่อน/แสดง คอลัมน์ใน ASP.NET GridView ด้วย jQuery ท่านผู้อ่านที่ได้เข้าไปอ่านแล้วอาจจะมีคำถามว่าถ้าไม่อยากใช้ jQuery ล่ะ เนื่องด้วยสาเหตุอะไรก็แล้วแต่ วันนี้ผมก็จะมานำเสนอการซ่อน/แสดงคอลัมน์ใน ASP.NET GridView อีกวิธี ซึ่งจะเป็นการควบคุมจาก code behind ที่เป็นภาษา C# หรือ VB.NET ในที่นี่ผู้เขียนจะใช้ภาษา C#

    ซึ่งจะมีขั้นตอนต่างๆ ดังต่อไปนี้

    1. ตัวอย่างโค้ด HTML จะมีการแก้ไขเพิ่มขึ้นอีกเล็กน้อยจากบทความเดิม

    <asp:CheckBox ID="chkCallNo" Text=" Show CallNo from code behind" runat="server" Checked="true"
                  AutoPostBack="true" OnCheckedChanged="chkCallNo_CheckedChanged" />
    <hr />
    
    <asp:GridView ID="gvBib" runat="server" AutoGenerateColumns="False">
        <Columns>
            <asp:BoundField DataField="BIB_NO" HeaderText="Bib#" />
            <asp:BoundField DataField="TITLE" HeaderText="Title" />
            <asp:BoundField DataField="AUTHOR" HeaderText="Author" />
            <asp:BoundField DataField="CALL_NO" HeaderText="CallNo" />
            <asp:BoundField DataField="ISBN" HeaderText="ISBN" />
        </Columns>
    </asp:GridView>

    โดยสิ่งที่เพิ่มขึ้นมาจะอยู่ที่ CheckBox คือ

    • AutoPostBack=”true” เพื่อให้มีการ PostBack ทุกครั้งที่มีการคลิก Checkbox
    • OnCheckedChanged=”chkCallNo_CheckedChanged” คือ event ที่อยู่ใน code behind ที่จะถูกเรียกใช้เมื่อมีการคลิก

    2. โค้ดในส่วนของการจำลองข้อมูล สามารถใช้โค้ดเดิมจากบทความเก่าได้เลย

    if(!IsPostBack)
    {
        DataTable dt = new DataTable();
        dt.Columns.AddRange(new DataColumn[5] { new DataColumn("BIB_NO"), 
                                                new DataColumn("TITLE"), 
                                                new DataColumn("AUTHOR"),
                                                new DataColumn("CALL_NO"),
                                                new DataColumn("ISBN")});
        dt.Rows.Add(1, "1 ทศวรรษ ดัชนีสุขภาพคนไทย", "สำนักงานคณะกรรมการสุขภาพแห่งชาติ (สช.)", "WA13 ห159 2556", "");
        dt.Rows.Add(2, "ความลับในร่างกายมนุษย์ที่เราไม่เคยรู้", "ฟรานซิส, เกวิน", "QS4 ฟ133a 2560", "9786168022887");
        dt.Rows.Add(3, "The best ICU", "ดุสิต สถาวร", "WX218 B561 2560", "9786168122020");
        dt.Rows.Add(4, "COVID-19 โรคระบาดแห่งศตวรรษ", "นำชัย ชีววิวรรธน์", "QW168.5.C8 น515c 2563", "9789740217060");
        dt.Rows.Add(5, "Good health & smart life ในวัย 40+", "ไวต์, จอห์น", "WT104 ว967g 2560", "9786160827237");
        gvBib.DataSource = dt;
        gvBib.DataBind();
    }

    3. เพิ่มโค้ดใน chkCallNo_CheckedChanged เพื่อควบคุมการซ่อน/แสดงคอลัมน์ที่ต้องการ

    protected void chkCallNo_CheckedChanged(object sender, EventArgs e)
    {
        gvBib.Columns[3].Visible = chkCallNo.Checked;
    }

    โดย gvBib.Columns[3].Visible จะเป็นการกำหนดให้คอลัมน์ที่ 3 ของ Gridview แสดงผลหรือไม่ ซึ่งก็คือคอลัมน์ CallNo นั่นเอง (จะเริ่มนับตั้งแต่ 0)

    4. ทดสอบการใช้งาน

    5. จะเห็นว่าระบบสามารถทำงานได้ตามความต้องการ คอลัมน์จะซ่อน/แสดงได้ตามเงื่อนไขที่เราเลือกจาก checkbox แต่จะสังเกตเห็นว่า ทุกครั้งที่มีการเลือก checkbox ระบบจะ refresh หน้าจอใหม่ทุกครั้ง ซึ่งถ้าในหน้าจอที่เรากำลังทำงานมีข้อมูลอื่นๆ อีกหลายอย่าง ก็จะถูกโหลดซ้ำโดยไม่จำเป็น เพื่อแก้ไขปัญหานี้ ASP.NET จะมีเครื่องมือที่เรียกว่า UpdatePanel ซึ่งจะทำงานในแบบ Partial Load ได้ตามตามเงื่อนไขที่เรากำหนด โดยเราจะต้องปรับแก้โค้ด HTML เพิ่มเติมดังนี้

    <asp:ScriptManager runat="server"></asp:ScriptManager>
    
    <asp:CheckBox ID="chkCallNo" Text=" Show CallNo from code behind" runat="server" AutoPostBack="true" Checked="true" OnCheckedChanged="chkCallNo_CheckedChanged" />
    <hr />
    
    <asp:UpdatePanel ID="UpdatePanel1" runat="server">
        <ContentTemplate>
            <asp:GridView ID="gvBib" runat="server" AutoGenerateColumns="False">
                <Columns>
                    <asp:BoundField DataField="BIB_NO" HeaderText="Bib#" />
                    <asp:BoundField DataField="TITLE" HeaderText="Title" />
                    <asp:BoundField DataField="AUTHOR" HeaderText="Author" />
                    <asp:BoundField DataField="CALL_NO" HeaderText="CallNo" />
                    <asp:BoundField DataField="ISBN" HeaderText="ISBN" />
                </Columns>
            </asp:GridView>
        </ContentTemplate>
        <Triggers>
            <asp:AsyncPostBackTrigger ControlID="chkCallNo" EventName="CheckedChanged" />
        </Triggers>
    </asp:UpdatePanel>

    สิ่งที่เพิ่มเติมเข้ามาคือ

    • ScriptManager สำหรับใช้ควบคุมการทำงาน UpdatePanel
    • UpdatePanel ใช้ครอบ component หรือพื้นที่ที่เราต้องให้สามารถทำ Partial Load ได้ ในที่นี่คือเราครอบ Gridview นั่นเอง
    • Triggers จะเป็นการกำหนดเพื่อให้เกิด Partial Load ตาม control และ event ที่ได้ระบุเอาไว้ ในที่นี้คือ จะโหลดเมื่อ chkCallNo เกิด event CheckdChanged ซึ่งก็คือเหตุการณ์คลิกนั่นเอง

    ทดสอบ run ก็จะได้ผลลัพธ์ดังรูปด้านล่าง

    จะเห็นว่าหลังจากมีการปรับแก้โค้ดไปแล้ว ทุกครั้งที่มีการคลิก CheckBox และมีการซ่อน/แสดงคอลัมน์ จะไม่มีการ refresh หน้าจออีกแล้ว เพราะ UpdatePanel ที่เราได้เพิ่มเข้าไปจะควบคุมให้มีการโหลดข้อมูลใหม่เฉพาะ component ที่อยู่ภายใน UpdatePanel เท่านั้น

    จากบทความนี้ก็จะเป็นวิธีการซ่อน/แสดงคอลัมน์ใน Gridview อีกทางเลือกหนึ่ง ที่ผู้อ่านสามารถนำไปประยุกต์ใช้กับงานของตัวเองได้ ในกรณีที่เราไม่อยากเพิ่ม jQuery เข้ามาในโครงการที่กำลังทำ หรือเห็นว่าไม่ถนัดในการใช้งาน jQuery ก็ตามแต่ ซึ่งผู้อ่านสามารถเลือกแนวทางได้เองตามอัธยาศัย สวัสดีครับ


    แหล่งข้อมูลอ้างอิง

  • ซ่อน/แสดง คอลัมน์ใน ASP.NET GridView ด้วย jQuery

    การแสดงผลข้อมูลใน Gridviews ในบางสถานการณ์เราต้องการซ่อนข้อมูลบางคอลัมน์ออกไปก่อนตามเงื่อนไขใดๆ และเมื่อเงื่อนไขเปลี่ยนเราก็จะแสดงข้อมูลในคอลัมน์ที่ถูกซ่อนนั้นออกมา

    ในบทความนี้ผู้เขียนจะแสดงตัวอย่างการ ซ่อน/แสดง คอลัมน์ใน ASP.NET GridView ด้วยชุดคำสั่ง jQuery โดยมีขั้นตอนดังต่อไปนี้

    1. เพิ่มโค้ด HTML ดังตัวอย่างด้างล่าง ซึ่งเป็นโค้ดที่แสดง Checkbox เพื่อใช้เลือกแสดงคอลัมน์ CallNo และ ASP.NET GridView ที่มีข้อมูล 5 คอลัมน์

    <asp:CheckBox ID="chkCallNo" Text=" Show CallNo" runat="server" Checked="true" />
    
    <hr />
    <asp:GridView ID="gvBib" runat="server" AutoGenerateColumns="False" >
    	<Columns>
    		<asp:BoundField DataField="BIB_NO" HeaderText="Bib#" />
    		<asp:BoundField DataField="TITLE" HeaderText="Title" />
    		<asp:BoundField DataField="Author" HeaderText="Author" />
    		<asp:BoundField DataField="CALL_NO" HeaderText="CallNo" />
    		<asp:BoundField DataField="ISBN" HeaderText="ISBN" />
    	</Columns>
    </asp:GridView>

    2. เพิ่มโค้ดใน event Page_Load ในหน้า code behind เพื่อจำลองข้อมูลที่จะใช้แสดงใน GridView

    protected void Page_Load(object sender, EventArgs e)
    {
        if(!IsPostBack)
        {
            DataTable dt = new DataTable();
            dt.Columns.AddRange(new DataColumn[5] { new DataColumn("BIB_NO"), 
                                                    new DataColumn("TITLE"), 
                                                    new DataColumn("AUTHOR"),
                                                    new DataColumn("CALL_NO"),
                                                    new DataColumn("ISBN")});
            dt.Rows.Add(1, "1 ทศวรรษ ดัชนีสุขภาพคนไทย", "สำนักงานคณะกรรมการสุขภาพแห่งชาติ (สช.)", "WA13 ห159 2556", "");
            dt.Rows.Add(2, "ความลับในร่างกายมนุษย์ที่เราไม่เคยรู้", "ฟรานซิส, เกวิน", "QS4 ฟ133a 2560", "9786168022887");
            dt.Rows.Add(3, "The best ICU", "ดุสิต สถาวร", "WX218 B561 2560", "9786168122020");
            dt.Rows.Add(4, "COVID-19 โรคระบาดแห่งศตวรรษ", "นำชัย ชีววิวรรธน์", "QW168.5.C8 น515c 2563", "9789740217060");
            dt.Rows.Add(5, "Good health & smart life ในวัย 40+", "ไวต์, จอห์น", "WT104 ว967g 2560", "9786160827237");
            gvBib.DataSource = dt;
            gvBib.DataBind();
        }
        
    }

    เนื่องจากโค้ดตัวอย่างมีการใช้งาน class DataTable และ DataColumn ซึ่งอยู่ใน namespace System.Data เพราะฉะนั้นจะต้อง Import namespace นี้ด้วย

    using System.Data;

    3. เพิ่มโค้ด jQuery เพื่อควบคุมการแสดง/ซ่อน คอลัมน์ เมื่อมีการคลิก เลือก/ยกเลิก เช็คบ๊อก (โดยในบทความนี้ผู้เขียนขออนุญาตข้ามขั้นตอนการติดตั้ง jQuery ออกไป)

    $(function () {
    
        //bind event click ให้กับ checkbox
        $("[id*=chkCallNo]").click(function () {
    		
    	//เก็บสถานะของ checkbox ว่าเลือกอยู่หรือไม่
            var isChecked = $(this).is(":checked");
    		
    	//เก็บ element ของหัวคอลัมน์ CallNo
            var th = $("[id*=gvBib] th:contains('CallNo')");
    	
            //ถ้า checkbox ถูกเลือก จะแสดงคอลัมน์ CallNo และถ้าไม่ ก็จะซ่อนคอลัมน์
            th.css("display", isChecked ? "" : "none");
    	
            //วนลูปเรคอร์ดที่เหลือทั้งหมด
            $("[id*=gvBib] tr").each(function () {
    	    
                //ใช้ลำดับของหัวคอลัมน์ CallNo (th.index) มาหาคอลัมน์ CallNo ที่อยู่ record ข้อมูล 
                //และกำหนดให้ซ่อนหรือแสดงตามการเลือก checkbox
                $(this).find("td").eq(th.index()).css("display", isChecked ? "" : "none");
            });
        });
    
    });

    ทดสอบ run ก็จะได้ผลลัพธ์ดังรูปด้านล่าง

    และเมื่อคลิกเช็คบ๊อก Show CallNo ออก คอลัมน์ CallNo ใน Gridview ก็จะหายไป

    จากตัวอย่างโค้ดในบทความนี้ จะเห็นว่าการซ่อนหรือแสดงคอลัมน์ด้วย jQuery ไม่ได้มีความยุ่งยาก สามารถนำไปประยุกต์ใช้กับงานของท่านได้

    ซึ่งผู้เขียนหวังเป็นอย่างยิ่งว่าบทความนี้น่าจะมีประโยชน์กับท่านผู้อ่านไม่มากก็น้อย สวัสดีครับ


    แหล่งข้อมูลอ้างอิง

  • Bootstrap Modal Full Screen

    หลายๆ ท่านที่เคยใช้งาน Bootstrap เป็น Frontend Framework น่าจะเคยใช้ modal กันมาบ้าง ซึ่ง modal เป็นจาวาสคลิปต์ปลั๊กอิน มีไว้สำหรับการแสดงผลข้อมูล ทั้งรูปภาพ ข้อความ หรือแบบฟอร์มรับข้อมูล ( html input form ) ในลักษณะป๊อปอัพ ซึ่ง modal ของ bootstrap สามารถแสดงผลได้หลายขนาด ทั้งแบบปกติ แบบเล็ก และแบบใหญ่ ขึ้นอยู่กับ class ที่เราสามารถระบุเพิ่มเข้าไปว่าต้องการให้แสดงผลเป็นแบบไหน

    ตัวอย่างโค้ด modal dialog และปุ่มสำหรับเปิด modal

    <!-- Button trigger modal -->
    <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#myModal">Modal</button>
    
    <!-- Modal -->
    <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
    	<div class="modal-dialog" role="document">
    		<div class="modal-content">
    			<div class="modal-header">
    				<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
    				<h4 class="modal-title" id="myModalLabel">Modal title</h4>
    			</div>
    			<div class="modal-body">
    				...
    			</div>
    
    		</div>
    	</div>
    </div>
    

    จะได้ผลลัพธ์ดังรูป

    ถ้าต้องการให้ modal แสดงผลใหญ่ขึ้นหรือเล็กลง ให้ระบุ modal-lg modal-sm หลัง modal-dialog ดังตัวอย่าง

    <div class="modal-dialog modal-lg" role="document">
    <div class="modal-dialog modal-sm" role="document">
    

    ถ้าเราต้องการให้ modal สามารถแสดงผลแบบเต็มจอ (full screen) จะไม่สามารถทำได้ (อ้างอิงจากเวอร์ชัน 3.3 ที่ผู้เขียนใช้งาน แต่จากการตรวจสอบล่าสุดพบว่าเวอร์ชัน 5.0 สามารถทำได้แล้ว)

    แต่เราจะใช้ความรู้ในเรื่อง css มาปรับแต่งเพิ่มเติมเพื่อให้สามารถแสดงผลได้ตามความต้องการ โดยเราจะต้องเพิ่ม css class ที่ระบุคุณสมบัติที่จำเป็น ดังตัวอย่าง

    <style>
    .fullscreen {
    	margin: 0;
    	top: 0;
    	left: 0;
    	width: 100% !important;
    	height: 100% !important;
    }
    </style>
    

    ระบุ class fullscreen ไว้ด้านหลัง modal-dialog

    <div class="modal-dialog fullscreen" role="document">

    modal จะได้แสดงผลเต็มจอดังรูป

    และเพื่อให้การแสดงผล modal มีความยืดหยุ่นและมีการทำงานใกล้เคียงกับ dialog ของ Windows ทั่วไป คือสามารถขยายให้เป็น full screen และย่อให้กลับมาขนาดเท่าเดิม โดยสิ่งที่เราต้องทำเพิ่มคือ

    1. เพิ่มปุ่ม fullscreen
      • เมื่อ modal แสดงผลอยู่ในสภาพปกติ
      • เมื่อคลิกปุ่ม fullscreen จะเปลี่ยนการแสดงผล modal ให้เป็นแบบ fullscreen
      • ซ่อนปุ่ม fullscreen และแสดงผลปุ่ม restore แทน
    2. เพิ่มปุ่ม restore
      • เมื่อ modal แสดงผลในรูปแบบ fullscreen
      • เมื่อคลิกปุ่ม restore จะเปลี่ยนการแสดงผล modal กลับไปเป็นสภาพปกติ
      • ซ่อนปุ่ม restore และแสดงผลปุ่ม fullscreen แทน

    โดยมีขั้นตอนดังต่อไปนี้

    1. เพิ่มปุ่ม fullscreen และปุ่ม restore ใน div class=”modal header”

    <div class="modal-header">
            //ปุ่ม Close
    	<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
    
            //ปุ่ม restore
    	<button type="button" class="close restore-diloag" title="restore" style="display: none; vertical-align: middle" tabindex="-1"><i class='fa fa-clone' style="font-size: 16px; font-weight: bolder"></i>&nbsp;</button>
    
            //ปุ่ม fullscreen
    	<button type="button" class="close fullscreen-dialog" title="maximize" style="vertical-align: middle" tabindex="-1"><i class='fa fa-window-maximize' style="font-size: 16px"></i>&nbsp;</button>
    	<h4 class="modal-title" id="myModalLabel">Modal title</h4>
    </div>
    

    จะเห็นว่าปุ่มที่เพิ่มขึ้นมาจะมีการระบุชื่อ class “restore-dialog” และ “fullscreen-dialog” ซึ่งจะใช้ในการอ้างถึงในโค้ด jQuery ที่ใช้ควบคุมการทำงานเมื่อมีการคลิกปุ่มนั้นๆ

    2. เนื่องจากผู้เขียนใช้ icon ที่อยู่ใน font awesome ดังนั้นจะต้องเพิ่ม link style sheet เพื่ออ้างไปถึงไฟล์ css ของ font awesome ภายนอกไซต์ที่กำลังพัฒนา (CDN) โดยไปเพิ่มไว้ใน tag <head></head>

    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" />

    3. เพิ่มชุดคำสั่ง jQuery

    <script>
    	$(function () {
    
    		//เมื่อคลิกปุ่ม fullscreen
    		$(document).on('click', '.fullscreen-dialog', function (e) {
    
    			//เพิ่ม class fullscreen เพื่อให้แสดงผลแบบเต็มจอ
    			$('div.modal-dialog').addClass("fullscreen");
    
                            //แสดงปุ่ม restore
    			$('div.modal-dialog').find('.restore-diloag').show();
    
                            //ซ่อนปุ่ม fullscreen
    			$('div.modal-dialog').find('.fullscreen-dialog').hide();
    		});
    
    		//เมื่อคลิกปุ่ม restore
    		$(document).on('click', '.restore-diloag', function (e) {
    
                            //ลบ class fullscreen เพื่อให้กลับไปแสดงผลเหมือนเดิม
    			$('div.modal-dialog').removeClass("fullscreen");
    
                            //ซ่อนปุ่ม restore
    			$('div.modal-dialog').find('.restore-diloag').hide();
    
                            //แสดงปุ่ม fullscreen
    			$('div.modal-dialog').find('.fullscreen-dialog').show();
    		});
    	});
    </script>

    4. ทดสอบ ก็จะได้ผลลัพธ์ดังภาพ

    จะเห็นว่ามีปุ่ม fullscreen แสดงอยู่ เมื่อกด modal จะแสดงผลเป็น fullscreen ดังภาพ

    และเมื่อกดปุ่ม restore หน้าจอ modal ก็จะแสดงผลกลับไปเป็นเหมือนเดิม

    หวังว่าบทความนี้จะเป็นประโยชน์ไม่มากก็น้อย น่าจะพอเป็นแนวทางให้ผู้อ่านนำไปประยุกต์ใช้กับงานของตัวเองนะครับ

    สวัสดีครับ


    แหล่งข้อมูลอ้างอิง