tags:

views:

362

answers:

5

I have a form which allows the user to create extra "rows" using JQuery (using .clone) so that they can decide how many of the same information they need to submit. My issue is that I cannot work out how to access these form items within my controller.

the form that is being submitted may look like this

<input type="text" name="Amount" id="Amount"><select name="Item">
                                             <option value="1">Item 1"</option>
                                             <option value="2">Item 2"</option>
                                             <option value="3">Item 3"</option></select>
<input type="text" name="Amount" id="Amount"><select name="Item">
                                             <option value="1">Item 1"</option>
                                             <option value="2">Item 2"</option>
                                             <option value="3">Item 3"</option></select>
<input type="text" name="Amount" id="Amount"><select name="Item">
                                             <option value="1">Item 1"</option>
                                             <option value="2">Item 2"</option>
                                             <option value="3">Item 3"</option></select>

Basically, the block between input and the select could be repeated an infinite number of times. When I submit to the controller I am then using FormCollection form to access the form elements. from there I am unsure how I can access the items that have been submitted. I thought of using a for loop and then accessing them via something like form["Amount"][i] but obviously that is not going to work.

Am I going about this the right way and if so, does anyone have any suggestions about how this might work?

Thanks in advance.

+1  A: 

I believe if you have multiple fields named Amount the values will be comma delimited.

To access each one just try:

string[] amounts = Request.Form["Amount"].Split(new char[] { ',' });

Keep in mind though, the inputs are not cleaned on submission so if someone enters a comma into the text box it's going to cause issues.

Hence I'd recommend numbering them.

Spencer Ruport
That is correct, it just the accessing them that I am having difficulty with.
dave
Ah yeah you can use the split method.
Spencer Ruport
Ok, so maybe I am looking at the wrong area and I need to find out how to changed cloned form attributes that include [] characters!
dave
Well once they're in the amounts array you can iterate through them using a for loop like so: for(int i=0; i<amounts.length; i++) Response.Write(amounts[i]);
Spencer Ruport
The only real issue is the someone adding a comma into the form field which I can take care of with validation. Do you think that doing it the way that I am currently is viable or would you recommend trying to get it working so that I number the form items?
dave
javascript validation should be fine. Honestly with HTTP forms anyone can screw up submissions if they really want to. Just protect your code accordingly and make sure that you don't accidentally access an array index that doesn't exist.
Spencer Ruport
Thanks Spencer, will report when I have finished trying to make this work!
dave
A: 

I would number them Amount1, Amount2, Amount3 etc.

Adam Pierce
The problem is that JQuery does not seem to like renaming a cloned form attribute when includes [] characters. The existing form element is cloned but the attributes id and name are not changed. Otherwise I would use this http://haacked.com/archive/0001/01/01/model-binding-to-a-list.aspx technique.
dave
A: 

You can change the id and name attribute of the input to something like this "Amount[1]","Amount[2]","Amount[3]" (yes, the id and name attribute can contain the special chars "[" or "]"). Then in the controller, write a http request parameter parser to get back the Amounts as collections.

jscoot
Thanks jscoot, same as the comment left for Adam's answer.
dave
+1  A: 

Check out Model Binding To A List. Your Action method should be:

public ActionResult MyAction(string[] Amount, int[] Item)
{
   // ...
}

However this will make you need to "link" the items. Alternatively create a "Item" class:

public class Item 
{
    public string Amount { get; set; }
    public int Item { get; set; }
}

And

public ActionResult MyAction(IList<Item> items)
{
   // ...
}

And your markup should be:

<input type="hidden" name="items.Index" value="0" />
<input type="text" name="items[0].Amount" id="items[0].Amount"><select name="items[0].Item">
                                             <option value="1">Item 1"</option>
                                             <option value="2">Item 2"</option>
                                             <option value="3">Item 3"</option></select>


<input type="hidden" name="items.Index" value="1" />
<input type="text" name="items[1].Amount" id="items[1].Amount"><select name="items[1].Item">
                                             <option value="1">Item 1"</option>
                                             <option value="2">Item 2"</option>
                                             <option value="3">Item 3"</option></select>

Etc...

veggerby
Thanks for the response, I did actually make a comment about doing this in Spencer's answer. It came down to JQuery not liking [] in the attribute id and name fields so when I went to change them, JQuery would not do this. Perhaps I should post about JQuery as it is a nicer way to do this.
dave
A: 

I ended up realising that (blush) the mechanism which JQuery uses to find the string within the cloned row (to replace) is basically regex. Thus I just needed to escape the square brackets and period. Once I did this I was able use JQuery to create form as Phil Haack's blog suggested.

Onto my next issue...!

dave