问题
I've got a repeater control containing a textbox and a label. I want to set the label value based on the value the user sets in the textbox, on the client-side to avoid a round-trip to the server.
I wrote a JavaScript function which is called by the textbox OnChange event. Now I just need to access the textbox and label in that function. I understand I should be accessing the controls via <%# Container.FindControl(...).ClientID %>
but I cannot get it to work in the OnChange event. I also tried <%# Container.ItemIndex %>
, in case there was a problem with the nested quotes, but that didn't work either.
I'm a novice with ASP.NET so I assume I'm missing something obvious.
Here's what I've got so far (currently attempting to use <%# Container.ItemIndex %>
):
<asp:Content ID="Content3" ContentPlaceHolderID="regionBody" runat="server">
<table class="DataGrid">
<tr class="HeaderStyle">
<td>Item</td>
<td>Weight (kg)</td>
<td>Total Volume (m3):</td>
</tr>
<asp:Repeater ID="rptItems" runat="server"
OnItemDataBound="rptItems_ItemDataBound" >
<ItemTemplate>
<tr class='<%# Container.ItemIndex % 2 == 0
? "ItemStyle"
: "AlternatingItemStyle" %>'
style="text-align: center">
<td>
<asp:Label ID="lblItemNum" runat="server" />
</td>
<td>
<asp:TextBox ID="txtWeight" Height="20px" Width="40px"
runat="server" Visible="true"
OnChange="ValidateItemWeightAndSetVolume(0);" />
</td>
<td>
<asp:Label ID="lblVolume" runat="server"
Visible="true" CssClass="numericLeft" />
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
</table>
</asp:Content>
And here's the JavaScript function:
function ValidateItemWeightAndSetVolume(itemIndex) {
var weightId = "regionBody_rptItems_txtWeight_" + itemIndex;
var volumeId = "regionBody_rptItems_lblVolume_" + itemIndex;
var txtWeight = document.getElementById(weightId);
var lblVolume = document.getElementById(volumeId);
var volume = 0;
var validated = ValidateItemWeight(txtWeight);
if (validated) {
var weight = parseFloat(txtWeight.value);
volume = weight / <%=VOLUMETRIC_WEIGHT_CONVERSION%>;
}
// asp:label is rendered as a span in HTML. So to set the value,
// have to set the inner HTML.
lblVolume.innerHTML = volume;
}
The second function, ValidateItemWeight, just checks the user entered a numeric value between certain limits and displays an alert if they didn't.
The code above works since I'm just passing an integer into the function: OnChange="ValidateItemWeightAndSetVolume(0);"
, but that is only applicable to the first repeater item. If I modify it as follows the function doesn't run: OnChange="ValidateItemWeightAndSetVolume(<%# Container.ItemIndex %>);"
回答1:
You can use <%# Container.ItemIndex %>
as ourmandave suggested in the comment:
... OnChange="ValidateItemWeightAndSetVolume(<%# Container.ItemIndex %>`);" />
But it would be better if you could use javascript to get the label (instead of index concat with string-id) like this (jQuery):
Use OnChange = ValidateItemWeightAndSetVolume(this)
and change the js function like this:
function ValidateItemWeightAndSetVolume(textBox) {
var txtWeight = textBox;
var lblVolume = $(textBox).closest("td").next("td").find("span")[0];
var volume = 0;
var validated = ValidateItemWeight(txtWeight);
if (validated) {
var weight = parseFloat(txtWeight.value);
volume = weight / <%=VOLUMETRIC_WEIGHT_CONVERSION%>;
}
lblVolume.innerHTML = volume;
}
Also, you can use a HeaderTemplate
and FooterTemplate
inside a Repeater
like this:
<asp:Repeater ID="rptItems" runat="server">
<HeaderTemplate>
<table class="DataGrid">
<tr class="HeaderStyle">
<td>Item</td>
<td>Weight (kg)</td>
<td>Total Volume (m3):</td>
</tr>
</HeaderTemplate>
<ItemTemplate>
<!-- Your item template here -->
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
This keeps the mark-up clean imo.
来源:https://stackoverflow.com/questions/33905959/accessing-repeater-item-controls-in-onchange-javascript