locked
Dynamically Add / Remove input fields in MVC & Save data into Database with Jquery Ajax RRS feed

  • Question

  • User490317677 posted

    I have page, where User can dynamically add/remove input fields and its generate input field as many as user wants and in the end user hit submit button to save data/value of input fields into database.

    But it saves only one input field value into database and it can not saves data/value of second or third input fields

    Can anyone please help me :) thanks in advance :)

    Here is my JavaScript - UPDATED :

    <script>
        $(document).ready(function () {
            //Add input field 
            var i = 1;
            $("#add").click(function (e) {
                i++;
                e.preventDefault();
               $("#tbhold").append('<tr id="row' + i + '"><td><div class="col-md-8"><input type="text" name="[' + i + ']Varenummer[]" id=' + i + ' class="form-control" /><input type="hidden" name="Varenummer.Index" value="' + i + '" /></div></td><td><div class="col-md-8"><input type="text" name=""[' + i + ']Serienummer[]" id=' + i + ' class="form-control" /><input type="hidden" name="Serienummer.Index" value="' + i + '" /></div></td><td><button type="button" class="btn btn-danger btn_remove" id="' + i + '" name="remove">X</button></td></tr>');
    }); //Remove input field $(document).on('click', '.btn_remove', function () { var button_id = $(this).attr("id"); $("#row" + button_id + '').remove(); }); //Save to db by click $("#submit").click(function (e) { e.preventDefault(); $.ajax({ type: 'POST', url: '@Url.Action("ProcessCreateRMA", "User")', dataType: 'json', data: $('#add_rma').serialize(), success: function (CreateRMA) { console.log(CreateRMA); }, error: function () { console.log('something went wrong - debug it!'); } }); }); }); </script>

    HTML:

    <form name="add_rma" id="add_rma">
        <table id='tbhold' class="table">
            <thead>
                <tr>
                    <th>Varenummer</th>
                    <th>Serienummer</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>
                        <div class="col-md-8">
                            <input type="text" name="Varenummer[]" id="Varenummer" class="form-control" />
                        </div>
                    </td>
                    <td>
                        <div class="col-md-8">
                            <input type="text" name="Serienummer[]" id="Serienummer" class="form-control" />
                        </div>
                    </td>
                 <td>
                  <button type="button" name="add" id="add" class="btn btn-success">Add More</button>
                </td>
            </tbody>
        </table>
        <input type="button" name="submit" id="submit" value="Submit" />
    </form>

    Controller - UPDATED:

        [HttpPost]
        public JsonResult ProcessCreateRMA()
        {
    List<CreateRMAVM> vm = new List<CreateRMAVM>();
    RMA_History model = new RMA_History();
    foreach (var item in vm)
    {
    model.Varenummer = item.Varenummer;
    model.Serienummer = item.Serienummer;
    db.RMA_History.Add(model);
    db.SaveChanges();
    }
    return Json(model, JsonRequestBehavior.AllowGet); } ViewModel: public class CreateRMAVM { public string Varenummer { get; set; } public string Serienummer { get; set; } }
    Monday, December 17, 2018 2:53 PM

Answers

  • User475983607 posted

    i updated my question with those changes as you said ,but its retrieve null :( 

    If the Indexes are sequential the HTML should have the following format.

            <table>
                <tr>
                    <td>
                        <input type="text" name="[0].Varenummer" value="var1" />
                    </td>
                    <td>
                        <input type="text" name="[0].Serienummer" value="ser1" />
                    </td>
                </tr>
                <tr>
                    <td>
                        <input type="text" name="[1].Varenummer" value="var3" />
                    </td>
                    <td>
                        <input type="text" name="[1].Serienummer" value="ser3" />
                    </td>
                </tr>
            </table>

    If the index is not sequential the HTML format is..

            <table>
                <tr>
                    <td>
                        <input type="hidden" name="Index" value="0" />
                        <input type="text" name="[0].Varenummer" value="var1" />
                    </td>
                    <td>
                        <input type="text" name="[0].Serienummer" value="ser1" />
                    </td>
                </tr>
                <tr>
                    <td>
                        <input type="hidden" name="Index" value="3" />
                        <input type="text" name="[3].Varenummer" value="var3" />
                    </td>
                    <td>
                        <input type="text" name="[3].Serienummer" value="ser3" />
                    </td>
                </tr>
            </table>

    https://www.learnrazorpages.com/razor-pages/model-binding



     

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, December 17, 2018 5:13 PM
  • User1520731567 posted

    Hi ManDown,

    According to your requirement,I suggest you could use model binder to pass List<model> from view to controller.

    You need to pay attention to the name tags.

    The name must correspond to the structure of List<model>.

    If so,you could get all data within List<model> to controller by clicking submit button.

    In addtion,id cannot be repeated.

    @model List<xxx.xxx.xxx.CreateRMAVM>
    ...


    <tbody> <tr> <td> <div class="col-md-8"> <input type="text" name="CreateRMAVM[0].Varenummer" id="Varenummer" class="form-control" /> </div> </td> <td> <div class="col-md-8"> <input type="text" name="CreateRMAVM[0].Serienummer" id="Serienummer" class="form-control" /> </div> </td> <td> <button type="button" name="add" id="add" class="btn btn-success">Add More</button> </td> </tbody>
    ...

    <input type="submit" name="submit" id="submit" value="Submit" />

    and the modify your js:

     var i = 0;
            $("#add").click(function (e) {
                i++;
                e.preventDefault();
                $("#tbhold").append('<tr id="row' + i + '"><td><div class="col-md-8"><input type="text" name="CreateRMAVM[' + i + '].Varenummer"  class="form-control" /></div></td><td><div class="col-md-8"><input type="text" name="CreateRMAVM[' + i + '].Serienummer"  class="form-control" /></div></td><td><button type="button" class="btn btn-danger btn_remove"  name="remove">X</button></td></tr>');
    
            });

    Controller:

    [HttpPost] 
    public ActionResult ProcessCreateRMA(List<CreateRMAVM> vm)
    {
    ...
    }

    The similar example,you could refer to:

    https://www.codeproject.com/Tips/766214/List-Model-Binding-in-MVC

    Best Regards.

    Yuki Tao

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, December 18, 2018 6:55 AM

All replies

  • User-474980206 posted
    Your post back model only allows one row. It should be a List<CreateRMAVM>. Also you should either remove the [] from the names or include the index.
    Monday, December 17, 2018 3:10 PM
  • User475983607 posted

    But it saves only one input field value into database.

    The ProcessCreateRMA take a single CreateRMAVM type.  

    [HttpPost]
    public JsonResult ProcessCreateRMA(CreateRMAVM model)
    {

    Define a collection argument not a single item.  You'll need to update the method body too so it handles a collection.

    [HttpPost]
    public JsonResult ProcessCreateRMA(List<CreateRMAVM> model)
    {

    The MVC model binder expects an indexed input name. You'll need to fix the input name attributes.

    <input type="text" name="[" + i + "]Serienummer[]" id=' + i + '  class="form-control" />

    This posses a problem when deleting a row as the index example above expects a sequence.

    For none sequences, you'll need to add a hidden field.

    <input type="hidden" name="Serienummer.Index" value="' + i + '" />
    <input type="text" name="[' + i + ']Serienummer[]" id="' + i + '"  class="form-control" />

    See the following Blog

    https://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/

    Also, use the browser's dev tools when debugging your code.  Dev tools makes debugging a lot easier.

    Monday, December 17, 2018 3:13 PM
  • User490317677 posted

    i updated my question with those changes as you said ,but its retrieve null :( 

    Monday, December 17, 2018 3:44 PM
  • User-474980206 posted

    the name needs to be:

    <input type="text" name="Serienummer[0]" id="Serienummer" class="form-control" />

    then incrementing number in dynamic. or just leave it off:

    <input type="text" name="Serienummer" id="Serienummer" class="form-control" />
    Monday, December 17, 2018 4:01 PM
  • User475983607 posted

    i updated my question with those changes as you said ,but its retrieve null :( 

    If the Indexes are sequential the HTML should have the following format.

            <table>
                <tr>
                    <td>
                        <input type="text" name="[0].Varenummer" value="var1" />
                    </td>
                    <td>
                        <input type="text" name="[0].Serienummer" value="ser1" />
                    </td>
                </tr>
                <tr>
                    <td>
                        <input type="text" name="[1].Varenummer" value="var3" />
                    </td>
                    <td>
                        <input type="text" name="[1].Serienummer" value="ser3" />
                    </td>
                </tr>
            </table>

    If the index is not sequential the HTML format is..

            <table>
                <tr>
                    <td>
                        <input type="hidden" name="Index" value="0" />
                        <input type="text" name="[0].Varenummer" value="var1" />
                    </td>
                    <td>
                        <input type="text" name="[0].Serienummer" value="ser1" />
                    </td>
                </tr>
                <tr>
                    <td>
                        <input type="hidden" name="Index" value="3" />
                        <input type="text" name="[3].Varenummer" value="var3" />
                    </td>
                    <td>
                        <input type="text" name="[3].Serienummer" value="ser3" />
                    </td>
                </tr>
            </table>

    https://www.learnrazorpages.com/razor-pages/model-binding



     

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, December 17, 2018 5:13 PM
  • User1080785583 posted

    Very old issue, which requires a very old thread by a guy by Phil Haack. 

    https://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/

    Whilst the sequence list will model bind correctly on your by val, there are other options to model bind list objects.

    Hope this helps!

    Monday, December 17, 2018 6:10 PM
  • User1520731567 posted

    Hi ManDown,

    According to your requirement,I suggest you could use model binder to pass List<model> from view to controller.

    You need to pay attention to the name tags.

    The name must correspond to the structure of List<model>.

    If so,you could get all data within List<model> to controller by clicking submit button.

    In addtion,id cannot be repeated.

    @model List<xxx.xxx.xxx.CreateRMAVM>
    ...


    <tbody> <tr> <td> <div class="col-md-8"> <input type="text" name="CreateRMAVM[0].Varenummer" id="Varenummer" class="form-control" /> </div> </td> <td> <div class="col-md-8"> <input type="text" name="CreateRMAVM[0].Serienummer" id="Serienummer" class="form-control" /> </div> </td> <td> <button type="button" name="add" id="add" class="btn btn-success">Add More</button> </td> </tbody>
    ...

    <input type="submit" name="submit" id="submit" value="Submit" />

    and the modify your js:

     var i = 0;
            $("#add").click(function (e) {
                i++;
                e.preventDefault();
                $("#tbhold").append('<tr id="row' + i + '"><td><div class="col-md-8"><input type="text" name="CreateRMAVM[' + i + '].Varenummer"  class="form-control" /></div></td><td><div class="col-md-8"><input type="text" name="CreateRMAVM[' + i + '].Serienummer"  class="form-control" /></div></td><td><button type="button" class="btn btn-danger btn_remove"  name="remove">X</button></td></tr>');
    
            });

    Controller:

    [HttpPost] 
    public ActionResult ProcessCreateRMA(List<CreateRMAVM> vm)
    {
    ...
    }

    The similar example,you could refer to:

    https://www.codeproject.com/Tips/766214/List-Model-Binding-in-MVC

    Best Regards.

    Yuki Tao

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, December 18, 2018 6:55 AM
  • User490317677 posted

    Thanks to both of you for help and useful links :)

    Tuesday, December 18, 2018 10:41 AM