I’ve got an MVC3 Read Only view that contains a table displaying properties for an Item.
For many of the properties of the Item, we track the changes a Vendor has made to the item. So, for example, a vendor may update a property named ‘Color’ from a value of ‘Blue’ to ‘Red’. In this View a table lists each property tracked in a table row, with a column showing the ‘Old Value’ and the ‘New Value’. The next column either shows the current change’s status (Awaiting Approval, Approved, or Rejected). However, for Admin users, the column will contain Links (‘Approve’, ‘Reject’, or ‘Reset to Awaiting Approval’).
My markup and Razor code for this is very repetitive and getting out of hand. I’d like to create an HTMLHelper for this, or possibly a partial view that I can use to move all the code into and then use it for each Item Property.
Here is an example of the code used for one Property. This code is repeated for another 10 or so properties.
I’m using some jquery and ajax for the actions. For example, when an change is rejected, the user must enter a reason for rejecting the change.
<tr id="rowId-color">
<td>@Html.LabelFor(model => model.Color)</td>
<td>@Html.DisplayFor(model => model.Color)</td>
@if (Model.ChangeLog != null && Model.ChangeLog.Item("Color") != null) {
var change = Model.ChangeLog.Item("Color");
var changeStatus = (ItemEnumerations.ItemChangeStatuses)change.ItemChangeStatusID;
<td>@change.OldValueDisplay</td>
<td id="tdstatusId-@change.ItemChangeID">
@if (changeStatus == ItemEnumerations.ItemChangeStatuses.AwaitingApproval && User.IsInRole("TVAPMgr")) {
@Ajax.ActionLink("Approve", "Approve", new { itemChangeID = change.ItemChangeID }, new AjaxOptions { HttpMethod = "POST", Confirm = "Approve this change?", OnSuccess = "actionCompleted" })
@Html.Raw("|")
<a href="#dialog" name="reject" data-id="@change.ItemChangeID" >Reject</a>
}
else if ((changeStatus == ItemEnumerations.ItemChangeStatuses.Rejected || changeStatus == ItemEnumerations.ItemChangeStatuses.Approved) && User.IsInRole("TVAPMgr")) {
@Ajax.ActionLink("Reset to Awaiting Approval", "Reset", new { itemChangeID = change.ItemChangeID }, new AjaxOptions { HttpMethod = "POST", Confirm = "Reset this change to Awaiting Approval?", OnSuccess = "actionCompleted" })
}
else {
@changeStatus.ToDisplayString()
}
</td>
<td id="tdreasonId-@change.ItemChangeID">@Html.DisplayFor(m => m.ChangeLog.Item(change.ItemChangeID).RejectedReason)</td>
}
else {
<td colspan="3">No Change</td>
}
</tr>
You haven’t shown nor explained how your domain and view models look like but I suspect that what you are using here is not an appropriate view model for this specific requirement of the view. A better view model would have been one that has a list of properties to approve which would be shown in the table.
Anyway, one possible approach is to write a custom HTML helper so that your view looks like this:
and the helper might be something along the line of:
A better approach would be to re-adapt your view model to the requirements of this view and simply use display templates.