So I asked a question last year about having an “add item” button that’ll generate a new row in a form in JavaScript that I can return to an MVC POST action handler.
For instance, if I have a form generated like this:
@for(int i = Model.Notes.Count - 1; i >= 0; i--)
{
<tr>
<td>@Html.HiddenFor(m => m.Notes[i].Id, new Dictionary<string, object> { { "data-index", i } } )
@Html.TextBoxFor(m => m.Notes[i].Timestamp, new { @class = "datepicker" })</td>
<td>@Html.DropDownListFor(m => m.Notes[i].PersonId, new SelectList(Model.People, "Id", "Name"))</td>
<td>@Html.EditorFor(m => m.Notes[i].Amount)</td>
<td>@Html.EditorFor(m => m.Notes[i].Comment)</td>
</tr>
}
The HTML it generates for a single row:
<tr>
<td><input data-index="2" data-val="true" data-val-number="The field Id must be a number." data-val-required="The Id field is required." id="Notes_2__Id" name="Notes[2].Id" type="hidden" value="16192">
<input class="datepicker hasDatepicker valid" data-val="true" data-val-required="The Timestamp field is required." id="Notes_2__Timestamp" name="Notes[2].Timestamp" type="text" value="11/04/2011 2:11:21 PM"></td>
<td><select id="Notes_2__PersonId" name="Notes[2].PersonId">
<option value="8367">Rei</option>
<option value="8668">Ray</option>
<option value="8883">Roy</option>
<option value="8814">Rob</option>
<option value="8886">Ron</option>
</select></td>
<td><input class="text-box single-line" data-val="true" data-val-number="The field Amount must be a number." data-val-required="The Amount field is required." id="Notes_2__Amount" name="Notes[2].Amount" type="text" value="0.00"></td>
<td><input class="text-box single-line" id="Notes_2__Comment" name="Notes[2].Comment" type="text" value="Some comment"></td>
</tr>
If I want to add an item in MVC2, I had to write some really dry JavaScript code to determine the index of the latest item, generate all the trs, tds, and input HTML and set the attributes to match.
Not only is this really non-trivial, if I ever change something in the cshtml, I have to be very careful to make sure all the JavaScript matches. It’s a really nasty duplication of code.
Is there any better way to do it in MVC3?
Thanks in advance,
Rei
Here’s a blog post illustrating that the situation could be better even in MVC 2 🙂 And the situation could be even further improved by using editor templates (which also exist in MVC 2) and never write a single
forloop in a view.