ISP
ISP

Reputation: 63

Post data in html dynamic table to controller with ajax

this is my table in view.

<table class="customtable" width="100%">
    <thead>
        <tr>
            <td>
                <div style="width: 80px">Employee ID</div>
            </td>
            <td>
                <label class="control-label">Employee Name:</label>
            </td>
            <td>
                <div style="width: 100px">Employee Type</div>
            </td>@foreach (var workDay in dayList) {
            <td>@workDay.Value
                <br>&nbsp; @workDay.Key</td>}</tr>
    </thead>
    <tbody>@for (int i = 0; i
        < Model.LineItems.Count; i++) { <tr>
            <td>@Html.DisplayFor(m =>@Model.LineItems[i].EmployeeNo)</td>
            <td>@Html.DisplayFor(m => @Model.LineItems[i].EmployeeName)</td>
            <td>@Html.DisplayFor(m => @Model.LineItems[i].EmployeeType)</td>@for (int j = 0; j
            < Model.LineItems[i].EmployeeLineItems.Count; j++) { <td>@Html.EditorFor(m => m.LineItems[i].EmployeeLineItems[j].ShiftCode, MVC.Shared.Views.EditorTemplates.ShiftCodePicker)</td>}</tr>}</tbody>
</table>

I want to pass this to controller via ajax post method

function ajaxAdd() {
    var i = 0;
    var model;
    for (i = 0; i < 10; i++) {
        model = {
            'EmployeeId': $("#@Html.FieldIdFor(m => m.EmployeeId)").val(),
                'SignatureId': $("#@Html.FieldIdFor(m => m.SignatureId)").val(),
                'StoreId': $("#@Html.FieldIdFor(m => m.StoreId)").val(),
                'ScheduleDate': $("#@Html.FieldIdFor(m => m.ScheduleDate)").val(),
                'LineItems[0].EmployeeLineItems[1].ShiftCode': $("#@Html.FieldIdFor(m => m.LineItems[0].EmployeeLineItems[1].ShiftCode)").val()
        };
    }


    $.ajax({
        url: "@Url.Action(MVC.WorkSchedule.ActionNames.AddNew, MVC.WorkSchedule.Name)",
        type: "post",
        data: JSON.stringify(model),
        contentType: 'application/json',
        success: function () {

            window.location.href = "@Url.Action(MVC.WorkSchedule.ActionNames.Create, MVC.WorkSchedule.Name)";
        }
    });
}

when i pass the values like $("#@Html.FieldIdFor(m => m.LineItems[0].EmployeeLineItems[1].ShiftCode)").val() i can get that value in controller method. but once i replace them with 'i' it will not work.

Is there any other way i can send this data to controller with ajax post method?

Upvotes: 1

Views: 4972

Answers (1)

sabotero
sabotero

Reputation: 4375

I don't have the details of your models but given the mark-up and code you provided I pull out this example using Microsoft jQuery Unobtrusive Ajax (You have to install it if you haven't yet, using Nuget is the easiest way. In the Nuget console enter Install-Package Microsoft.jQuery.Unobtrusive.Ajax. You can also use the NuGet Packages Manager).

This works as expected sending to the server (via AJAX into the action EmployeesPost) the new values on shift codes TextBoxes.

After install the Microsoft.jQuery.Unobtrusive.Ajax you have to add a bundle in your BundleConfig.csfile under the App_Start folder, like this:

 bundles.Add(new ScriptBundle("~/bundles/jqueryajax").Include(
                "~/Scripts/jquery.unobtrusive-ajax.js"));

Here are the models I create trying to reproduce yours : (I put all these in a EmployeeViewModels.cs file under Models folder)

using System.Collections.Generic;

    namespace ExemplesApplication.Models
    {
        public class ShiftCode
        {
            public string Name { get; set; }
        }
        public class EmployeeLine
        {
            public ShiftCode ShiftCode { get; set; }
        }
        public class Employee
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public string Type { get; set; }
        public List<EmployeeLine> EmployeeLineItems { get; set; }

        public Employee()
        {
            EmployeeLineItems = new List<EmployeeLine>
            {
                new EmployeeLine {ShiftCode = new ShiftCode {Name = "Morning" }},
                new EmployeeLine {ShiftCode = new ShiftCode {Name = "NOON"}},
                new EmployeeLine {ShiftCode = new ShiftCode {Name = "Afternoon"}},
                new EmployeeLine {ShiftCode = new ShiftCode {Name = "evening"}},
                new EmployeeLine {ShiftCode = new ShiftCode {Name = "Night"}}
            };
        }
    }
    public class EmployeesViewModel
    {
        public bool HaveToAddRow { get; set; }
        public Dictionary<string, string> WorkDays
        {
            get
            {
                return new Dictionary<string, string>
                {
                    {"Monday", "1"},
                    {"Tuesday", "2"},
                    {"Wednesday", "3"},
                    {"Thursday", "4"},
                    {"Friday", "5"}
                };
            }
        }

        public List<Employee> Employees { get; set; }

        public EmployeesViewModel()
        {
            Employees = new List<Employee>
            {
                new Employee {Id = 1, Name = "Robert", Type = "Engineer"},
                new Employee {Id = 2, Name = "Albert", Type = "Driver"},
                new Employee {Id = 3, Name = "Fred", Type = "Manager"},
                new Employee {Id = 4, Name = "Thomas", Type = "Sales"},
                new Employee {Id = 5, Name = "Sahra", Type = "Engineer"}
            };
        }
    }
}

Then the controller looks like this (EmployeeController.cs) :

    using ExemplesApplication.Models;
    using System.Web.Mvc;

    namespace ExemplesApplication.Controllers
    {
        public partial class EmployeeController : Controller
        {
            public virtual ActionResult Index()
            {
                return View(new EmployeesViewModel());
            }

            public virtual ActionResult EmployeesPost(EmployeesViewModel model)
            {
                if (model.HaveToAddRow)
                {
                    //add row
                    model.Employees.Add(new Employee {Id = 1, Name = "New employee", Type = "Engineer"});
                    return PartialView(MVC.Employee.Views._TableEmployees, model);
                }
                else
                {
                    // your logic to save 
                    //here

                    // render the partial view
                    return PartialView(MVC.Employee.Views._TableEmployees, model);
                }
            }
        }
    }

Then I created one view and one partial view :

View (/Views/Employee/Index.cshtml)

@model ExemplesApplication.Models.EmployeesViewModel
@{
    ViewBag.Title = "Employees";

    var ajaxOptions = new AjaxOptions {UpdateTargetId = "employees-table-container", Url = Url.Action(MVC.Employee.EmployeesPost())};
}

<h2>Index</h2>

@using(Ajax.BeginForm(ajaxOptions))
{
    @Html.HiddenFor(m=>m.HaveToAddRow)
    <div id="employee-container">
        <div id="employees-table-container">
            @Html.Partial(MVC.Employee.Views._TableEmployees, Model)
        </div>
        <input id="add-row" type="button" value="Add Row" />
        <input id="save-table"type="submit" value="Submit" />
    </div>
}

@section scripts
{
    @Scripts.Render("~/bundles/jqueryajax")
    <script type="text/javascript">
        $(document).ready(function () {
            var $form = $("form"),
                $haveToAddRowHidden = $("#HaveToAddRow");

            $("#add-row").on("click", function() {
                $haveToAddRowHidden.val(true);
                $form.submit();
            });

            $("#save-table").on("click", function () {
                $haveToAddRowHidden.val(false);
            });
        });
    </script>
}

PartialView (/Views/Employee/_TableEmployees.cshtml)

@model ExemplesApplication.Models.EmployeesViewModel

<table class="customtable" width="100%">
    <thead>
        <tr>
            <td>
                <div style="width: 80px">Employee ID</div>
            </td>
            <td>
                <label class="control-label">Employee Name:</label>
            </td>
            <td>
                <div style="width: 100px">Employee Type</div>
            </td>
            @foreach (var workDay in Model.WorkDays)
            {
                <td>
                    @workDay.Value
                    <br>&nbsp; @workDay.Key
                </td>
            }
        </tr>
    </thead>
    <tbody>
        @for (var i = 0; i < Model.Employees.Count(); i++)
        {
            <tr>
                <td>
                    @Html.DisplayFor(m => @Model.Employees[i].Id)
                    @Html.HiddenFor(m => @Model.Employees[i].Id)
                </td>
                <td>
                    @Html.DisplayFor(m => @Model.Employees[i].Name)
                    @Html.HiddenFor(m => @Model.Employees[i].Name)
                </td>
                <td>
                    @Html.DisplayFor(m => @Model.Employees[i].Type)
                    @Html.HiddenFor(m => @Model.Employees[i].Type)
                </td>
                @for (var j = 0; j < Model.Employees[i].EmployeeLineItems.Count; j++)
                {
                    <td>@Html.EditorFor(m => m.Employees[i].EmployeeLineItems[j].ShiftCode, MVC.Shared.Views.EditorTemplates.ShiftCodePicker)</td>
                }
            </tr>
        }
    </tbody>
</table>

Finally I created the EditorTemplate (Views/Shared/EditorTemplates/ShiftCodePicker.chtml)

@model ExemplesApplication.Models.ShiftCode

@Html.TextBoxFor(m=> m.Name, new { @class = "editor-for-shiftcode" })

Upvotes: 1

Related Questions