0

Given the following situation:

I have a model that contains various properties, one of those properties is a List. The model is the following:

public class DocumentTypeViewModel : BaseViewModel<int>
{
    #region Properties

    public string Name { get; set; }

    public List<DocumentTypeProperty> Properties { get; set; } 

    #endregion Properties
}

The DocumentTypeProperty, has just a single field with a name (and off course an id, but that's not important here).

Now, the ActionResult to show the view on which the create will happen is the following:

public ActionResult Create()
{
    var model = Mapper.Map<DocumentType, DocumentTypeViewModel>(new DocumentType());
    return View(model);
}

So, as you see, I send an empty model to the view, so the collection is null. Now, on in my Razor view i want to have an add button that I can use to add an element to the collection (I know that I can use jQuery to create elements), but I don't want to post it since it's not needed, the post will occur on the save of the model.

So the question is:

How can I pass my dynamiccly created textboxes to my ActionResult?

Kind regards,

tereško
  • 58,060
  • 25
  • 98
  • 150
Complexity
  • 5,682
  • 6
  • 41
  • 84

2 Answers2

2

The Model Binding in MVC will bind to a collection

@Html.TextBoxFor(model => model[0].Name)
@Html.TextBoxFor(model => model[1].Name)

Then your controller could be

public ActionResult Create(List<DocumentTypeViewModel> )

Then you could create all rows at once when the form is submitted.

If you want to save each row to the database as it is added to the form, then you'll need to do some AJAX.

Also, there's no need to put the DateCreated and the DateUpdated in the view. If you do, then a savvy user would be able to edit them. Just have the controller add them before the save.

RyanB
  • 757
  • 4
  • 11
  • Sorry but it's not really clear to me. I know how mvc binds to a collection. But my model is initially empty. So how can I add elects to the collection dynamically. Saving all iets at once? – Complexity May 16 '14 at 18:33
  • You'll need to use JavaScript (ex., JQuery) to dynamically add the textboxes to the page. When the form is submitted the control will get them all in a collection as long as they are named properly (element[0].Name and element[1].Name). The indexes have to start at 0 and be sequential. – RyanB May 16 '14 at 18:38
  • I'm sorry but I'm affraid, your solution doesn't work. An exception is thrown when using this code in MVC:
    @Html.LabelFor(model => model.Properties[0].Name)
    It seems that LabelFor and others cannot be used on a collection. I'm a bit lost :s And in the controllerAction, I don't need to post a list, it's a model and the model itself contains a list property
    – Complexity May 16 '14 at 18:50
  • Ok, it was because I was using an IEnumerable instead of a List :) – Complexity May 16 '14 at 18:51
  • Anyway, I've tested it further and as I tought, I have an error right now because my collection is empty: @Html.TextBoxFor(model => model.Properties[0].Name) I'll adapt the question to make it more clear. – Complexity May 16 '14 at 18:53
  • Before you send the model to the View, initialize the List with an empty list. model.Properties = new List(); – RyanB May 16 '14 at 19:01
  • That doesn't work either, I just initialize an empty list so List[0] doesn't exists. The collection is still empty, so I don't see why it should work? – Complexity May 16 '14 at 19:04
  • Sorry, since you want the form to start out with a single DocumentViewModel, you should add one to the list. So, model.Properties.Add(dvm); When you add new fields with jQuery you'll need to create them manually input name=element[i].Name – RyanB May 16 '14 at 19:08
  • Sorry, but I think I'm not very clear, the form doesn't need to have properties, so I would not like to add anything to the list beforehand. You mind helping me out? – Complexity May 16 '14 at 19:10
  • If the view starts with Zero entries you won't use @Html.TextBoxFor() and thus you won't get an error for List[0] not existing. If that's the case, the jQuery will need to create the first input with [0]. – RyanB May 16 '14 at 19:13
  • I'll understand, maybe it was wrong off me but the TextBoxFor was just there for showing what I would like to do. You could give me a small example on how to create the correct input box with jQuery, then my problem is finally solved. I'll keep trying things myself, maybe you can post your thing as an anwser, that way I can give you some reputation :) – Complexity May 16 '14 at 19:15
  • Ok, I've managed to create the objects so no problem anymore. It's resolved. Just an additional question maybe, any idea on how I could set the data-val-maxlength-max and other validation properties based on the data annotations on my model? – Complexity May 16 '14 at 19:21
  • Here's a pretty good example. Just make sure to get the naming right. http://www.mkyong.com/jquery/how-to-add-remove-textbox-dynamically-with-jquery/ If the variable in your Controller is called elements the name should be elements[i].Name – RyanB May 16 '14 at 19:22
  • I know, I have it already (see comment above). Thanks for all the valuable help. Do you just have another idea about the validation properties (data annotations)? – Complexity May 16 '14 at 19:23
  • You're welcome. Here's an explanation of validating a dynamic form. http://stackoverflow.com/questions/5272663/asp-net-mvc-3-client-side-validation-with-a-dynamic-form – RyanB May 16 '14 at 19:30
  • I don't get it, there are extra properties on the textbox that has the text displayed on the data annotations, but I will have a look further down on it. – Complexity May 16 '14 at 19:31
1

If you want to show a IEnumerable/list on your view, you can just usea forech loop.either you can send the list from your controller via viewbag or modelbinding.Something like that

In Controller

   public ActionResult Create()
   {
    var model = Mapper.Map<DocumentType, DocumentTypeViewModel>(new DocumentType());
    Viewbag.List=Userlist// bind your list here
    return View(model);
   }

In view

Just use a table and a forech loop to represent your list data

     @foreach (var item in @Viewbag.List) 
    {
    //Define your table structure
    } 

And i am not clear what u r saying about your second step for adding data.let me clear first. Thanks

Badhon Ashfaq
  • 851
  • 6
  • 9