I'm developing an ASP.NET MVC 5 web with C# and .NET Framework 4.5.1.
I have this form in a cshtml file:
#model MyProduct.Web.API.Models.ConnectBatchProductViewModel
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Create</title>
</head>
<body>
#if (#Model != null)
{
<h4>Producto: #Model.Product.ProductCode, Cantidad: #Model.ExternalCodesForThisProduct</h4>
using (Html.BeginForm("Save", "ConnectBatchProduct", FormMethod.Post))
{
#Html.HiddenFor(model => model.Product.Id, new { #id = "productId", #Name = "productId" });
<div>
<table id ="batchTable" class="order-list">
<thead>
<tr>
<td>Cantidad</td>
<td>Lote</td>
</tr>
</thead>
<tbody>
<tr>
<td>#Html.TextBox("ConnectBatchProductViewModel.BatchProducts[0].Quantity")</td>
<td>#Html.TextBox("ConnectBatchProductViewModel.BatchProducts[0].BatchName")</td>
<td><a class="deleteRow"></a></td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="5" style="text-align: left;">
<input type="button" id="addrow" value="Add Row" />
</td>
</tr>
</tfoot>
</table>
</div>
<p><input type="submit" value="Seleccionar" /></p>
}
}
else
{
<div>Error.</div>
}
<script src="~/Scripts/jquery-2.1.3.min.js"></script>
<script src="~/js/createBatches.js"></script> <!-- Resource jQuery -->
</body>
</html>
And this is the action method:
[HttpPost]
public ActionResult Save(FormCollection form)
{
return null;
}
And the two ViewModel:
public class BatchProductViewModel
{
public int Quantity { get; set; }
public string BatchName { get; set; }
}
public class ConnectBatchProductViewModel
{
public Models.Products Product { get; set; }
public int ExternalCodesForThisProduct { get; set; }
public IEnumerable<BatchProductViewModel> BatchProducts { get; set; }
}
But I get this in FormCollection form var:
But I want to get an IEnumerable<BatchProductViewModel> model:
public ActionResult Save(int productId, IEnumerable<BatchProductViewModel> model);
If I use the above method signature both parameters are null.
I want an IEnumerable because user is going to add more rows dynamically using jQuery.
This is jQuery script:
jQuery(document).ready(function ($) {
var counter = 0;
$("#addrow").on("click", function () {
counter = $('#batchTable tr').length - 2;
var newRow = $("<tr>");
var cols = "";
var quantity = 'ConnectBatchProductViewModel.BatchProducts[0].Quantity'.replace(/\[.{1}\]/, '[' + counter + ']');
var batchName = 'ConnectBatchProductViewModel.BatchProducts[0].BatchName'.replace(/\[.{1}\]/, '[' + counter + ']');
cols += '<td><input type="text" name="' + quantity + '"/></td>';
cols += '<td><input type="text" name="' + batchName + '"/></td>';
cols += '<td><input type="button" class="ibtnDel" value="Delete"></td>';
newRow.append(cols);
$("table.order-list").append(newRow);
counter++;
});
$("table.order-list").on("click", ".ibtnDel", function (event) {
$(this).closest("tr").remove();
counter -= 1
$('#addrow').attr('disabled', false).prop('value', "Add Row");
});
});
Any idea?
I have checked this SO answer, and this article but I don't get my code working.
You need to generate the controls for the collection in a for loop so they are correctly named with indexers (note that property BatchProducts needs to be IList<BatchProductViewModel>
#using (Html.BeginForm("Save", "ConnectBatchProduct", FormMethod.Post))
{
....
<table>
....
#for(int i = 0; i < Model.BatchProducts.Count; i++)
{
<tr>
<td>#Html.TextBoxFor(m => m.BatchProducts[i].Quantity)</td>
<td>#Html.TextBoxFor(m => m.BatchProducts[i].BatchName)</td>
<td>
// add the following to allow for dynamically deleting items in the view
<input type="hidden" name="BatchProducts.Index" value="#i" />
<a class="deleteRow"></a>
</td>
</tr>
}
....
</table>
....
}
Then the POST method needs to be
public ActionResult Save(ConnectBatchProductViewModel model)
{
....
}
Edit
Note: Further to your edit, if you want to dynamically add and remove BatchProductViewModel items in he view, you will need to use the BeginCollectionItem helper or a html template as discussed in this answer
The template to dynamically add new items would be
<div id="NewBatchProduct" style="display:none">
<tr>
<td><input type="text" name="BatchProducts[#].Quantity" value /></td>
<td><input type="text" name="BatchProducts[#].BatchName" value /></td>
<td>
<input type="hidden" name="BatchProducts.Index" value ="%"/>
<a class="deleteRow"></a>
</td>
</tr>
</div>
Note the dummy indexers and the non-matching value for the hidden input prevents this template posting back.
Then the script to add a new BatchProducts would be
$("#addrow").click(function() {
var index = (new Date()).getTime(); // unique indexer
var clone = $('#NewBatchProduct').clone(); // clone the BatchProducts item
// Update the index of the clone
clone.html($(clone).html().replace(/\[#\]/g, '[' + index + ']'));
clone.html($(clone).html().replace(/"%"/g, '"' + index + '"'));
$("table.order-list").append(clone.html());
});
In your Post Methode you receive "MyProduct.Web.API.Models.ConnectBatchProductViewModel" as Parameter.
Use the existing model for the Post methode.
Why do you want a IEnumerable from your model? there is only one available including the id in the model.
you can visit this article for complete source code with a video tutorial.
you have to create an action first, from where we can pass the list of object
[HttpGet]
public ActionResult Index()
{
List<Contact> model = new List<Contact>();
using (MyDatabaseEntities dc = new MyDatabaseEntities())
{
model = dc.Contacts.ToList();
}
return View(model);
}
then we need to create a view for that action
#model List<UpdateMultiRecord.Contact>
#{
ViewBag.Title = "Update multiple row at once Using MVC 4 and EF ";
}
#using (#Html.BeginForm("Index","Home", FormMethod.Post))
{
<table>
<tr>
<th></th>
<th>Contact Person</th>
<th>Contact No</th>
<th>Email ID</th>
</tr>
#for (int i = 0; i < Model.Count; i++)
{
<tr>
<td> #Html.HiddenFor(model => model[i].ContactID)</td>
<td>#Html.EditorFor(model => model[i].ContactPerson)</td>
<td>#Html.EditorFor(model => model[i].Contactno)</td>
<td>#Html.EditorFor(model => model[i].EmailID)</td>
</tr>
}
</table>
<p><input type="submit" value="Save" /></p>
<p style="color:green; font-size:12px;">
#ViewBag.Message
</p>
}
#section Scripts{
#Scripts.Render("~/bundles/jqueryval")
}
and then we have to write code for save the list of object to the database
[HttpPost]
public ActionResult Index(List<Contact> list)
{
if (ModelState.IsValid)
{
using (MyDatabaseEntities dc = new MyDatabaseEntities())
{
foreach (var i in list)
{
var c = dc.Contacts.Where(a =>a.ContactID.Equals(i.ContactID)).FirstOrDefault();
if (c != null)
{
c.ContactPerson = i.ContactPerson;
c.Contactno = i.Contactno;
c.EmailID = i.EmailID;
}
}
dc.SaveChanges();
}
ViewBag.Message = "Successfully Updated.";
return View(list);
}
else
{
ViewBag.Message = "Failed ! Please try again.";
return View(list);
}
}
using(Html.BeginForm())
{
// code here
}
While to Post form Data all tags must be included form tag.
Following the principle of DRY, you can create one EditorTemplate for that purpose.
Steps:
1- In Views > Shared > Create new folder named (EditorTemplates)
2- Create a view inside your newly created EditorTemplates folder , the view's model should be BatchProductViewModel according to the OP example. Place your code inside the Editor view. No loop or index is required.
An EditorTemplate will act similar to a PartialView for every child entity but in a more generic way.
3- In your parent entity's view, call your Editor :
#Html.EditorFor(m => m.BatchProducts)
Not only this provides a more organized views, but also let's you re-use the same editor in other views as well.
Related
I have a form in which a user can supply an arbitrary-length list of <DateTime, int> pairs. It is represented like so:
List<ItemsPerDay> ItemsPerDayList = new List<ItemsPerDay>();
public class ItemsPerDay {
public DateTime Date { get; set; }
public int Amount { get; set; }
}
<tbody>
#{ var i = 0; }
#foreach (var _ in Model.ItemsPerDayList) {
<tr>
<td><input asp-for="ItemsPerDayList[i].Date" type="date" /></td>
<td><input asp-for="ItemsPerDayList[i].Amount" /></td>
<td><a class="remove">Remove</a></td>
</tr>
i++;
}
</tbody>
The issue:
The user is able to add/remove rows as they need. However, the property binding relies on the pairs being properly indexed. If, for example, you remove the first item, the list now begins at [1] and the property binding does not work; ItemsPerDayList is posted as null.
My current workaround:
I've had to use some JavaScript to make sure the indexes always remain correct. This works but isn't optimal.
function reIndexItemRows() {
$("table > tbody > tr").each(function(idx) {
$(this).find("input[type=date]").attr({
"data-val": true,
"data-val-required": "The Date field is required.",
id: `ItemsPerDayList_${idx}__Date`,
name: `ItemsPerDayList[${idx}].Date`
});
$(this).find("input[type=number]").attr({
"data-val": true,
"data-val-required": "The Amount field is required.",
id: `ItemsPerDayList_${idx}__Amount`,
name: `ItemsPerDayList[${idx}].Amount`
});
});
}
The question:
What is the appropriate way to represent this model on the front-end, such that I don't have to rely on JavaScript to groom the form each time a row is added or removed?
NOTE: I am not doing any updates, therefore the indexes are not necessary. Upon submission, any existing pairs are deleted, and the form-submitted pairs are inserted.
JavaScript is necessary for adjusting index. You can add events to adjust the index when submitting the form.
Add a event on Remove. Here is the form.
<form method="post" id="myform">
<table>
<tbody>
#{ var i = 0; }
#foreach (var _ in Model.ItemsPerDayList)
{
<tr>
<td><input asp-for="ItemsPerDayList[i].Date" type="date" /></td>
<td><input asp-for="ItemsPerDayList[i].Amount" /></td>
<td><a class="remove" onclick="remove(this)" >Remove</a></td>
</tr>
i++;
}
</tbody>
</table>
<input type="submit" name="name" value="submit" />
</form>
<button id="add" onclick="add()" class="btn-primary">add</button>
Before submitting the form, javascript iterates each row and modify the index.
#section Scripts{
<script>
$('#myform').submit(function () {
var i = 0;
$("tbody> tr ").each(function () {
$(this).find("td input[name$='Date']").attr("name", "ItemsPerDayList[" + i + "].Date");
$(this).find("td input[name$='Amount']").attr("name", "ItemsPerDayList[" + i + "].Amount");
i++
})
// ...
return true; // return false to cancel form action
});
function remove(e) {
$(e).parent().parent().remove()
}
function add() {
$('tbody').append('<tr><td> <input name="ItemsPerDayList[i].Date" type="date" /></td ><td><input name="ItemsPerDayList[i].Amount" /><td><a class="remove" onclick="remove(this)">Remove</a></td></tr>');
}
</script>
}
Then, I can get the all data from front-end.
I'm developing an ASP.NET MVC 5 web with C# and .NET Framework 4.5.1.
I have this form in a cshtml file:
#model MyProduct.Web.API.Models.ConnectBatchProductViewModel
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Create</title>
</head>
<body>
#if (#Model != null)
{
<h4>Producto: #Model.Product.ProductCode, Cantidad: #Model.ExternalCodesForThisProduct</h4>
using (Html.BeginForm("Save", "ConnectBatchProduct", FormMethod.Post))
{
#Html.HiddenFor(model => model.Product.Id, new { #id = "productId", #Name = "productId" });
<div>
<table id ="batchTable" class="order-list">
<thead>
<tr>
<td>Cantidad</td>
<td>Lote</td>
</tr>
</thead>
<tbody>
<tr>
<td>#Html.TextBox("ConnectBatchProductViewModel.BatchProducts[0].Quantity")</td>
<td>#Html.TextBox("ConnectBatchProductViewModel.BatchProducts[0].BatchName")</td>
<td><a class="deleteRow"></a></td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="5" style="text-align: left;">
<input type="button" id="addrow" value="Add Row" />
</td>
</tr>
</tfoot>
</table>
</div>
<p><input type="submit" value="Seleccionar" /></p>
}
}
else
{
<div>Error.</div>
}
<script src="~/Scripts/jquery-2.1.3.min.js"></script>
<script src="~/js/createBatches.js"></script> <!-- Resource jQuery -->
</body>
</html>
And this is the action method:
[HttpPost]
public ActionResult Save(FormCollection form)
{
return null;
}
And the two ViewModel:
public class BatchProductViewModel
{
public int Quantity { get; set; }
public string BatchName { get; set; }
}
public class ConnectBatchProductViewModel
{
public Models.Products Product { get; set; }
public int ExternalCodesForThisProduct { get; set; }
public IEnumerable<BatchProductViewModel> BatchProducts { get; set; }
}
But I get this in FormCollection form var:
But I want to get an IEnumerable<BatchProductViewModel> model:
public ActionResult Save(int productId, IEnumerable<BatchProductViewModel> model);
If I use the above method signature both parameters are null.
I want an IEnumerable because user is going to add more rows dynamically using jQuery.
This is jQuery script:
jQuery(document).ready(function ($) {
var counter = 0;
$("#addrow").on("click", function () {
counter = $('#batchTable tr').length - 2;
var newRow = $("<tr>");
var cols = "";
var quantity = 'ConnectBatchProductViewModel.BatchProducts[0].Quantity'.replace(/\[.{1}\]/, '[' + counter + ']');
var batchName = 'ConnectBatchProductViewModel.BatchProducts[0].BatchName'.replace(/\[.{1}\]/, '[' + counter + ']');
cols += '<td><input type="text" name="' + quantity + '"/></td>';
cols += '<td><input type="text" name="' + batchName + '"/></td>';
cols += '<td><input type="button" class="ibtnDel" value="Delete"></td>';
newRow.append(cols);
$("table.order-list").append(newRow);
counter++;
});
$("table.order-list").on("click", ".ibtnDel", function (event) {
$(this).closest("tr").remove();
counter -= 1
$('#addrow').attr('disabled', false).prop('value', "Add Row");
});
});
Any idea?
I have checked this SO answer, and this article but I don't get my code working.
You need to generate the controls for the collection in a for loop so they are correctly named with indexers (note that property BatchProducts needs to be IList<BatchProductViewModel>
#using (Html.BeginForm("Save", "ConnectBatchProduct", FormMethod.Post))
{
....
<table>
....
#for(int i = 0; i < Model.BatchProducts.Count; i++)
{
<tr>
<td>#Html.TextBoxFor(m => m.BatchProducts[i].Quantity)</td>
<td>#Html.TextBoxFor(m => m.BatchProducts[i].BatchName)</td>
<td>
// add the following to allow for dynamically deleting items in the view
<input type="hidden" name="BatchProducts.Index" value="#i" />
<a class="deleteRow"></a>
</td>
</tr>
}
....
</table>
....
}
Then the POST method needs to be
public ActionResult Save(ConnectBatchProductViewModel model)
{
....
}
Edit
Note: Further to your edit, if you want to dynamically add and remove BatchProductViewModel items in he view, you will need to use the BeginCollectionItem helper or a html template as discussed in this answer
The template to dynamically add new items would be
<div id="NewBatchProduct" style="display:none">
<tr>
<td><input type="text" name="BatchProducts[#].Quantity" value /></td>
<td><input type="text" name="BatchProducts[#].BatchName" value /></td>
<td>
<input type="hidden" name="BatchProducts.Index" value ="%"/>
<a class="deleteRow"></a>
</td>
</tr>
</div>
Note the dummy indexers and the non-matching value for the hidden input prevents this template posting back.
Then the script to add a new BatchProducts would be
$("#addrow").click(function() {
var index = (new Date()).getTime(); // unique indexer
var clone = $('#NewBatchProduct').clone(); // clone the BatchProducts item
// Update the index of the clone
clone.html($(clone).html().replace(/\[#\]/g, '[' + index + ']'));
clone.html($(clone).html().replace(/"%"/g, '"' + index + '"'));
$("table.order-list").append(clone.html());
});
In your Post Methode you receive "MyProduct.Web.API.Models.ConnectBatchProductViewModel" as Parameter.
Use the existing model for the Post methode.
Why do you want a IEnumerable from your model? there is only one available including the id in the model.
you can visit this article for complete source code with a video tutorial.
you have to create an action first, from where we can pass the list of object
[HttpGet]
public ActionResult Index()
{
List<Contact> model = new List<Contact>();
using (MyDatabaseEntities dc = new MyDatabaseEntities())
{
model = dc.Contacts.ToList();
}
return View(model);
}
then we need to create a view for that action
#model List<UpdateMultiRecord.Contact>
#{
ViewBag.Title = "Update multiple row at once Using MVC 4 and EF ";
}
#using (#Html.BeginForm("Index","Home", FormMethod.Post))
{
<table>
<tr>
<th></th>
<th>Contact Person</th>
<th>Contact No</th>
<th>Email ID</th>
</tr>
#for (int i = 0; i < Model.Count; i++)
{
<tr>
<td> #Html.HiddenFor(model => model[i].ContactID)</td>
<td>#Html.EditorFor(model => model[i].ContactPerson)</td>
<td>#Html.EditorFor(model => model[i].Contactno)</td>
<td>#Html.EditorFor(model => model[i].EmailID)</td>
</tr>
}
</table>
<p><input type="submit" value="Save" /></p>
<p style="color:green; font-size:12px;">
#ViewBag.Message
</p>
}
#section Scripts{
#Scripts.Render("~/bundles/jqueryval")
}
and then we have to write code for save the list of object to the database
[HttpPost]
public ActionResult Index(List<Contact> list)
{
if (ModelState.IsValid)
{
using (MyDatabaseEntities dc = new MyDatabaseEntities())
{
foreach (var i in list)
{
var c = dc.Contacts.Where(a =>a.ContactID.Equals(i.ContactID)).FirstOrDefault();
if (c != null)
{
c.ContactPerson = i.ContactPerson;
c.Contactno = i.Contactno;
c.EmailID = i.EmailID;
}
}
dc.SaveChanges();
}
ViewBag.Message = "Successfully Updated.";
return View(list);
}
else
{
ViewBag.Message = "Failed ! Please try again.";
return View(list);
}
}
using(Html.BeginForm())
{
// code here
}
While to Post form Data all tags must be included form tag.
Following the principle of DRY, you can create one EditorTemplate for that purpose.
Steps:
1- In Views > Shared > Create new folder named (EditorTemplates)
2- Create a view inside your newly created EditorTemplates folder , the view's model should be BatchProductViewModel according to the OP example. Place your code inside the Editor view. No loop or index is required.
An EditorTemplate will act similar to a PartialView for every child entity but in a more generic way.
3- In your parent entity's view, call your Editor :
#Html.EditorFor(m => m.BatchProducts)
Not only this provides a more organized views, but also let's you re-use the same editor in other views as well.
I got this error when I am trying to remove the item from the Cart table.
HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /Panier/RemoveFromCart/1. This URL seems to be fine with me. It should branch to the PanierController at RemoveCart. I don't understand why it is not branching.
Thanks
Index.cshtml
#model Tp1WebStore3.ViewModels.ShoppingCartViewModel
#{
ViewBag.Title = "Shopping Cart";
}
<script src="/Scripts/jquery-1.4.4.min.js"
type="text/javascript"></script>
<script type="text/javascript">
$(function () {
// Document.ready -> link up remove event handler
$(".RemoveLink").click(function () {
// Get the id from the link
var recordToDelete = $(this).attr("data-id");
if (recordToDelete != '') {
// Perform the ajax post
$.post("/ShoppingCart/RemoveFromCart", {"id": recordToDelete },
function (data) {
// Successful requests get here
// Update the page elements
if (data.ItemCount == 0) {
$('#row-' + data.DeleteId).fadeOut('slow');
} else {
$('#item-count-' + data.DeleteId).text(data.ItemCount);
}
$('#cart-total').text(data.CartTotal);
$('#update-message').text(data.Message);
$('#cart-status').text('Cart (' + data.CartCount + ')');
});
}
});
});
</script>
<h3>
<em>Details</em> du panier:
</h3>
<p class="button">
#Html.ActionLink("Checkout >>", "AddressAndPayment", "Checkout")
</p>
<div id="update-message">
</div>
<table>
<tr>
<th>
Produit
</th>
<th>
Prix (unitaire)
</th>
<th>
Quantite
</th>
<th></th>
</tr>
#foreach (var item in Model.CartItems)
{
<tr id="row-#item.ProduitId">
<td>
#Html.ActionLink(item.Produit.Description,"Details", "Store", new { id =
item.ProduitId }, null)
</td>
<td>
#item.Produit.Prix
</td>
<td id="item-count-#item.ProduitId">
#item.Quantite
</td>
<td>
#Html.ActionLink("Enlever du panier", "RemoveFromCart", "Panier", new { id =
item.ProduitId }, null)
</td>
</tr>
}
<tr>
<td>
Total
</td>
<td></td>
<td></td>
<td id="cart-total">
#Model.CartTotal
</td>
</tr>
</table>
PanierController.cs
namespace Tp1WebStore3.Controllers
{
public class PanierController : Controller
{
Tp1WebStoreDBEntities dbProduit = new Tp1WebStoreDBEntities();
[HttpPost]
public ActionResult RemoveFromCart(int id)
{
// Remove the item from the cart
var cart = ShoppingCart.GetCart(this.HttpContext);
// Get the name of the product to display confirmation
string produitDescription = dbProduit.Paniers
.Single(item => item.PanierId == id).Produit.Description;
// Remove from cart
int itemCount = cart.RemoveFromCart(id);
// Display the confirmation message
var results = new ShoppingCartRemoveViewModel
{
Message = Server.HtmlEncode(produitDescription) +
" has been removed from your shopping cart.",
CartTotal = cart.GetTotal(),
CartCount = cart.GetCount(),
ItemCount = itemCount,
DeleteId = id
};
return View("Details");
}
Your RemoveFromCart controller action is decorated with the [HttpPost] attribute meaning that it is ONLY accessible by POST verbs. But in your view you seem to have generated some action link to it:
#Html.ActionLink(
"Enlever du panier",
"RemoveFromCart",
"Panier",
new { id = item.ProduitId },
null
)
But as you are well aware, an Html.ActionLink translates into an <a> tag in your markup which obviously is sending a GET request to the server when clicked.
So basically you have 3 possibilities here:
Use an Html.BeginForm instead of an ActionLink to refer to this action which would allow you to send a POST request
Get rid of the [HttpPost] attribute from your RemoveFromCart action
AJAXify the anchor which would allow you to use a POST request.
I'm building an MVC app and right now my view generates a pack of items. The user needs to check a checkbox if he wants to send the data.
Here's my view and how it is builded:
<script type="text/javascript">
$(document).ready(function() {
//alert("The document is ready");
$("#selectAll").click(function() {
//alert("The case has been clicked");
var chkValue = $(this).is(":checked");
$(".divChckBox").prop("checked", chkValue);
});
});
</script>
<p>
#using (Html.BeginForm("SendObj", "Manager"))
{
<p>
Select / UnSelet All Items #Html.CheckBox("selectAll", true)
</p>
<table>
<tr>
<th>Card Name</th>
<th>Number In Stock</th>
(...)
</tr>
#for (int i = 0; i < Model.Count(); i++)
{
<tr>
<td>#Html.DisplayFor(x => x[i].m_OthObj.m_ObjName)</td>
<td>#Html.DisplayFor(x => x[i].m_NbInStock)#Html.HiddenFor(x => x[i].m_NbInStock)</td>
(...)
<td>
<input type="checkbox" name="itdoesnotmatter" class="divChckBox" checked="true"/>
</td>
</tr>
}
</table>
<input type="submit" value="Send"/>
}
</p>
So you understand why I cannot use "CheckboxFor". Now what I want to do is send only the items which checkbox status is "checked". I know how to do this via model binding (checkboxfor), but I'm clueless as to how to build this.
I need to return a list of items. So how could I do this? Thank you very much!
Your form will return the values based on name, so shoot whoever told you such a stupid name :)
Use
<input type="checkbox" name="InStock" class="divChckBox" checked="true" value="#Model[i].ID" />
Or something more representative. Note that it is CRITICAL that you supply a unique identifier as the value of your checkbox. The value is how you will identify what was checked!
In your controller, there's several ways you can capture it. I do it like this:
public ActionResult Create(List<int> InStock)
{
foreach(var inStockItem in InStock)
{
//do what you need to do
}
}
The important points:
List<int> InStock
This must match the NAME attribute on your checkbox. The actual values will be the Value of your checkboxes.
Here I just randomly selected Create for your Action, but you need to make it match whatever action you are in (Edit, Index, etc..)
Good Luck!
try using the attr method to change the property checked.
$(document).ready(function() {
$("#selectAll").click(function() {
var chkValue = $(this).is(":checked");
$(".divChckBox").attr("checked", chkValue);
});
});
View code:
<!-- note "x[i].m_id"; Use the entity's id property is here
...maybe this should be m_NbInStock? -->
<input type="checkbox" name="selectedItems" value="#x[i].m_id" class="divChckBox" checked="true"/>
Controller code:
public class Manager : Controller
{
/* ... */
[HttpPost]
public ActionResult SendObj(IList<Int32> selectedItems)
{
// Grab those items by their IDs found within `selectedItems` and perform
// any processing necessary
// ...
//return View();
}
/* ... */
}
I'm stuck trying to wrap my head around how to make a page like this work. My model contains a list of objects which have text fields for different languages. There's a spot in the view that needs to be dynamically changed to display the text fields associated to the language selected in a drop-down list. The text fields also need to be editable such that when the parent form is submitted, the text fields need to save correctly in the parent model after being edited in the partial view/model. I was hinted in another page that partial views is what I should try to do, maybe something about programmatically generating partial views for each language in the list, and doing something to update/render the correct partial view based on the selection in the drop down list...?
My initial attempt led me to try using ajax calls to the controller to return the correct partial view based on the value of the drop down menu, but I can't bind it to the model, and hence can't update/save it when the main view form is submitted. Here's what I've been working with so far:
Model:
public class EditModel
{
public List<TextField> TextFieldList;
public List<string> DisplayList
{
get
{
List<string> tempList = new List<string>();
foreach (TextField a in TextFieldList)
{
tempList.Add(a.Language.ToString() + "/" + a.Currency.ToString());
}
return tempList;
}
}
}
Controller:
public ActionResult EditTextFields(int adId, int index)
{
Ad ad = this.Repository.GetById(adId);
return PartialView("EditTextFields", ad.TextFieldsList[index]);
}
Main View:
#model Models.EditModel
<script type="text/javascript">
$(function () {
$(href('DisplayList').change(function () {
var value = $(this).find(':selected').val();
var adId = GetId();
$.get('/Controllers/EditTextFields', "{\"adId\": " + String(adId) + ", \"index\":\"" + value + "\"}", function (data) {
$('#TextFieldDiv').html(data);
});
}));
});
</script>
#using (Html.BeginForm("Edit", "Widget", FormMethod.Post, new { id = "WidgetEditForm", enctype = "multipart/form-data" }))
{
<div>
#Html.DisplayFor(m => m.DisplayList)
</div>
<div id="TextFieldDiv">
#{Html.RenderPartial("EditTextFields", (TextField)#Model.TextFieldList[0]);}
</div>
}
Partial View:
#model Objects.TextField
#using (Html.BeginForm())
{
<table>
<tr>
<td class="fieldName" style="vertical-align: top;">
Headline Text:
</td>
<td>
#Html.EditorFor(m => m.Headline)
#Html.ValidationMessageFor(m => m.Headline)
</td>
</tr>
<tr>
<td class="fieldName">
Sub-Headline Text:
</td>
<td>
#Html.EditorFor(m => m.SubHeadline)
#Html.ValidationMessageFor(m => m.SubHeadline)
</td>
</tr>
</table>
}
Ideas to point me in a good direction?