0

I am currently trying to insert model objects via HTML form, however when debugged, it is the second table as null objects even though I specified the inputs field with name attributes which match how they have been called out in the models.

Here is the edmx diagram of my table:

enter image description here

my models:

 public class TReportHeaderModel
    {

        public int ID { get; set; }
        public int ClientID { get; set; }
        public string  THeaderTitle { get; set; }
        public int RowNumber { get; set; }

        public IList<TReporURLModel> TotalReports { get; set; }


    }


 public class TReporURLModel
    {
        public int ID { get; set; }
        public string  name { get; set; }
        public string url { get; set; }
        public int RowNumber { get; set; }
        public string hash { get; set; }
        //public int THeaderID { get; set; }
    }

Here is my HTML Form as modal. Please ignore the JavaScript as it is a way to demonstrate the functionality of the form I am here trying to implement.

However, my ajax to submit the form is below:

 initCreateGroupForm: function ()
    {
        $('#create-report-group-form').ajaxForm({

            dataType: 'json',
            beforeSerializate: function ($form, options) {

                Reporting.Forms = $form;
            },
            success: function (response) {

                if (response.Success == true) {
                    JQueryUX.Msg.BootStrapShow({
                        msg: response.Message,
                        className: 'alert alert-success',
                        title: 'Report Has Been Created.'
                    });

                    $("#create-report-group-modal").modal('hide');


                }
                else {
                    alert(response.Message);
                }



            },
            onError: function (xhr, status, error)
            {
                alert(error);

            }

        });

$(document).ready(function() {
  $("#add_row").on("click", function() {
    // Dynamic Rows Code

    // Get max row id and set new id
    var newid = 0;
    $.each($("#tab_logic tr"), function() {
      if (parseInt($(this).data("id")) > newid) {
        newid = parseInt($(this).data("id"));
      }
    });
    newid++;

    var tr = $("<tr></tr>", {
      id: "addr" + newid,
      "data-id": newid
    });

    // loop through each td and create new elements with name of newid
    $.each($("#tab_logic tbody tr:nth(0) td"), function() {
      var cur_td = $(this);

      var children = cur_td.children();

      // add new td and element if it has a nane
      if ($(this).data("name") != undefined) {
        var td = $("<td></td>", {
          "data-name": $(cur_td).data("name")
        });

        var c = $(cur_td).find($(children[0]).prop('tagName')).clone().val("");
        c.attr("name", $(cur_td).data("name") + newid);
        c.appendTo($(td));
        td.appendTo($(tr));
      } else {
        var td = $("<td></td>", {
          'text': $('#tab_logic tr').length
        }).appendTo($(tr));
      }
    });

    // add delete button and td
    /*
    $("<td></td>").append(
        $("<button class='btn btn-danger glyphicon glyphicon-remove row-remove'></button>")
            .click(function() {
                $(this).closest("tr").remove();
            })
    ).appendTo($(tr));
    */

    // add the new row
    $(tr).appendTo($('#tab_logic'));

    $(tr).find("td button.row-remove").on("click", function() {
      $(this).closest("tr").remove();
    });
  }); <!--Ends Here-->








  $("#add_row").trigger("click");
});
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form class="form-horizontal" id="create-report-group-form" action="@Url.Action(" CreateReport ", "TReporting ")" method="post">
  <input type="hidden" id="hidden-report-group-id" name="ID" value="null" />
  <div class="col-lg-12 table-responsive">
    <div class="col-lg-12" style="margin-bottom:20px;margin-left:-18px;">
      <label> Report Group Title</label>
      <input type="text" class="form-control" id="input-report-header-title" placeholder="Report Group Title" name="THeaderTitle">
    </div>
    <table class="table table-bordered table-hover table-sortable" id="tab_logic">
      <thead>
        <tr>
          <th class="text-center">
            Report Name
          </th>
          <th class="text-center">
            URLs
          </th>
          <th>
            <button id="add_row" type="button" class="btn btn-success" data-role="add">
                                            <span class="glyphicon glyphicon-plus"></span>
                                        </button>
          </th>
        </tr>
      </thead>


      <tbody>
        <tr id='addr0' data-id="0" class="">

          <td data-name="name">
            <input type="hidden" id="hidden-report-url-id" name="ID" value="null" />
            <input type="text" id="input-report-name" name='name' placeholder='Report Name' class="form-control" />
          </td>
          <td data-name="url">
            <input type="text" id="input-report-url" name='url' placeholder='https://' class="form-control" />
          </td>


          <td data-name="del">
            <button name="del0" type="button" class='btn btn-danger glyphicon glyphicon-remove row-remove'></button>
          </td>
        </tr>

      </tbody>


    </table>
    <div class="modal-footer">
      <button type="submit" class="btn-save btn btn-primary btn-block">Save</button>
      <button type="button" class="btn-cancel btn btn-secondary btn-block">Cancel</button>

    </div>
    <!--Modal-Footer Ends Here-->
  </div>
  <!---Model Body Ends Here-->

</form>

Is there specific way to call out the inputs which belong to the second table so that inputs can pass to TReport table with no issue.

Because no matter what I do, it keeps coming back to the service as null. As I debug it, I will get the first table's inputs but nothing will pass to the second query which is TReport table. My service code is below:

 public void CreateReport(TReportHeaderModel model)
        {

            using (var connection = new TReportEntitiesConnection())

            {
                connection.THeader.Add(new THeader()
                {
                    ID = model.ID,
                    THeaderTitle = model.THeaderTitle,
                    RowNumber = model.RowNumber


                });

                foreach (var urls in model.TotalReports)
                {

                    connection.TReport.Add(new TReport()
                    {
                        TReportName=urls.name,
                        URL=urls.url


                    });


                }

                connection.SaveChanges();


            }

Thank you!

Gerle Batde
  • 183
  • 3
  • 21
  • 1
    Your not creating inputs with the correct `name` attributes despite what your think - they need to be `name="TotalReports[0].ID"`, `name="TotalReports[1].ID"` etc (refer [this answer](http://stackoverflow.com/questions/30094047/html-table-to-ado-net-datatable/30094943#30094943) for an explanation –  Oct 24 '17 at 21:01
  • And it seems you wanting to dynamically create (and delete) new collection items, in which case, refer [this answer](http://stackoverflow.com/questions/28019793/submit-same-partial-view-called-multiple-times-data-to-controller/28081308#28081308) –  Oct 24 '17 at 21:03
  • @StephenMuecke Hi Stephen, as I try to loop with for loop, it is still giving me null results. Can you please show me some examples to approach this method correctly? – Gerle Batde Oct 24 '17 at 22:39
  • Look at both the links I gave you, in particular the 2nd one since you seem to be wanting to dynamically add collection items –  Oct 24 '17 at 22:43
  • @GerleBatde FYI, I included re-indexing in my answer, please let me know how it works for you. – David Lee Oct 27 '17 at 01:29

1 Answers1

1

I cleaned up some of your HTML and rewrote some JavaScript. This code is untested so please let me know how it works for you.

var index = 0;
var rowTemplate =
  `<tr id='addrINDEX' data-id="INDEX" class="">
    <td data-name="name">
      <input type="text" id="input-report-name" name='TotalReports[INDEX].name' placeholder='Report Name' class="form-control" />
    </td>
      <td data-name="url">
        <input type="text" id="input-report-url" name='TotalReports[INDEX].url' placeholder='https://' class="form-control" />
      </td>
      <td data-name="del">
        <button type="button" class='btn btn-danger glyphicon glyphicon-remove row-remove' onClick="deleteRow(INDEX);"></button>
      </td>
    </tr>`;

function realignIndexes() {
  var newIndex = 0;
  $.each($("#tab_logic tbody tr"), function() {
  
    // update table row id
    var tr = $(this);
    tr.attr("id", "addr" + newIndex);
    tr.attr("data-id", newIndex);

    // update inputs name
    var inputs = $(this).find(":input");
    inputs.each(function(index) {
      var e = $(this);
      var id = $(this).attr("id");
      if (id == "input-report-name") {
        $(this).attr('name', "TotalReports[" + newIndex + "].name");
      } else if (id == "input-report-url") {
        $(this).attr('name', "TotalReports[" + newIndex + "].url");
      }
    });
    
    // update button param
    var btn = $(this).find(":button");
    btn.attr("onclick", "deleteRow(" + newIndex + ")");

    newIndex++;
  });
}

function addRow() {
  var newTemplate = rowTemplate.replace(/INDEX/g, index);

  // add the new row
  $(newTemplate).appendTo($('#tab_logic'));
  index++;
};

function deleteRow(i) {
  if (index > 1) {
    $("#addr" + i).remove();
    index--;
    realignIndexes();
  }
};

$("#add_row").on("click", function() {
  addRow();
});

$(document).ready(function() {
  $("#add_row").trigger("click");
});
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="create-report-group-form" action="@Url.Action(" CreateReport ", "TReporting ")" method="post">
  <div class="panel">
    <div class="panel-body">
      <div class="h5">
        <label>Report Group Title</label>
        <input type="text" class="form-control" id="input-report-header-title" placeholder="Report Group Title" name="THeaderTitle">
      </div>
      <div class="table-responsive">
        <table class="table table-bordered table-hover table-sortable" id="tab_logic">
          <thead>
            <tr>
              <th class="text-center">Report Name</th>
              <th class="text-center">URLs</th>
              <th><button id="add_row" type="button" class="btn btn-success" data-role="add"><span class="glyphicon glyphicon-plus"></span></button></th>
            </tr>
          </thead>
          <tbody>
          </tbody>
        </table>
      </div>
    </div>
    <div class="modal-footer">
      <button type="submit" class="btn-save btn btn-primary btn-block">Save</button>
      <button type="button" class="btn-cancel btn btn-secondary btn-block">Cancel</button>
    </div>
  </div>
</form>

EDIT: Included re-indexing on delete.

David Lee
  • 2,040
  • 17
  • 36
  • I will test it out now. Thanks so much! – Gerle Batde Oct 27 '17 at 01:32
  • Sure thing, anytime. If you run into any issues just leave a comment and I maybe able to help. – David Lee Oct 27 '17 at 02:20
  • Hi David, I figured out a way to append new index #. However, what if there are already pre-added Indexes. So from there, how to figure out the index to add more rows? – Gerle Batde Oct 30 '17 at 18:52
  • https://jsfiddle.net/Gereltuya/oyjnw1ok/. Here is the example. My Ajax is appending tbody with index number but when I try to add more items. it'd start from index 0. how to get the maximum index of each table? – Gerle Batde Oct 30 '17 at 19:13
  • @GerleBatde A table should only have one tbody. I would remove the few extra you have in your html. When I do that your fiddle is indexing correctly. I did notice that the data-name and name attributes on your inputs are appending the number instead of overwriting, this would most likely cause issues when you post to the server. – David Lee Oct 30 '17 at 20:04