Reputation: 1002
I have a table where the user can add a entry and once the user is done they they can add another.
After they added a entry they can remove it again. This is where the problem happens. Here is an example
ACTION:
Public ActionResult Submit(List<String> Names)
{
//DO STUFF
}
When they add a entry it will grab the index of the previous entry and add a hidden field for it, so at the end it will look something like this:
HTML:
<input type="hidden" name='Names[0]' value='John'/>
<input type='hidden' name='Names[1]' value='Peter' />
<input type='hidden' name='Names[2] value='David' />
When I submit this it will map all the names correcty. The problem is that the user can remove one of the names after they added it before the submit. If they remove the input with the value 'Peter' the html will look like this
HTML AFTER REMOVE:
<input type="hidden" name='Names[0]' value='John'/>
<input type='hidden' name='Names[2] value='David' />
When this gets submitted, only the input with the value 'John', will get mapped.
Does anyone know how to fix this without coding a jquery function that will redo all the indexes in the html? I'm looking for a solution that I can add server side for the bindings, a override or something. The reason I don't want to do it with jquery is because I have multiple pages that has such functionality, and doing it for each page will be quite time time consuming.
*****EDIT*******
The code above are just an example, one of my models that I try to bind look like the following:
public class Product {
public string Code {get;set;}
public string Name {get;set;}
public int Quantity {get;set;}
public decimal Price {get;set;}
}
And then obviously in my Action
public ActionResult Submit(List<namespace.Product> Products)
{
//do stuff
}
Upvotes: 1
Views: 2142
Reputation: 1002
Thanks to Zabavsky comment, I found the solution I was looking for.
I used non-sequential indices.
Here is an example:
Action:
public ActionResult Create(List<namespace.Product> Products)
{
//do stuff
}
Model:
public class Product {
public string Code {get;set;}
public string Name {get;set;}
public int Quantity {get;set;}
public decimal Price {get;set;}
}
In my form the html will look like the following:
<input type='hidden' name='Products.Index' value='1'/>
<input type='hidden' name='Products[1].Code' value='xyz' />
<input type='hidden' name='Products[1].Name' value='Shirt' />
<input type='hidden' name='Products[1].Quantity' value='5'/>
<input type='hidden' name='Products[1].Price' value='50'/>
<input type='hidden' name='Products.Index' value='7'/>
<input type='hidden' name='Products[7].Code' value='zxy' />
<input type='hidden' name='Products[7].Name' value='Pants' />
<input type='hidden' name='Products[7].Quantity' value='8'/>
<input type='hidden' name='Products[7].Price' value='70'/>
<input type='hidden' name='Products.Index' value='foo'/>
<input type='hidden' name='Products[foo].Code' value='1234' />
<input type='hidden' name='Products[foo].Name' value='Shoes' />
<input type='hidden' name='Products[foo].Quantity' value='2'/>
<input type='hidden' name='Products[foo].Price' value='100'/>
All these will bind correctly. All that I had to add was the:
<input type='hidden' name='Products.Index' value='1'/>
All the index values just needs to be unique for this to work, so with just a few lines of jquery I was able to achieve this.
More information can be found here: Model Binding To A List
Upvotes: 0
Reputation: 39
I'm sure you figured this out a long time ago but it looks like you have a typo. Your example is using "values" instead of "value" for the second row values='David' />
Upvotes: 0
Reputation: 12034
You can try update the model with Ajax jQuery, that could be more eassier.
you can add a input button like:
<input type="button" value="Save/Update" id="saveUpdate" />
//Other HtmlCode
//Now script code
<script>
$(function(){
$("#saveUpdate").click(function({
$.ajax({
url: '/myController/GetDataForInvoiceNumber',
type: 'POST',
data: JSON.stringify(requestData),
dataType: 'json',
contentType: 'application/json; charset=utf-8',
error: function (xhr) {
alert('Error: ' + xhr.statusText);
},
success: function (result) {
CheckIfInvoiceFound(result);
},
async: true,
processData: false
});
});
});
</script>
//Contoller
Public ActionResult Submit(Products requestData)
{
//DO STUFF
}
That could works
Upvotes: 1
Reputation: 1898
You don't need an index to submit a list to the controller.
Public ActionResult Submit(string[] Names)
{
//DO STUFF
}
Then just change Names[]
to just Names
and it will still map to the Names
parameter even if you remove items.
<input type="hidden" name='Names' value='John'/>
<input type='hidden' name='Names` values='David' />
Upvotes: 0