Search code examples
javascriptc#htmlasp.netlabel

ASP NET Label Get Dynamic Value using Javascript


I have a sample records of 4 student names:

  1. John Doe
  2. Jane Smith
  3. Alice Johnson
  4. Bob Anderson

I am having below html code which take a list of records from db and store:

<asp:TemplateField HeaderText="StudentName" ItemStyle-HorizontalAlign="Center" HeaderStyle-Width="10%" ItemStyle-Width="10%">
        <ItemTemplate>
                <asp:Label ID="lblStudentName" runat="server" Text='<%# Bind("StudentName") %>' Visible="true"></asp:Label>
                <img src="../Images/copy.png" alt="Printer" onclick="copyLabelValue('lblStudentName')" class="col-2" style="cursor: pointer; width: 30px; height: 30px;" />
        </ItemTemplate>
</asp:TemplateField>

and a javascript of

function copyLabelValue(label) {           
            var value = document.getElementById(label).innerText;
            navigator.clipboard.writeText(value);
}

but the value keeps returning the first name "John Doe" to me even when i trigerred the third/forth copy image. Tried some other ways but still couldnt get what i want which able to return me the third value if i pressed on the third copy image and vice versa.

Ways:

document.getElementById(label).innerText returns "John Doe"

document.getElementById('<%=lblStudentName.ClientID%>').innerText returns "John Doe"

$('#<%=lblStudentName.ClientID%>').html() returns "John Doe"

document.getElementById(label).innerHtml returns undefined

document.getElementById('<%=lblStudentName.ClientID%>').innerHtml returns undefined


Solution

  • OK, you don't show if this is a repeater, gridview, or even a details view.

    However, it probably does not matter.

    The issue of course is that you don't have JUST ONE instance of the label, or the image or whatever. As a result each row is "repeated" many times , and in fact both the label, and your image button is ALSO repeated many times.

    As a result, then each row of controls are actually "generated" and given a specific row ID. A great way to see how this works is to hit f12 (browser debug tools), select "elements", and then click on the "pointer" and now click on a element in the page - you see that EACH ROW of controls is given a specific name (usually prefixed by the control such as gridview, then the control name, and then a row number!).

    So, there are several ways to do this. One simple way is to PASS the row value, and that's probably the most simple.

    So, say this markup:

            <div style="float:left">
                <asp:GridView ID="GridView1" runat="server" ShowHeaderWhenEmpty="true"
                    AutoGenerateColumns="False" DataKeyNames="ID" CssClass="table table-hover" 
                    Width="55em">
                    <Columns>
                        <asp:BoundField DataField="FirstName" HeaderText="FirstName" />
                        <asp:BoundField DataField="LastName" HeaderText="LastName" />
                        <asp:BoundField DataField="HotelName" HeaderText="HotelName" />
                        <asp:BoundField DataField="City" HeaderText="City" />
                        <asp:BoundField DataField="Province" HeaderText="Province" />
                        <asp:BoundField DataField="Description" HeaderText="Description" />
                        <asp:TemplateField>
                            <ItemTemplate>
    
                                <img src="../Content/copy.png" 
                                    onclick="copyLabelValue('<%# Eval("HotelName") %>')"
                                    style="width:48px;height:48px" 
                                    />
                            </ItemTemplate>
                        </asp:TemplateField>
                    </Columns>
                </asp:GridView>
            </div>
    
            <div style="float:left;margin-left:40px">
                <h4>Paste test area</h4>
                <asp:TextBox ID="TextBox1" runat="server" 
                    TextMode="MultiLine" Height="117px" Width="304px"></asp:TextBox>
            </div>
    
    
            <script>
                function copyLabelValue(cText) {
                    navigator.clipboard.writeText(cText);
    
                }
            </script>
    

    In above, I just pass the "expression" to the js code.

    So, code to load is this:

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        If Not IsPostBack Then
            LoadGrid
        End If
    End Sub
    
    Sub LoadGrid()
    
        GridView1.DataSource =
            MyRst("SELECT * FROM tblHotelsA ORDER BY HotelName")
        GridView1.DataBind()
    
    End Sub
    

    And the result is thus this:

    enter image description here

    However, let's say we want to grab the control on that grid row.

    So, say this markup:

                        <asp:TemplateField>
                            <ItemTemplate>
                                <asp:Label ID="lblHotelName" runat="server" 
                                    Text='<%# Eval("HotelName") %>' style="display:none"></asp:Label>
    
                                <img src="../Content/copy.png" id="myimagebtn" runat="server"
                                    onclick="copyLabelValue2(this.id,'myimagebtn')"
                                    style="width:48px;height:48px" 
                                    />
                            </ItemTemplate>
                        </asp:TemplateField>
    

    And then this:

                function copyLabelValue2(btn, cText) {
                    var tlbl = btn.replace(cText, 'lblHotelName')
                    var HotelText = document.getElementById(tlbl).innerText
                    navigator.clipboard.writeText(HotelText);
                }
    

    There are other ways. I think often just passing the value using a server side expression works quite well. However, if the value has single (or double) quotes, then the code can fail.

    As a result, it probably better to pass the "id" of the current control (make sure there is a runat="server", so the server side automatic control re-name occurs for each row of the repeater/gridview/listview (in fact any data repeating control).

    Another possible trick? I often just make up a custom attribute for the control in question. This allows MULTIPLE values to be passed!

    Say like this:

                        <asp:TemplateField>
                            <ItemTemplate>
                                <img src="../Content/copy.png" id="myimagebtn" runat="server"
                                    onclick="copyLabelValue3(this)"
                                    style="width:48px;height:48px" 
                                    myHotel='<%# Eval("HotelName") %>'
                                    />
                            </ItemTemplate>
                        </asp:TemplateField>
    

    And then this code:

                function copyLabelValue3(btn) {
                    var HotelText = btn.getAttribute("myHotel")
                    alert(HotelText)
                    navigator.clipboard.writeText(HotelText);
                }
    

    but, note that I could say pass Hotel and City by just adding another "made up" attribute

    eg:

        <img src="../Content/copy.png" id="myimagebtn" runat="server"
            onclick="copyLabelValue3(this)"
            style="width:48px;height:48px" 
            myHotel='<%# Eval("HotelName") %>'
            myCity='<%# Eval("City") %>'
            />
    

    However, since this means the data is being repeated (sent) to the browser 2 times, then with a large page, this would start to add additional payload to the web page. However, for a few extra values here and there, then adding "made up" attributes works rather well.