0

I have a sort of Master-Detail Edit form and I'm trying to follow this post: Using Ajax... to get the partial view to postback.

My Edit form has a partial view that has a list of sub items, and another partial create view in it to add new items. I'd like the partial create view to post back and update the list without refreshing the whole page if possible.

Here's what I have so far:

MyController.cs -

public ActionResult Edit(int? id)
{
    //...
    ViewBag.CustomFormId = id;
    using (var _db = new MkpContext())
    {
        //...
        return View(profileEdit);
    }
}

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(CustomForm editForm)
{
    //...
    if (!ModelState.IsValid) return View(editForm);
    using (var _db = new MkpContext())
    {
        var form = _db.CustomForms.Find(editForm.CustomFormId);
        //...
        _db.Entry(form).State = EntityState.Modified;
        _db.SaveChanges(User.ProfileId);
        return RedirectToAction("Index");
    }
}

public ActionResult _CustomFieldList(int id)
{
    ViewBag.CustomFormId = id;
    using (var _db = new MkpContext())
    {
        var formCustomFields = (from cf in _db.CustomFields
                                where cf.CustomFormId == id
                                select cf);
        return PartialView(formCustomFields.ToList());
    }
}

// Nested in _CustomFieldList
public ActionResult _CustomFieldCreate(int id)
{
    var newField = new CustomField
    {
        CustomFormId = id
    };
    return PartialView(newField);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult _CustomFieldCreate(CustomField addField)
{
    ViewBag.CustomFormId = addField.CustomFormId;
    if (ModelState.IsValid)
    {
        using (var _db = new MkpContext())
        {
            _db.CustomFields.Add(addField);
            _db.SaveChanges();
        }

        var newField = new CustomField
        {
            CustomFormId = addField.CustomFormId
        };
        return PartialView(newField); // Probably need to change this somehow
    }
    return PartialView(addField);
}

And the views:

Edit.cshtml -

@model PublicationSystem.Model.CustomForm
@{
    ViewBag.Title = "Edit Custom Form";
    Layout = "~/Views/Shared/_LayoutSmBanner.cshtml";
}
    <div class="form-horizontal">
        <div class="row">
        @using (Html.BeginForm())
        {
            @Html.AntiForgeryToken()
            @* Fields for this form *@
        }
        <div id="CustomFields" class="col-md-6">
            @Html.Action("_CustomFieldCreate", new { id = ViewBag.CustomFormId })
        </div>
    </div>
</div>

<script>
$(function () {
    $("#createFieldForm").on("submit", function (e) {
        e.preventDefault(); //This prevent the regular form submit
        $.ajax({
                url: this.action,
                type: this.method,
                data: $(this).serialize(),
                success: function (result) {
                    $("#CustomFields").html(result);
                }
            });
        return false;
    });
});
</script>

_CustomFieldCreate.cshtml -

@model PublicationSystem.Model.CustomField
@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()
    <div id="result"></div>
    <div class="form-horizontal">
        <h4>CustomField</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        @Html.HiddenFor(model =>model.CustomFormId)

    <div class="row">
        @* Fields for the form *@
    </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div id="customFieldList">
    @Html.Action("_CustomFieldList", new { id = ViewBag.CustomFormId })
</div>

_CustomFieldList.cshtml

@model System.Collections.Generic.IEnumerable<PublicationSystem.Model.CustomField>
<table class="table">
    @* List table code *@
</table>

Edit: I rewrote the pages so that the list is part of the create partial view. What happens now is, if you enter data for _CustomFieldCreate and press submit, the first time, it refreshes just that view (including the nested list view). However the second time, it redirects to the view, probably because the first refresh didn't rebind the javascript to the submit button. Also, the Create view doesn't clear out the fields, but persists the originally entered data.

Community
  • 1
  • 1
M Kenyon II
  • 4,136
  • 4
  • 46
  • 94

2 Answers2

0

You will need a form in your partial view whose submit action binds to a javascript function that posts to your controller.

For example if your form id is MyForm:

 $('#MyForm').on('submit', function (e) {
    e.preventDefault(); //This prevent the regular form submit
    $.ajax({
        url: $(this).action, // This will submit the post to whatever action your form goes to
        type: "POST", // This tells it that it is a post
        data: $(this).serialize(), // This sends the data in the form to the controller
        success: function (data) {
            // do some javascript on success
        },
        error: function (xhr, ajaxOptions, thrownError) {
            // do some javascript on error
        }
    });
});

This javascript overrides the default form submit and does an ajax post to your controller and then returns with success or error where you can do anything you want.

Here is some jquery ajax documentation:

http://api.jquery.com/jquery.ajax/

krilovich
  • 3,475
  • 1
  • 23
  • 33
0

You should look into using AJAX. That should accomplish what I think you are describing. You'll want to create a javascript function that handles the submit event on the form, then post the form data to some create action in your MVC app using AJAX. If you are using jQuery, the library makes it pretty simple. http://api.jquery.com/jquery.ajax/

ryano.mcc13
  • 474
  • 4
  • 10