I\'ve done this in the past, and i may have to do it again, but before i do, i want to throw it out there to see how people handle it.
Razor view:
&l
I've had to deal with exactly that same situation as well. The easiest solution I came up with, was using a wrapper model, similar to:
public class QuestionListModel
{
public IList Questions { get; set; }
public IList Template
{
get
{
return new List
{
new QuestionModel {/* defaults for new question */}
};
}
}
public QuestionListModel()
{
Questions = new List();
}
}
The important part, is having the Template property, which is also a an IEnumerable
of the same type as the actual model you want. That way, the auto-numbering will be done for you by MVC. So using this model, what you get is, your collection, with "Questions_0__Title" numbering, and you also get one template row with "Template_0__Title" naming.
I keep my template row hidden from the UI and use it when adding a new row.
In razor, you'd bind the template just as you'd bind a regular question, the only difference is it would be in a hidden When adding a row, the trick is, using javascript: Get the count from the hidden field, increment it. Take the entire template block, clone it (using jquery's For each item, such as inputs in your new appended block (you can find it with the new id you assigned to it), you replace ids => "Template_0" with "Questions__count from step 2", and names => "Template[0]" with "Questions[count from step 2]". Update the hidden field for the counter=> Now, regarding deletions, the way I do it, is, my ViewModel for it actually has an This way I avoid having to deal with individual ways of identifying deleted items, and also renumbering all the items in the UI. Plus, you get the advantage of having server-side code determine what should actually happen when deleting (such as validating or undoing the action). It is a long post, but the implementation is not really that difficult (or long), and can easily be reused in a generic way. Cheers!Count
of your Questions list to a hidden field as well. In my case, I have an editor template for a Question, which renders it inside
var counter = $("#QuestionsListCount");
var count = parseInt(counter.val());
count++;
.clone(true)
for example), name it as something unique (using the counter value from step 1 for example), and append it to the section where your questions are. var template = $("#templateContainer");
var newItem = template.clone(true);
var newId = "item_" + count;
var newQuestion = newItem.children().first();
newQuestion.attr("id", newId);
newQuestion.appendTo('#items');
$("#" + newId + " :input").each(function (index, input) {
input.id = input.id.replace("Template_0", "Questions_" + (count - 1));
input.name = input.name.replace("Template[0]", "Questions[" + (count - 1) + "]");
});
counter.val(count);
IsDeleted
flag, which i bind to a hidden field within the Question editor template as well.
That way, deletions are as simple as hiding the particular Question (the question selector comes handy) and you set that IsDeleted
field to true.
When you get your entire list back through the default model binder, you need to discard all deleted ones (or issue actual deletes, depending on your back-end data model).