I have a sample records of 4 student names:
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
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:
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.