I have a bootstrap modal that displays a list of titles with a delete button for each title. I created a little sketch to make it clear what I am talking about.
The table is created with a Repeater:
<asp:Repeater ID="rpRelated" runat="server" OnItemDataBound="rpRelated_ItemDataBound">
<HeaderTemplate>
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th style="width: 20%">Title</th>
<th style="width: 10%">Delete</i></th>
</tr>
</thead>
</HeaderTemplate>
<ItemTemplate>
<tr runat="server" id="related">
<td>
<asp:HiddenField runat="server" ID="titleRelatedID" Value='<%# DataBinder.Eval(Container.DataItem , "ID")%>' />
<asp:TextBox runat="server" ID="relatedTitle" Text='<%# DataBinder.Eval(Container.DataItem , "Title")%>' CssClass="form-control" />
</td>
<td>
<a class="my-red-button" href='javascript:hideRelated(<%# DataBinder.Eval(Container.DataItem , "ID")%>);'>Delete</i></a>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
I set the related <tr>
ID in the Repeater's ItemDataBound
method in order to make it dynamic so that I can tell which row to hide (Source of the Idea):
protected void rpRelated_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
Title title = (Title)e.Item.DataItem;
var row = e.Item.FindControl("related");
row.ClientIDMode = ClientIDMode.Static;
row.ID = "related" + title.ID;
}
}
When one of the delete buttons (links) is pressed, the following JS function is called:
function hideRelated(num) {
document.getElementById('related' + num).style.display = 'none';
}
This function hides the row temporarily, yet doesn't actually delete the title.
I don't want any of the titles to actually get deleted until the SAVE button on the bottom is pressed. When the SAVE button is clicked, the following Click Event is called in the CodeBehind, and this is where I am getting stuck:
protected void btnSaveRelated_Click(object sender, EventArgs e)
{
foreach (RepeaterItem item in rpRelated.Items)
{
int ID = Convert.ToInt32(((HiddenField)item.FindControl("titleRelatedID")).Value);
var a = item.FindControl("related" + ID); //returns null
if (???title row is hidden???)
{
//code to actually delete the Title goes here
}
}
}
As I iterate through the Repeater Items, how can I figure out if the corresponding <tr>
has the display:none
attribute?
I tried accessing the item's row by doing item.FindControl("related" + ID);
, yet this doesn't seem to work since it is always returning null (possibly because the ClientIDMode is Static). I though of using a HiddenField
like I did with titleRelatedID
, yet I couldn't figure out how to update the correct value in the JavaScript code when one of the buttons is clicked. I also though of possibly using Visible=false
instead of display:none
yet I couldn't either figure out how to work this method in JavaScript.
I would love to get my current method to work, yet I am open to completely different approaches to accomplish my task which is:
One approach is to use another HiddenField control that tracks the IDs of deleted titles:
<!-- before/after (not inside) the Repeater -->
<asp:HiddenField runat="server" ID="deletedRelatedIDs" />
In the hideRelated
JavaScript function, append the argument to the hidden field:
document.getElementById('deletedRelatedIDs').value += num + ' ';
In the btnSaveRelated_Click
method, read the value of the hidden field:
foreach (string id in this.deletedRelatedIDs.Value.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries))
{
// Delete the title with this ID.
}
Security Note: The user can easily tamper with the contents of the hidden field. If necessary, the btnSaveRelated_Click
method should validate that each ID is valid and that the user has permission to delete the title.
As I iterate through the Repeater Items, how can I figure out if the corresponding
<tr>
has thedisplay:none
attribute?
You can't. When the browser submits the form to the server, the server doesn't receive the values of CSS attributes.
Why does
item.FindControl("related" + ID)
always return null?
Unlike most ASP.NET server control properties, the ID property is not backed by view state, so changes to the ID property aren't preserved across postbacks. Instead, the ID reverts to the value specified in the markup ("related"
).