locked
Reading data on client side from html table generated by ASP.Net gridview RRS feed

  • Question

  • User1120190316 posted

    I have a gridview control that has a button in its right-most column which, when clicked, should copy data from the selected row.  

    Here is the html source code generated by the gridview control for the first record of the resulting table:

    <table cellspacing="0" cellpadding="3" rules="cols" border="1" id="ctl00_cphMain_gvTaskRecur" style="background-color:White;border-color:#999999;border-width:1px;border-style:Groove;width:100%;border-collapse:collapse;">
        <tr style="color:White;background-color:#000084;font-weight:bold;">
            <th scope="col">Task Name</th>
            <th scope="col">Goal</th>
            <th scope="col">High Priority</th>
            <th scope="col">Start Date</th>
            <th scope="col">End Date</th>
            <th scope="col">&nbsp;</th>
        </tr>
        <tr style="color:Black;background-color:#EEEEEE;">
            <td style="width:30%;">
                        <span id="ctl00_cphMain_gvTaskRecur_ctl02_lblRecurTaskName">Send out new invoices</span>
                    </td>
            <td style="width:30%;">
                            <span id="ctl00_cphMain_gvTaskRecur_ctl02_lblGoalName" style="display:inline-block;width:80%;"></span>
                    </td>
            <td>
                            <input id="ctl00_cphMain_gvTaskRecur_ctl02_chkHighPriority" type="checkbox" name="ctl00$cphMain$gvTaskRecur$ctl02$chkHighPriority" />
                    </td>
            <td>
                            <span id="ctl00_cphMain_gvTaskRecur_ctl02_lblEditTaskStartDate">9/1/2009</span>
                    </td>
            <td>
                            <span id="ctl00_cphMain_gvTaskRecur_ctl02_lblEditTaskEndDate"></span>
                    </td>
            <td>
                <input type="button" name="ctl00$cphMain$gvTaskRecur$ctl02$btnEditTask" value="Edit" onclick="editTask();return false;__doPostBack('ctl00$cphMain$gvTaskRecur$ctl02$btnEditTask','')" id="ctl00_cphMain_gvTaskRecur_ctl02_btnEditTask" />&nbsp;
                            <input type="submit" name="ctl00$cphMain$gvTaskRecur$ctl02$btnDeleteTask" value="Delete" onclick="return confirm('Are you sure you want to delete this Event/Appointment?');" id="ctl00_cphMain_gvTaskRecur_ctl02_btnDeleteTask" />
                            <input type="button" name="ctl00$cphMain$gvTaskRecur$ctl02$btnTaskWebLinksA" value="Web Links" onclick="javascript:__doPostBack('ctl00$cphMain$gvTaskRecur$ctl02$btnTaskWebLinksA','')" id="ctl00_cphMain_gvTaskRecur_ctl02_btnTaskWebLinksA" style="color:White;background-color:#0033CC;font-weight:bold;font-style:italic;" />
            </td>
        </tr>

    The click event of the button in the last column, labeled "Edit", is set to launch the EditTask() javascript function listed below which is supposed to display an alert with the contents of one of the cells:

    function editTask() {

            var rowTask = $(this).closest('tr');

            var col1 = rowTask.find("td:eq(0)").html();

             //var col1 = rowTask.find("td:eq(0)").text();

            //var col1 = rowTask.cells[0];

            //var col1 = rowTask.find("span:eq(0)").text();

             alert(col1);

             alert('editTask did not crash!');

              }

    The code above does not work, nor do a number of variations which I experimented with.  Please, can somebody show me how to access on the client side the data stored in each column of the selected row of a table?  Many thanks in advance.

    Sunday, January 17, 2021 9:40 AM

Answers

  • User1535942433 posted

    Hi Sheldon Penner,

    Accroding to your description,as far as I think,you could for loop every column.If you need,you could push them into an array.

    Just like this:

    <script>
            $(function () {
                $("input[id*=btnEditTask]").click(function () {
                    var list = [];
                    var trs = $(this).closest('tr').find('td');
                    $.each(trs, function () {
                        var x = $.trim($(this).text());
                        //alert(x);
                        list.push(x);
                    })
                    alert(list);
                })
            })
        </script>

    Best regards,

    Yijing Sun

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, January 19, 2021 8:05 AM
  • User1120190316 posted

    Eureka!  I found the answer.

    The problem described in my previous message occurred because the "this" function does not behave as expected inside a function called in "OnClientClick" inside the definition of a gridview row.  In the present case, it was not returning the button control that was used to launch it.

    The solution turned out to be to put the "this" function call inside OnClientClick() like this:

    OnClientClick="editTask(this.id);return false;"

    Then I added a buttonID argument to the editTask function and replaced references to the "this" function with references to buttonID:

            function editTask(buttonID) {
                var rw = $('#' + buttonID).closest('tr');
                var cols = rw.find('td');    // each columns of one row
                var list = [];
                $.each(cols, function () {
                    var x = $.trim($(this).text());
                    list.push(x);
                })
                alert(list);
            }

    Notice that the "this" function inside the .each loop runs just fine.  But it does not work when trying to reference the button clicked to launch the function.

    I hope this is helpful to someone out there.  

    Thanks once again, Yij Sun, for all your help and attention.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, January 21, 2021 3:50 AM

All replies

  • User1535942433 posted

    Hi Sheldon Penner,

    Accroding to your description,I suggest you could use jquery. You need to use script file.I have created a test.Just like this:

    <script src="Scripts/jquery-3.4.1.min.js"></script>
        <script>
            $(function () {
                $("input[id*=btnEditTask]").click(function () {
                    var tr = $(this).closest('tr').find('td:eq(0)').text();  //the first column of the row
                    var trs = $(this).closest('tr').find('td');    // each columns of one row
                    $.each(trs, function () {
                        console.log($(this).text());
                    })
                })
            })
        </script>
    <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false">
                    <Columns>
                        <asp:TemplateField HeaderText="Task Name">
                            <ItemTemplate>
                                <asp:Label ID="lblRecurTaskName" runat="server" Text='<%# Bind("Task_Name") %>'></asp:Label>
                            </ItemTemplate>
                        </asp:TemplateField>
                        <asp:TemplateField HeaderText="Goal">
                            <ItemTemplate>
                                <asp:Label ID="lblGoalName" runat="server" Text='<%# Bind("Goal") %>'></asp:Label>
                            </ItemTemplate>
                        </asp:TemplateField>
                        <asp:TemplateField HeaderText="High Priority">
                            <ItemTemplate>
                                <input id="chkHighPriority" type="checkbox" />
                                <%--                        <asp:Label ID="L1" runat="server" Text='<%# Bind("High_Priority") %>'></asp:Label>--%>
                            </ItemTemplate>
                        </asp:TemplateField>
                        <asp:TemplateField HeaderText="Start Date">
                            <ItemTemplate>
                                <asp:Label ID="lblEditTaskStartDate" runat="server" Text='<%# Bind("Start_Date") %>'></asp:Label>
                            </ItemTemplate>
                        </asp:TemplateField>
                        <asp:TemplateField HeaderText="End Date">
                            <ItemTemplate>
                                <asp:Label ID="lblEditTaskEndDate" runat="server" Text='<%# Bind("End_Date") %>'></asp:Label>
                            </ItemTemplate>
                        </asp:TemplateField>
                        <asp:TemplateField>
                            <ItemTemplate>
                                <input id="btnEditTask" type="button" value="Edit" />
                            </ItemTemplate>
                        </asp:TemplateField>
                    </Columns>
                </asp:GridView>

    Best regards,

    Yijing Sun

    Monday, January 18, 2021 6:08 AM
  • User1120190316 posted

    Thank you for your response, Yij Sun.  Your code works!

    I have  one more question:  What I actually need to do is copy the contents of those table cells into variables, then paste them elsewhere on the page.  I experimented with ".find("td:eq(n)").text();" but that returns "Object object".  How can I capture the contents of each individual cell?

    Tuesday, January 19, 2021 6:44 AM
  • User1535942433 posted

    Hi Sheldon Penner,

    Accroding to your description,as far as I think,you could for loop every column.If you need,you could push them into an array.

    Just like this:

    <script>
            $(function () {
                $("input[id*=btnEditTask]").click(function () {
                    var list = [];
                    var trs = $(this).closest('tr').find('td');
                    $.each(trs, function () {
                        var x = $.trim($(this).text());
                        //alert(x);
                        list.push(x);
                    })
                    alert(list);
                })
            })
        </script>

    Best regards,

    Yijing Sun

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, January 19, 2021 8:05 AM
  • User1120190316 posted

    Hello again, Yij Sun, and thanks again for your response.

    Again, it works, and thank you for that.  One small issue remains:  I am unable to prevent the page from reposting when I click btnEditTask.  In the asp.net code, I set UseSubmitBehavior=false, and I added Return false to the end of the function code, but the page reposts as soon as I dismiss the alert displaying the array List.  Advice on how I can avoid that?

    Tuesday, January 19, 2021 10:45 AM
  • User1535942433 posted

    Hi Sheldon Penner,

    As far as I think,if you set UseSubmitBehavior=false,it will adds a javascript call to __doPostBack().If you need to prevent postback,the 'cleanest' hack i discovered is to just add a return false statement after your javascript function call. 

    Just like this:

    OnClientClick="myJsFunction();return false;"

    Sum up,I think,you needn't to use UseSubmitBehavior=false.

    Best regards,

    Yijing Sun

    Wednesday, January 20, 2021 7:24 AM
  • User1120190316 posted

    Hello Yij Sun

    I moved the code into function editTask() and revised the tag for btnEditTask as you suggested.  Much to my surprise, the function no longer works.  Apparently, the problem is that "this" is interpreted differently in a function assigned from the gridview.  $(this).closest('tr') returns nothing, and so the .each loop never runs and the List array remains empty.

    Here is the current btnEditTask inside a gridview template

                            <asp:TemplateField ShowHeader="False">
                                <ItemTemplate>
                                    <asp:Button ID="btnEditTask" runat="server" CausesValidation="False" 
                                        Text="Edit" OnClientClick="editTask();return false;"/>&nbsp;

    and here is the editTask() function.  I left in a few alerts that make the problem clear.

            function editTask() {
                alert($(this).ID);
                var tr = $(this).closest('tr');
                var cols = $(this).closest('tr').find('td');    // each columns of one row
                alert(cols.length);
                var list = [];
                $.each(cols, function () {
                    var x = $.trim($(this).text());
                    alert(x);
                    list.push(x);
                    //alert($(this).text());
                })
                alert(list);
            }

    I expected the first alert to display the ClientID of the instance of btnEditTask that was clicked; instead it says "undefined".  The second alert contains the length of cols, which is 0.  Since there are no items in cols, the alert inside the .each loop never runs.  And the final alert, the list, is blank.

    So, perhaps there is some alternate method for getting a reference to the row containing the button clicked?

    Wednesday, January 20, 2021 10:02 AM
  • User1120190316 posted

    Eureka!  I found the answer.

    The problem described in my previous message occurred because the "this" function does not behave as expected inside a function called in "OnClientClick" inside the definition of a gridview row.  In the present case, it was not returning the button control that was used to launch it.

    The solution turned out to be to put the "this" function call inside OnClientClick() like this:

    OnClientClick="editTask(this.id);return false;"

    Then I added a buttonID argument to the editTask function and replaced references to the "this" function with references to buttonID:

            function editTask(buttonID) {
                var rw = $('#' + buttonID).closest('tr');
                var cols = rw.find('td');    // each columns of one row
                var list = [];
                $.each(cols, function () {
                    var x = $.trim($(this).text());
                    list.push(x);
                })
                alert(list);
            }

    Notice that the "this" function inside the .each loop runs just fine.  But it does not work when trying to reference the button clicked to launch the function.

    I hope this is helpful to someone out there.  

    Thanks once again, Yij Sun, for all your help and attention.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, January 21, 2021 3:50 AM