2

So I have a table that works like this: https://gfycat.com/WeakBlueIslandwhistler

Generated by:

<table class="table table-bordered table-with-button table-condensed " id="hidTable">
                            <thead>
                            <tr>
                                <th>HID #</th>
                                <th>Lines</th>
                            </tr>
                            </thead>
                            @for (int j = 0; j < 3; j++)
                            {
                                <tr>
                                    <td>
                                        <input class="form-control table-with-button" type="number" placeholder="HID" id="hid-@j">
                                    </td>
                                    <td>
                                        <input class="form-control table-with-button" type="number" placeholder="Lines" id="lines-@j">
                                    </td>
                                </tr>
                            }
 </table>

New rows and textboxes are created by calling a javascript method.

Essentially, there are an unknown number of pairs of text fields in this table, and the data pairs need to be passed to the controller... (I'm thinking storing it as an object in tempdata?)

Each textbox has a unique id (hid-1, hid-2 hid-3 and lines-1, lines-2, lines-3 respectively)

What is the best way to iterate over these textboxes, save their value (I can handle validation prior to saving) and then pass it to the backend?

1
  • Note that your code will never be able to 2-way bind correctly and you need a collection of a model with 2 properties ( int Hid and int Line) and then to generate the view correctly and allow correct binding and validation, refer this answer Commented Oct 27, 2016 at 22:11

1 Answer 1

2

The MVC Modelbinder will be able to directly bind the POST data if you meet some conditions:

  • The name and id of the dynamically added HTML inputs conform to the naming scheme used by MVC. I.e. to bind the first element of a collection, the value of the html id attribute should be {collectionName}_0 and the value of the name attribute should be {collectionName}[0]
  • The ViewModel contains collections to which the list of inputs can be bound.

So in your case, define a ViewModel that contains lists for HIDs and Lines

public class PostDataModel {
    public ICollection<int> Hids { get; set; }
    public ICollection<int> Lines { get; set; }
}

Then make sure that the javascript code that adds additional lines sets idand name correctly.

The generated inputs for the 0th line should look like this:

<input class="form-control table-with-button" type="number" placeholder="HID" id="Hids_0" name="Hids[0]">
<input class="form-control table-with-button" type="number" placeholder="Lines" id="Lines_0" name="Lines[0]">

If the User can delete any line before sumbitting, watch out for non sequential indices!

Then just submit the form with a normal POST and correlate HIDs and Lines using their index.

Sign up to request clarification or add additional context in comments.

2 Comments

Wow, thanks, that works perfectly! Is this behaviour specific to icollections or can it be used for other collection types? (Out of curiosity, really- I am sticking with your solution.) Lets say I would want indexes at some point.
You do not need the indexer because its a collection of simple values (the indexers are only required for collections of complex objects and it can simply be <input class="..." type="number" placeholder="HID" name="hids"> (the id attribute is unnecessary)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.