Richard Clarke
Richard Clarke

Reputation: 33

jQuery Form plugin ASP.NET MVC 3 handling PartialView

I am writing a ASP.NET MVC page for adding products. The page will display the form with an Add button and also the list of products. When the user clicks Add, I want the new product added to the list, and the form reset. I am trying to do this using the jQuery form plugin and without using Ajax.BeginForm etc. I have put the list of products into a partial view.

The Product class is as follows:

public class Product
{
    public int Id { get; set; }
    public string Description { get; set; }
    public decimal Price { get; set; }
}

I am using a viewmodel:

public class ProductViewModel
{
    public ProductViewModel()
    {
    }

    public ProductViewModel(AjaxDataEntryContext db)
    {
        Products = db.Products.ToList();
        NewProduct = new Product();
    }
    public List<Product> Products { get; set;}
    public Product NewProduct { get; set;}
}

The controller does this:

public class ProductController : Controller
{
    private AjaxDataEntryContext db = new AjaxDataEntryContext();

    [HttpGet]
    public ViewResult AjaxForm()
    {
        return View(new ProductViewModel(db));
    }

    [HttpPost]
    public ActionResult AjaxForm(ProductViewModel viewModel)
    {
        db.Products.Add(viewModel.NewProduct);
        db.SaveChanges();
        return PartialView("_ProductList", db.Products.ToList());
    }
}

My cshtml is as follows:

@model AjaxDataEntry.ViewModels.ProductViewModel
@{
    ViewBag.Title = "Index";
}
@Html.Partial("_ProductList", Model.Products)
@using (Html.BeginForm("AjaxForm", "Product", null, FormMethod.Post, new { id = "myForm1" }))
{
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Product</legend>
        <div class="editor-label">
            @Html.LabelFor(model => model.NewProduct.Description)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.NewProduct.Description)
            @Html.ValidationMessageFor(model => model.NewProduct.Description)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.NewProduct.Price)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.NewProduct.Price)
            @Html.ValidationMessageFor(model => model.NewProduct.Price)
        </div>
        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}

<script type="text/javascript">
    $(document).ready(function () {
        var options = {
            target: '#producttable',   // target element(s) to be updated with server response 
            beforeSubmit: showRequest,  // pre-submit callback 
            success:       showResponse,  // post-submit callback 
            replaceTarget: true,
            dataType:  html,        // 'xml', 'script', or 'json' (expected server response type) 
            clearForm: true        // clear all form fields after successful submit 
        };

        // bind form using 'ajaxForm' 
        $('#myForm1').ajaxForm(options);
    });

    // pre-submit callback 
    function showRequest(formData, jqForm, options) {
        var queryString = $.param(formData);
        alert('About to submit: \n\n' + queryString);
        return true;
    }

    // post-submit callback 
    function showResponse(responseText, statusText, xhr, $form) {
        alert('status: ' + statusText + '\n\nresponseText: \n' + responseText +
        '\n\nThe output div should have already been updated with the responseText.');
    }
</script>

And finally the _ProductList partial as referenced in the above page (and the Controller):

@model IEnumerable<AjaxDataEntry.Models.Product>
<div id="producttable">
    <table>
        <tr>
            <th>
                Description
            </th>
            <th>
                Price
            </th>
            <th>
            </th>
        </tr>
        @foreach (var item in Model)
        {
            <tr>
                <td>
                    @Html.DisplayFor(modelItem => item.Description)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Price)
                </td>
                <td>
                    @Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
                    @Html.ActionLink("Details", "Details", new { id = item.Id }) |
                    @Html.ActionLink("Delete", "Delete", new { id = item.Id })
                </td>
            </tr>
        }
    </table>
</div>

My problem is that when i click Add, the product is added correctly, I see the showRequest message, but when the screen refreshes, all I see is the list i.e. the partial, not the full view. I also don't see the showResponse message.

Anybody know what I'm doing wrong?

Upvotes: 0

Views: 561

Answers (1)

JoelH
JoelH

Reputation: 25

ShowResponse is not called because you are submitting the whole page, instead of using Html.BeginForm(..., you should use Ajax.BeginForm(....

Upvotes: 0

Related Questions