jQuery & JavaScript

Read GridView row values and HiddenFields on the client with jQuery

jQuery & JavaScript · · Published 2026-09-16

Sometimes the browser should react to a row without a postback: fill a dialog, enable a toolbar, compute a total. A GridView renders an ordinary <table>, so jQuery can read any row. The trick is to put the values you need in the markup in a form that is easy to read.

Markup: HiddenField or data attributes

<asp:GridView ID="gvProducts" runat="server" AutoGenerateColumns="false" CssClass="products">
    <Columns>
        <asp:TemplateField HeaderText="Product">
            <ItemTemplate>
                <asp:HiddenField ID="hfId" runat="server" Value='<%# Eval("ProductId") %>' />
                <span class="name"><%#: Eval("Name") %></span>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:BoundField DataField="Stock" HeaderText="Stock" />
        <asp:TemplateField>
            <ItemTemplate>
                <button type="button" class="pick" data-id='<%# Eval("ProductId") %>'
                        data-price='<%# ((decimal)Eval("Price")).ToString(System.Globalization.CultureInfo.InvariantCulture) %>'>Pick</button>
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>
<p>Selected: <span id="picked">none</span></p>

An asp:HiddenField renders <input type="hidden"> with a generated id per row; its id looks like gvProducts_hfId_0, so find it relative to the row rather than by id. A data- attribute on the button is even simpler to read.

jQuery

$(function () {
  $(".products").on("click", "button.pick", function () {
    var $row = $(this).closest("tr");

    var idFromHidden = $row.find("input[type=hidden]").first().val(); // ids end in _0, _1…
    var idFromData = $(this).data("id");          // number, converted by jQuery
    var price = parseFloat($(this).attr("data-price"));
    var name = $row.find(".name").text();
    var stock = parseInt($row.children("td").eq(1).text(), 10);

    $(".products tr").removeClass("is-picked");
    $row.addClass("is-picked");
    $("#picked").text(name + " (#" + idFromData + "), " + price.toFixed(2) + ", stock " + stock);
  });
});

Delegating from the table (.on("click", "button.pick", …)) needs one handler for all rows and keeps working when the grid is refreshed inside an UpdatePanel, as long as the table element itself is replaced along with its rows; if it is, bind to a container outside the panel instead.

.data("id") converts numeric-looking values to numbers; use .attr("data-id") to get the exact string, for example for ids with leading zeros.

Sending the choice back to the server

Put the selected id in a page-level HiddenField outside the grid, then post normally:

$("#<%= hfSelectedId.ClientID %>").val(idFromData);
protected void btnContinue_Click(object sender, EventArgs e)
{
    if (int.TryParse(hfSelectedId.Value, out int id)) LoadProduct(id); // validate: the client can send anything
}

On the server side, reading the selected row without script is covered in GridView selected row in code-behind.

Common mistakes

Official documentation