ASP.NET กับ jQuery: MasterPage getElementById ใน ContentPlaceHolder

ทำไป แก้ไป …

เมื่อเราใช้ MasterPage เป็น Layout หลักของ Web การสร้าง new page ใหม่ที่อ้างอิง MasterPage หลักของ web ใน page ใหม่ก็จะประกอบไปด้วย Content เป็นส่วนๆ ซึ่งในแต่ละ content ก็จะถูกนำไปแทนที่ใน ContentPlaceHolder ของ MasterPage แล้วเราจะอ้างอิง control เช่น TextBox ของเราได้อย่างไรใน JavaScript

ตัวอย่าง code สมมติผมมี control ตามนี้วางอยู่ใน Web Page ที่มี MasterPage

<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
    Message:
    <asp:TextBox ID="MessageTextBox" runat="server"></asp:TextBox>
    <asp:Button ID="AlertMessageCommand" runat="server" Text="Alert สิ!" OnClientClick="alertSi()"/>
</asp:Content>

จาก code ด้านบน OnClientClick ผูก method alertSi() ที่เป็น javascript หน้าที่ของเราก็คือต้องใส่ code javascript ที่เอาค่าจาก textbox แล้ว alert ออกมาเฉยๆ ดังนั้นเป้าหมายของเราก็คือต้องรู้ id ของ MessageTextBox ที่อยู่ใน MasterPage แล้วให้ได้

หลายๆท่าน รวมทั้งผมด้วย แก้ปัญหานี้โดยไม่คิดมาก run page ขึ้นมาเลย แล้วคลิกขวาดู View Source ซะเลย เราก็จะเห็น id ของ MessageTextBox แล้ว นั่นคือ

<input name="ctl00$MainContent$MessageTextBox" type="text" id="MainContent_MessageTextBox" />

อ้าเขียน method alertSi() ได้แล้ว แบบนี้

<script>
    function alertSi() {
        var textbox = document.getElementById('MainContent_MessageTextBox');
        alert("คุณ alert ข้อความนี้: " + textbox.value);
    }
</script>

ลองใช้งานดู ก็ work ดีครับ เมื่อพิจารณา pattern ของการสร้าง id ของ master page ก็ทำให้เราเข้าใจว่า มันจะเติม id ของมันเองแล้วขั้นด้วย _ และต่อด้วย id ของ textbox ใน page ลูก ดังนั้นในทุกครั้งที่เราเขียน javascript ที่ใช้ master page จะต้องอ้างอิง id ตามรูปแบบนี้ ในครั้งต่อไปเราก็ไม่จำเป็นต้องดู source อีกแล้ว

เวลาก็ผ่านไปเราก็เขียนด้วยวิธีนี้มาตลอด จนกระทั้งวันหนึ่ง เราก็เกิดความคิดที่จะ reuse เจ้า method alertSi ขึ้นมาซะอย่างงั้น จึง move มันไปไว้ที่ file javascript ที่ชื่อว่า ChavPLib.cs แล้วก็ include มันเข้ามาใน web projects อื่น เอาละสิ MasterPage อื่นดันใช้ id ชื่ออื่นดันใช้ชื่อ MainBody ทำไงดีละทีนี้ ต้องกลับไปแก้ javasript ให้เป็น MainBody_MessageTextBox อีกเหรอโอ้ว แจกให้คนอื่นใช้ไปเยอะแล้วด้วยทำไงดี

และแล้วผมก็เจอ jQuery เมื่อลองดูวิธีการที่มันใช้ค้นหา control บน HTML เอ๊ะนี่มันใช่เลย แถมเป็นการค้นหาได้ในรูปแบบทั่วไปซะด้วย ผมก็เลยกลับมาแก้ไข code เก่าให้ง่ายกว่าเดิมก็เลยได้ code แบบนี้

เพิ่ม jQuery lib เข้าไปที่ MasterPage

<script src="Scripts/jquery-1.4.1.min.js" type="text/javascript"></script>

แก้ไข javascript alertSi

function alertSi() {
    var textbox = $('input[id$=MessageTextBox]');
    alert("คุณ alert ข้อความนี้: " + textbox.val());
}

เรียบร้อยครับ อธิบายได้ว่า jQuery จะค้นหาวัตถุ input ที่มี id ที่ลงท้ายด้วย MessageTextBox นั่นเองครับ

id$=”xxx”  หมายความว่า id ที่มีคำลงท้าย(suffix) เท่ากับ xxx

id^=”yyy” หมายความว่า id ที่มีคำขึ้นต้น(prefix) เท่ากับ yyy

วิธีแก้ไขวิธีอื่น โดยไม่ใช้ jQuery ก็มีครับ เช่นให้เขียน javascript ไว้ที่ page load แบบนี้

    protected void Page_Load(object sender, EventArgs e)
    {
        ClientScript.RegisterClientScriptBlock(this.GetType(), "MyScript",
        string.Format(@"function alertSi()
            {{
                var textbox = document.getElementById('{0}');
                if (textbox != null) alert('คุณ alert ข้อความนี้: ' + textbox.value);
            }}"
        , MessageTextBox.ClientID), true);

    }

ซึ่งมันจะ print javascript ไว้ที่ page ของเราหน้าตาเหมือนกับที่เราไม่ใช้ jQuery ครับ

หรืออีกวิธีที่ง่ายกว่านั้น

var textbox = document.getElementById('<%=MessageTextBox.ClientID%>');

ทั้งสองแบบที่ไม่ใช้ jQuery ค้นหา textbox ใช้งานได้ทั้งคู่ครับ

แต่จะเกิดปัญหาเมื่อเราแยกไปไว้ใน file javascript ต่างหากเพื่อ reuse method และกรณีที่เราเจอ MessageTextBox ที่เป็น input textbox HTML ธรรมดาแล้ว ทดลองดูก็ได้ครับ

ผมขอจบบทความเพียงเท่านี้

ขอบคุณครับ 😉

Advertisements

#asp-net, #javascript, #jquery