2

I'm trying to have an editable table, where each row is a view that can be submitted individually, in order to harvest all the benefits of Model validation etc.

Here is what I've got:
Model:

public class PeopleGroup
{
    public string Name { get; set; }
    public ICollection<PersonModel> People { get; set; }
}

public class PersonModel
{
    [Required]
    public uint Id { get; set; }

    [Required]
    [RegularExpression("[\\w\\s]{2,100}")]
    [StringLength(100)]
    public string FirstName { get; set; }

    [Required]
    [RegularExpression("[\\w\\s]{2,100}")]
    [StringLength(100)]
    public string LastName { get; set; }
}

List View:

@model Mvc4TestApp.Models.PeopleGroup
@{
    ViewBag.Title = "People";
}

<h2>@Model.Name</h2>
<table>
    @foreach (var item in Model.People)
    {
    <tr id="@string.Format("Person-{0}", item.Id)">
        @Html.Partial("EditorSingle", item)
    </tr>
    }
</table>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

Row (partial) View:

@model Mvc4TestApp.Models.PersonModel
@using (Ajax.BeginForm("Edit", new AjaxOptions() { InsertionMode = InsertionMode.Replace, UpdateTargetId = string.Format("Person-{0}", Model.Id) }))
{
    <td>@Html.EditorFor(x => x.FirstName)</td>
    <td>@Html.EditorFor(x => x.LastName)</td>
    <td>
        <input type="submit" value="OK" />
        @Html.HiddenFor(x => x.Id)
    </td>
}

Here a controller:

public class PeopleController : Controller
{
    public ActionResult Index()
    {
        return View(new PeopleGroup()
        {
            Name = "Presidents",
            People = GetPeople()
        });
    }

    public ActionResult Edit(PersonModel model)
    {
        if (ModelState.IsValid)
        {
            var people = GetPeople();
            var original = people.Where(x => x.Id == model.Id).SingleOrDefault();
            if (original != null)
                people.Remove(original);
            people.Add(model);
        }
        return PartialView("EditorSingle", model);
    }

    public ICollection<PersonModel> GetPeople()
    {
        ICollection<PersonModel> collection = Session["people"] as ICollection<PersonModel>;
        if (collection == null)
        {
            collection = new List<PersonModel>() {
                new PersonModel() { Id = 0, FirstName = "George", LastName = "Washington"},
                new PersonModel() { Id = 1, FirstName = "Abraham", LastName = "Lincoln"},
                new PersonModel() { Id = 2, FirstName = "Thomas", LastName = "Jefferson"}
            };
            Session["people"] = collection;
        }
        return collection;
    }
}

I tested the whole thing as a list (table -> ul, tr -> li, td -> div) that works, no problem! But as a table it only works with the first submit. As soon as I submit that same row again, nothing happens. I debugged it, and the problem seems, that there is just no form submit event thrown for the form that came through ajax. I'm pretty confident this has nothing todo with asp mvc. I'd say it must be an issue with placing a form directly into a tr.

Has anyone had this issue before? Do you know of any workarounds?

Thanks!

Sam7
  • 3,382
  • 2
  • 34
  • 57

1 Answers1

0

I'd say it must be an issue with placing a form directly into a tr

Yeap, it's exactly that. You need a nested table:

@model Mvc4TestApp.Models.PersonModel
<td colspan="3">
    @using (Ajax.BeginForm("Edit", new AjaxOptions() { InsertionMode = InsertionMode.Replace, UpdateTargetId = string.Format("Person-{0}", Model.Id) }))
    {
        <table>
            <tr>
                <td>@Html.EditorFor(x => x.FirstName)</td>
                <td>@Html.EditorFor(x => x.LastName)</td>
                <td>
                    <input type="submit" value="OK" />
                    @Html.HiddenFor(x => x.Id)
                </td>
            </tr>
        </table>
    }
</td>
Community
  • 1
  • 1
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • Thanks, but that will void the use of the table, since the purpose is to align all columns. – Sam7 Jun 04 '13 at 10:27