madster madster - 4 months ago 78
jQuery Question

Nested Gridview should expand/collapse when row is clicked

I have a nested GridView as follows:

<asp:GridView ID="gvParent" runat="server" DataKeyNames="id">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:GridView ID="gvChild" runat="server">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:Label ID="lblChild1" runat="server"/>
</ItemTemplate>
</asp:TemplateField>
//... some more child columns
</Columns>
</asp:GridView>
</ItemTemplate>
</asp:TemplateField>

<asp:TemplateField>
<ItemTemplate>
<asp:Label ID="lblParent1" runat="server"/>
</ItemTemplate>
</asp:TemplateField>
//... some more parent columns
<asp:TemplateField>
<ItemTemplate>
<asp:HiddenField ID="IsExpanded" ClientIDMode="Static" runat="server" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>


What I want to do is when the user clicks anywhere on the parent row, the child row expands, showing all rows in the child GridView that relate to the parent then when I click again, it should collapse.

I can get the data into the GridViews fine and can get the expand/collapse working as in this tutorial but I don't want to have just the image clickable, I want the whole row clickable.

To at least try and get it to expand I used the same logic from the tutorial:

$(function () {
$("[id*=gvParent] td").click(function () {
$(this).closest("tr").after("<tr><td></td><td colspan = '999'>" + $(this).next().html() + "</td></tr>");
});
});


But it just copies the contents of the column to the right of the clicked column within that row to the next row (see snip). I'm sure it's probably simple but I just can't find the answer anywhere!

UPDATE:

I now have:

$("[id*=gvFileUploadAdmin] td").click(function () {
if ($("#IsExpanded").val() == "expanded") {
debugger;
collapseRow(this);
}
else if (typeof $("#IsExpanded").val() == 'undefined'
|| $("#IsExpanded").val() == "collapsed") {
expandRow(this);
}
});

function expandRow(row) {
$(row)
.closest("tr")
.after("<tr><td></td><td colspan = '999'>" +
$("[id*=pnlFiles]", $(row).closest("tr")).html() +
"</td></tr>");
$("#IsExpanded").val("expanded");
};

function collapseRow(row) {
$(row).closest("tr").next().remove();
$("#IsExpanded").val("collapsed");
}


Which allows me to open and close individual rows BUT when one row is open and then another is opened, the row beside that is deleted. There is definitely something going on with the unique IDs but I'm not sure how to fix it. I do have some C# in the background doing this:

HiddenField IsExpanded = row.FindControl("IsExpanded") as HiddenField;
var uniqueId = IsExpanded.UniqueID;
IsExpanded.Value = Request.Form[uniqueId];


But when that's removed it makes no difference to how it works because Request.Form[uniqueId] returns null.

Answer

So I finally managed to get it working! Here's what I did (note that this doesn't expand the row if the user presses a button within that row):

$(function () {
    $("[id*=gvParent] td").click(function () {
        if ($(this).parents('tr').find('input[type="hidden"]').val() == "expanded")
            collapseRow(this);
        else
            expandRow(this);
     });

     // Ensure the row doesn't expand/collapse if a button is clicked
     $("[id*=gvParent] td .btn").click(function (e) {
         e.stopPropagation();
     });
     //Ensures any clicks on the child row aren't registered
     $("[id*=gvParent] td .gvChild").click(function (e) {
         e.stopPropagation();
     });
});

function expandRow(row) {
    $(row).closest("tr").after("<tr><td></td><td colspan = '999'>" +
                $("[id*=pnlFiles]", $(row).closest("tr")).html() +
                "</td></tr>");
    $(row).parents('tr').find('input[type="hidden"]').val("expanded");
};

function collapseRow(row) {
    $(row).closest("tr").next().hide();
    $(row).parents('tr').find('input[type="hidden"]').val("collapsed");
}

I also changed the ClientIDMode from static:

<asp:HiddenField ID="IsExpanded" ClientIDMode="Static" runat="server" />

to AutoID:

<asp:HiddenField ID="IsExpanded" ClientIDMode="AutoID" runat="server" />