Reputation: 7490
My mark up has one div
with id= "divGrid"
and one ajax enabled form outside that div
. Form contains two text inputs and one submit button with UpdateTargetId = "divGrid"
. It does update that grid perfectly but add duplicate ajax-enabled form on the page. Why this? How to fix this?
Here is my View:
@model List<EF.Models.Data.Books>
@{
ViewBag.Title = "CodeFirst";
Layout = null;
}
<script src="~/Scripts/jquery-1.8.2.min.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
<div id="divGrid">
@foreach (var item in Model)
{
<table>
<tr>
<td>@item.ID</td>
<td>@item.Name</td>
<td>@item.Price</td>
</tr>
</table>
}
</div>
@using (Ajax.BeginForm(new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "divGrid", InsertionMode = InsertionMode.Replace }))
{
@Html.TextBox("name");
<br />
@Html.TextBox("price");
<input type="submit" value="Insert" />
}
My controller action:
[HttpPost]
public ViewResult CodeFirst(FormCollection form)
{
book.Name = form["name"];
book.Price = Convert.ToDecimal(form["price"]);
context.Books.Add(book);
context.SaveChanges();
result = context.Books.ToList();
return View(result);
}
Interestingly, my rendered mark-up is something like
<div id="divGrid">
<div id="divGrid">
<!-- Data display as expected -->
</div>
<!-- ajax enabled form, that is out side of this in source code -->
</div>
<!-- ajax enabled form, that is out side of this in source code -->
Upvotes: 0
Views: 53
Reputation:
Your CodeFirst()
method is returning the same view you initially rendered and its being inserted inside the <div id="divGrid">
which is why you see the form repeated. You need to return a separate partial view containing only the table. Create a separate child only method to display the initial table
[ChildActionOnly]
public ActionResult BookTable()
{
var model = context.Books; // no need for .ToList()
return PartialView(model);
}
BookTable.cshtml
@model IEnumerable<EF.Models.Data.Books>
@foreach (var item in Model)
{
<table>
<tr>
<td>@item.ID</td>
<td>@item.Name</td>
<td>@item.Price</td>
</tr>
</table>
}
Then create a view model for adding a new book so you can take advantage of MVC features such as strong type binding, client and server side validation etc.
public class BookVM
{
[Required]
public string Name { get; set; }
public decimal Price { get; set; }
}
and you controller methods become
public ActionResult CodeFirst()
{
BookVM model = new BookVM();
return View(model);
}
[HttpPost]
public ViewResult CodeFirst(BookVM model)
{
Book book = new Book(){ Name = model.Name, Price = model.Price };
context.Books.Add(book);
context.SaveChanges();
result = context.Books();
return PartialView("BookTable", result);
}
and change your view to
@model BookVM
....
<div id="divGrid">
@Html.Action("BookTable");
</div>
@using (Ajax.BeginForm(new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "divGrid", InsertionMode = InsertionMode.Replace }))
{
@Html.LabelFor(m => m.Name)
@Html.TextBoxFor(m => m.Name)
@Html.ValidationMessageFor(m => m.Name)
.... // ditto for Price
<input type="submit" value="Insert" />
}
However this means your regenerating the html for the whole table everytime you submit the form. You would get far better performance by just using jquery and ajax to call a method that inserts the book and returns its new ID as json, then dynamically adding a new row to the table based on the returned ID, and the values from the textboxes in the form.
Upvotes: 1