Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

asp:repeater collapsing table rows - Updated

I'm wondering if someone has a creative solution to my problem. I have a repeater that is populated from my database and it is as follows:

<asp:Repeater ID="ResultsTableRepeater" runat="server" OnPreRender="ResultsTableRepeater_PreRender">

        <HeaderTemplate>
            <table class="td-table-bordered" style="font-size: small; width: 90%">
                <tr>
                    <th>Change #</th>
                    <th>Change Title</th>
                    <th>Change Description</th>
                    <th>Clarity Id</th>
                    <th>Package Description</th>
                    <th>Package Name</th>
                    <th>Package Status</th>
                    <th>Assigned To</th>
                    <th>New Package</th>
                </tr>
        </HeaderTemplate>
        <ItemTemplate>
            <asp:Literal runat="server" Text='<%# Eval("ChangeId") %>' ID="IdTag" Visible="false"></asp:Label>
            <tr id="tableRow" class="" data-changeId='<%# Eval("ChangeId") %>' runat="server" style='<%#(Eval("AssignedTo").ToString() == "7" || Eval("AssignedTo").ToString() == "8")? "": "font-weight:bold; background-color:cornsilk" %>'>
                <td><%# Eval("ChangeId") %></td>
                <td><%# Eval("ChangeTitle") %></td>
                <td><%# Eval("ChangeDescription") %></td>
                <td><%# Eval("ClarityId") %></td>
                <td><%# (Eval("PackageId").ToString() == string.Empty) ?  "" 
                    : "<a href=http://dev.rlaninfrastructure.tdbank.ca/RCIViewForm?ChangeId=" + Eval("ChangeId") + "&PackageId=" + Eval("PackageId") + " runat='server' id='RCILink'>" %>
                    <asp:Label ID="ExistingPackageLabel" runat="server" Text='<%# (Eval("PackageId").ToString() == string.Empty) ? "No packages" : Eval("PackageDescription").ToString() %>'>
                    </asp:Label><%# (Eval("PackageId").ToString() == string.Empty) ? "" : "</a>" %>
                </td>
                <td><%# Eval("PackageName") %></td>
                <td>
                    <asp:Label ID="LabRequestedLabel" runat="server" Text='<%# (Eval("PackageStatus").ToString() == "1") ? "Requested" 
                                                                             : (Eval("PackageStatus").ToString() == "2") ? "Built" 
                                                                             : (Eval("PackageStatus").ToString() == "3") ? "NFT"
                                                                             : (Eval("PackageStatus").ToString() == "4") ? "Pilot"
                                                                             : (Eval("PackageStatus").ToString() == "5") ? "Production" 
                                                                             : (Eval("PackageStatus").ToString() == "6") ? "Completed" 
                                                                             : (Eval("PackageStatus").ToString() == "7") ? "Cancelled"
                                                                             : (Eval("PackageStatus").ToString() == "8") ? "Pending" 
                                                                             : "" %>'></asp:Label>
                </td>
                <td><%# (Eval("EmployeeName").ToString() == string.Empty) ? "" : Eval("EmployeeName")%></td>
                <td><%# "<a href=http://dev.rlaninfrastructure.tdbank.ca/RCIViewForm?ChangeId=" + Eval("ChangeId") + " runat='server' id='RCILink'>"%>
                    <asp:Label ID="NewPackageLabel" runat="server" Text="Create New">
                    </asp:Label><%#"</a>" %></td>
            </tr>
        </ItemTemplate>
        <FooterTemplate>
            </table>
        </FooterTemplate>
    </asp:Repeater>

and it produces a table that looks like this

enter image description here

What I've circled are rows with repeating Change Id's that I'd like to default to collapsed but can be clicked to be expanded (as well as clicked again to be collapsed again).

I've begun to implement Jon P's solution below, and I'm almost done! Just the Jquery onclick event.

Below is my codebehind PreRender method.

protected void ResultsTableRepeater_PreRender(object sender, EventArgs e) {
        int previousId = 0;
        int currentId = 0;
        int nextId = 0;

        for (int item = 0; item < ResultsTableRepeater.Items.Count; item++) {
            Literal idTag = (Literal)ResultsTableRepeater.Items[item].FindControl("IdTag");
            Literal classTag = (Literal)ResultsTableRepeater.Items[item].FindControl("ClassTag");
            HtmlTableRow tableRow = (HtmlTableRow)ResultsTableRepeater.Items[item].FindControl("tableRow");
            if (item != ResultsTableRepeater.Items.Count - 1)
                int.TryParse(((Literal)ResultsTableRepeater.Items[item + 1].FindControl("IdTag")).Text.ToString(), out nextId);

            if (int.TryParse(idTag.Text, out currentId)) {
                if (currentId == previousId) {
                    tableRow.Attributes["class"] = "hidden";             
                }
                else if (currentId != previousId && currentId == nextId) {
                    tableRow.Attributes["class"] = "toggler";
                }
            }
            else
                nextId = 0;

            int.TryParse(idTag.Text, out previousId);
        }
    }

Update again: The only thing I have left to fix is the jquery, which expands and collapses the hidden/opened rows on the toggler lines. Below is the jquery and css as per Jon P's help.

$(".toggler").click(function(){
  var idClicked = $(this).data("changeid");

  //Toggle hidden on the sibling rows with the same data id
  $(this).nextAll("[data-changeId='" + idClicked +"']").toggleClass("hidden");

  //Toggle opened status on clicked row
  $(this).toggleClass("opened");
});


.hidden{display:none;}
.toggler td:first-child::after{content:" +";}
.toggler.opened td:first-child::after{content:" -";}

Can someone help me out in this final stretch? I feel like I'm close.

like image 268
David Avatar asked Oct 30 '22 06:10

David


1 Answers

Don't have time for a complete answer as there is a fair bit involved server side so I'll try and give you a broad picture.

You need to look at adding a class to your table row, maybe add asp:literal to your tr to hold the class. Also add an asp:literal for your id, this will give you a control you can get the value from. Perhaps use that literal for a data attribute on the table row.

Then use an OnPreRender event on your Repeater. Here iterate the items of the repeater. Compare the id you have stored in the literal I mentioned above with the id in the previous and next items. If the id is the same as the previous, add a css class you can use to hide it. If the id is differnt to the previous but the same as the next, add a css class to indicate that the row is used to hide and collapse.

Add some CSS to to hide the rows using the class added above.

You want to end up with HTML that resembles the following. I've also added the expand and collapse with jquery

$(document).ready(function() {
  $(".toggler").click(function() {
    var idClicked = $(this).data("changeid");

    //Toggle hidden on the sibling rows with the same data id
    $(this).nextAll("[data-changeId='" + idClicked + "']").toggleClass("hidden");

    //Toggle opened status on clicked row
    $(this).toggleClass("opened");
  });
});
.hidden {
  display: none;
}

.toggler td:first-child::after {
  content: " +";
}

.toggler.opened td:first-child::after {
  content: " -";
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table class="td-table-bordered" style="font-size: small; width:90%">
  <tr>
    <th>Change #</th>
    <th>Change Title</th>
    <th>Change Description</th>
    <th>Clarity Id</th>
    <th>Package Description</th>
    <th>Package Name</th>
    <th>Package Status</th>
    <th>Assigned To</th>
    <th>New Package</th>
  </tr>
  <tr data-changeId="1">
    <td>1</td>
    <td>Change Title</td>
    <td>Change Description</td>
    <td>Clarity Id</td>
    <td>Package Description</td>
    <td>Package Name</td>
    <td>Package Status</td>
    <td>Assigned To</td>
    <td>New Package</td>
  </tr>
  <tr class="toggler" data-changeId="2">
    <td>2</td>
    <td>Change Title</td>
    <td>Change Description</td>
    <td>Clarity Id</td>
    <td>Package Description</td>
    <td>Package Name</td>
    <td>Package Status</td>
    <td>Assigned To</td>
    <td>New Package</td>
  </tr>
  <tr class="hidden" data-changeId="2">
    <td>2</td>
    <td>Change Title</td>
    <td>Change Description</td>
    <td>Clarity Id</td>
    <td>Package Description</td>
    <td>Package Name</td>
    <td>Package Status</td>
    <td>Assigned To</td>
    <td>New Package</td>
  </tr>
  <tr class="hidden" data-changeId="2">
    <td>2</td>
    <td>Change Title</td>
    <td>Change Description</td>
    <td>Clarity Id</td>
    <td>Package Description</td>
    <td>Package Name</td>
    <td>Package Status</td>
    <td>Assigned To</td>
    <td>New Package</td>
  </tr>
  <tr data-changeId="3">
    <td>3</td>
    <td>Change Title</td>
    <td>Change Description</td>
    <td>Clarity Id</td>
    <td>Package Description</td>
    <td>Package Name</td>
    <td>Package Status</td>
    <td>Assigned To</td>
    <td>New Package</td>
  </tr>
  <tr class="toggler" data-changeId="4">
    <td>4</td>
    <td>Change Title</td>
    <td>Change Description</td>
    <td>Clarity Id</td>
    <td>Package Description</td>
    <td>Package Name</td>
    <td>Package Status</td>
    <td>Assigned To</td>
    <td>New Package</td>
  </tr>
  <tr class="hidden" data-changeId="4">
    <td>4</td>
    <td>Change Title</td>
    <td>Change Description</td>
    <td>Clarity Id</td>
    <td>Package Description</td>
    <td>Package Name</td>
    <td>Package Status</td>
    <td>Assigned To</td>
    <td>New Package</td>
  </tr>
</table>

NOTE this could all be done client side, but you would have a brief moment when the table is fully expanded while javascript works out what to hide. That can be a jarring experience for your users.

like image 78
Jon P Avatar answered Nov 11 '22 14:11

Jon P