0

I have a table that its rows are created dynamically with jQuery. I can add or remove rows so when all fields are ready, I just submit it. Since the rows are created before any posting, how can I properly name them to later easily retrieve their values in controller actions like Create? Consider that each row is "an object" or at least an array for each one.

In ruby, just by adding [] to the name= attribute do the job, not sure if ASP.NET is possible to that.

This is the script for creating rows:

function add_row() {
  var detalle = $('#detail');
  var index = $("#detail tbody").children("tr").length;
  var newRow = '<tr>' +
    '<td style="display:none"><input name="Detalle.Index" type="hidden" value="' + index + '" /></td>' +
    '<td data-title="Quantity">' +
    '<div class="input-group">' +
    '<span class="input-group-addon"></span>' +
    '<input class="form-control" type="number" aria-label="Quantity" name="Detail['+ index +'].quantity" id="Detail_' + index + '__quantity"  step="0.001" min="0.000">' +
    '</div>' +
    '</td>' +
    '<td data-title="Price" >' +
    '<div class="input-group">' +
    '<span class="input-group-addon">$</span>' +
    '<input type="number" class="form-control" aria-label="Price" name="Detail['+ index +'].price" id="Detail_' + index + '__price" step="0.001" min="0.000" required="true">' +
    '</div>' +
    '</td>' +
    '<td data-title=""><button type="button" class="btn btn-danger btn-sm" onclick="delete_row(this)">Cancel</button></td>' +
    '</tr>';
  detail.append(newRow);
}

In controller I can access to Request with Request.Form["Detail[0].price"] to get a specific value, however I'm not able how to get the total of rows to create a loop and get values like this: Detail[i].inputname

Any suggestion will be appreciated.

Mr_LinDowsMac
  • 2,644
  • 9
  • 56
  • 75
  • 2
    Don't use `Request` Make use of the features of MVC. You POST method should include a parameter `List model` so that the collection is bound by the `DefaultModelBinder`. Refer the answers [here](http://stackoverflow.com/questions/29161481/post-a-form-array-without-successful/29161796#29161796) and [here](http://stackoverflow.com/questions/28019793/submit-same-partial-view-called-multiple-times-data-to-controller/28081308#28081308) for some examples –  Oct 19 '15 at 21:51
  • This is Master-detail scenario. That is still applicable? – Mr_LinDowsMac Oct 19 '15 at 22:34
  • 1
    Absolutely. And note in the examples the hidden input for the indexer (in your case it will be `` (where `#` is the indexer) which allows you to delete items from the collection. Note also your current implementation could never work because if your added some items and then deleted some, you could end up with duplicate indexers because of your use of `$("#detail tbody").children("tr").length;` –  Oct 19 '15 at 22:39

1 Answers1

2

Rather than using Request.Form[".."] to get the form values, make use of MVC's powerful model binding features and bind directly to your model.

Based on the code in your script you have a main model with a property named Detail which is a collection of a complex object with properties quantity and price, so your method can be

public ActionResult Edit(YourMainModel model)

and the values of model.Detail will be correctly bound.

However there a 2 errors in your script which will prevent binding to the model

First is the incorrect name attribute for the hidden input. It needs to be

<input name="Detail.Index" type="hidden" value="' + index + '" />

not name="Detalle.Index"

The second is that your indexer is based on the number of rows in the table which could result in duplicate indexers. If you started with an empty table and added 3 items, the last one would have the index value as 2. If you then deleted say the first one and then added another, its index value would also be 2 causing binding to fail. You need to ensure that the indexer is unique. One way of achieving this is to use

var index = (new Date()).getTime();