0

Below is my Razor View

    <tr id="CGT_Row">
                    <td class="noGutter">@Html.TextBoxFor(m => m.clsCGT.CGT_Visit_Date, new {@id="dp1",  @class = "input-sm text-center date", @readonly = "true" }) </td>
                    <td class="noGutter">
                        @Html.DropDownListFor(m => m.clsCGT.days_of_CGT, new List<SelectListItem>
                                           {
                                               new SelectListItem { Text="1 Day",Value="1 Day"},
                                               new SelectListItem { Text="2 Day",Value="2 Day"},
                                               new SelectListItem { Text="3 Day",Value="3 Day"},
                                           },
             new { @class = "input-sm", @actor = "DropDown" })
                </td>
                <td class="noGutter">@Html.TextBoxFor(m => m.clsCGT.village_Name, new { @class = "input-sm text-center" })</td>
                <td class="noGutter">@Html.DropDownListFor(m => m.clsCGT.fo_Name_CGT, TempData["Staff_List"] as IEnumerable<SelectListItem>, new { @id = "ddl_CGT_fo", @class = "input-sm", @actor = "DropDown", @style = "width:auto;" })</td>
                <td class="noGutter">
                    @Html.DropDownListFor(m => m.clsCGT.member_attendence_CGT, new List<SelectListItem>
                                           {
                                               new SelectListItem { Text="Less than 100%",Value="Less than 100%"},
                                               new SelectListItem { Text="100%",Value="100%"}
                                           },
                     new { @class = "input-sm", @actor = "DropDown", @style = "width:auto;" })
            </td>
            <td class="noGutter">
                @Html.DropDownListFor(m => m.clsCGT.process_follow_CGT, new List<SelectListItem>
                                           {
                                               new SelectListItem { Text="n",Value="n"},
                                               new SelectListItem { Text="y",Value="y"}
                                           },
                             new { @class = "input-sm", @actor = "DropDown", @style = "width:100%;" })
        </td>
        <td class="noGutter">
            @Html.DropDownListFor(m => m.clsCGT.CGT_timing, new List<SelectListItem>
                                           {
                                               new SelectListItem { Text="As per time",Value="As per time"},
                                               new SelectListItem { Text="Delayed",Value="Delayed"},
                                               new SelectListItem { Text="Reschedule",Value="Reschedule"},
                                           },
                                     new { @class = "input-sm", @actor = "DropDown", @style = "width:auto;" })
    </td>
    <td class="noGutter">
        @Html.DropDownListFor(m => m.clsCGT.fo_comm_to_client, new List<SelectListItem>
                                           {
                                               new SelectListItem { Text="n",Value="n"},
                                               new SelectListItem { Text="y",Value="y"}
                                           },
                                             new { @class = "input-sm", @actor = "DropDown", @style = "width:100%" })
</td>
<td class="noGutter">
    @Html.DropDownListFor(m => m.clsCGT.member_house_verification_CGT, new List<SelectListItem>
                                           {
                                               new SelectListItem { Text="n",Value="n"},
                                               new SelectListItem { Text="y",Value="y"}
                                           },
                                                   new { @class = "input-sm", @actor = "DropDown", @style = "width:100%;" })
</td>
<td class="noGutter">
    @Html.DropDownListFor(m => m.clsCGT.documentation_complete_CGT, new List<SelectListItem>
                                           {
                                               new SelectListItem { Text="n",Value="n"},
                                               new SelectListItem { Text="y",Value="y"}
                                           },
                                                   new { @class = "input-sm", @actor = "DropDown", @style = "width:100%;" })
</td>
<td class="noGutter">
    @Html.DropDownListFor(m => m.clsCGT.CGT_conducted_for_3_days, new List<SelectListItem>
                                           {
                                               new SelectListItem { Text="n",Value="n"},
                                               new SelectListItem { Text="y",Value="y"}
                                           },
                                                   new { @class = "input-sm", @actor = "DropDown", @style = "width:100%;" })
</td>
<td class="noGutter">@Html.TextAreaFor(m => m.clsCGT.CGT_remarks, new { @class = "input-sm" })</td>
</tr>

This is bind with model and onclick of a button I can save this into database without any problem .

But my need is I want to add another row too before saving it into database

So I used jquery to add another row in table below this row

function Create_New_Row(id) {

    var row; var table;
    var closeBtn = '<td><a onclick="$(this).parent().parent().remove();"><i class="fa fa-times fa-lg fa-border" aria-hidden="true" style="color:#e90029"></i></a></td>';
    if (id == 'CGT_Row')
    {
        row = '#CGT_Row';
        table = '#tbl_CGT tr:last';
    }
    else if (id == 'GRT_Row')
    {
        row = '#GRT_Row';
        table = '#tbl_GRT tr:last';
    }
    else if (id == 'Disb_Row')
    {
        row = '#Disb_Row';
        table = '#tbl_Disb tr:last';
    }
    var v = $(row);
    var html = '<tr>' + v.html() + closeBtn + '</tr>';
    $(table).after(html);

    $('[id^="dp"]').datepicker({
         format: 'dd/mm/yyyy',
         autoclose: true
    });

}

This will look like this

See this image

Click to add new row - to add new row into table

Save Details - To save all these rows into database

The Problem is - Only first row is bound to model , which I can access to save data, how to get data from other rows(added later ) coz they are just duplicate copy of first row html only without model binding

For example - if I filled 4 rows than on Click of Save Details all 4 rows should be saved in database (SQL Server)

Update :1

For Viktor Oleksyshyn

Below is my js code to convert this table values into array and pass it to controller

function Table_to_Array(id) {

    if (id == "CGT_Data")
    { var tbl="tbl_CGT"; }
    if (id == "GRT_Data")
    { var tbl = "tbl_GRT"; }
    if (id == "Disb_Data")
    { var tbl = "tbl_Disb"; }

    var myTableArray = $('#'+tbl+' tr').map(function () {
        return $(this).find(':input').map(function () {
            return this.value;
        }).get();
    }).get();
    return myTableArray;
}

function send_to_server(id)
{
    var iden = id;
    var result = Table_to_Array(id);
    var data = {
        data_holder: result,
        Category: id
    };

    var params = {
        url: '@Url.Action("Send_to_server", "Annex1")',
        type: "POST",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        traditional : true,
        data: JSON.stringify(data),
        success: function (result) { alert('Ok! It worked.'); },
        error: function (result) { alert('Warning! It failed.'); }
    };
    $.ajax(params);
}

It does pass the array to controller but also show alert failure - (set on error: function [alert('Warning! It failed.'); ])

  • Are you using ajax for saving? – Power Star Aug 10 '17 at 06:41
  • I think using jQuery to generate tables dynamically is quite complicated. A single partial view which rendered for every row added by AJAX call (use indexing) & using custom model binder to save rows data is more preferred over fully JS/jQuery solution. – Tetsuya Yamamoto Aug 10 '17 at 06:41
  • @TetsuyaYamamoto can you refer any post for this approach ? –  Aug 10 '17 at 06:45
  • @PowerStar , no . For right now I don't have any idea to save this data . In Asp.net It is doable with gridview which allow us to add footer template functionality , But i don't know how to do that in mvc –  Aug 10 '17 at 06:46
  • Is your post method handled from jquery ajax or from the server side itself? If you can please share it. – Libin C Jacob Aug 10 '17 at 06:49
  • @Guru Try reading this as reference: http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/. Basically in Razor view it can be used, just use `return PartialView` for every AJAX call made & append HTML element to the table. – Tetsuya Yamamoto Aug 10 '17 at 06:51
  • @TetsuyaYamamoto, Thanks for your response , But all it shows is how to use partial view for dynamic addition or row functionality , It does not say anything about how to save data from all those row . Adding row is not a problem , saving them is the main issue –  Aug 10 '17 at 06:58
  • @Guru - you can use begincollectionitem in mvc. https://stackoverflow.com/questions/29700557/mvc-5-dynamic-rows-with-begincollectionitem – Ubiquitous Developers Aug 10 '17 at 07:00
  • I've also posted an answer to a similiar question using Tetsuyas linked blog post as a refernce: https://stackoverflow.com/questions/45160894/how-to-handle-multiple-dynamic-form-with-c-sharp/45164126#45164126 – Marco Aug 10 '17 at 08:30
  • @Marco - does "files" in beginCollection need to be a property in model ? –  Aug 10 '17 at 08:39
  • not in the model. But if you name your collection "files", then the parameter in your action method needs to be named files as well or it will not be picked up – Marco Aug 10 '17 at 09:37
  • I did that and only getting one collection , other collections are getting lost –  Aug 10 '17 at 09:41
  • @Marco , please search for "MVC Html.BeginCollectionItem is not creating collection" –  Aug 10 '17 at 09:42

1 Answers1

0

As I can see you are using
@Html.TextAreaFor(m => m.clsCGT.CGT_remarks... That would be rendered to something like this:

<input type="text" name="CGT_remarks" ... />

When you making a copy of row - you did not change the name of the input. So in the example you have three collections of inputs with same names. When you submitting a form "system" uses names as identifiest for request parameters, so - 1 unique name for parameter. What you can do for simple workaround:

  1. If you have simple form.submit or Ajax call with data: form.collection - you can change the control names by adding some suffix at the end and then manually parse it on controller via this.Request.Form. I do not really like this solution, so I hope the second one fits.

  2. You can also collect your objects from inputs by jquery selector into array. Then, just use Ajax call and pass your array to controller like in this solution

  • I was thinking about second option too , but above everyone said its the most worst way to do this , see my updated question , it post data to controller but also show alert which is set on error function –  Aug 10 '17 at 08:35
  • What is your Action returns? If it returns null, please try return this.Json(true); – Viktor Oleksyshyn Aug 10 '17 at 08:42
  • Adding Json(true) helped here , Thanks –  Aug 10 '17 at 09:02