Retrieve checkbox checked values of webgrid in mvc - asp.net-mvc-3

I have a simple WebGrid with a check box column in it. When the user checks a few rows and submits the form, I should retrieve the values of those rows and save those values in the database. How do I retrieve the row values one by one? I'm posting my WebGrid code below:
#grid.GetHtml(tableStyle: "webGrid",
htmlAttributes: new { id = "DataTable" },
headerStyle: "header",
alternatingRowStyle: "alt",
columns: grid.Columns(
grid.Column(header: "Select", style: "centered", format: #<text><input type="checkbox" id="chk" name="chk" title="#item.Id" value="#item.Id"/></text>),
grid.Column("FirstName"),
grid.Column("LastName")))
When the user clicks the submit button, it fires the below action method:
[HttpPost]
public ActionResult Submit()
{
return View();
}

I assume the form posts to the Submit function, and below you can see how to access the checked values, i.e. you use the name of the checkbox as the parameter for the action:
public ActionResult Submit(string[] chk)

Related

Bind my form to a Model

I have a ViewModel which contains a List of my Model, like so:
public class OrderConfirm
{
public ICollection<DayBookQuoteLines> SalesLines { get; set; }
public ICollection<DayBookQuoteLines> LostLines { get; set; }
public string Currency { get; set; }
}
I then use this ViewModel in my View like so:
#model btn_intranet.Areas.DayBook.Models.ViewModels.OrderConfirm
#{
ViewBag.Title = "Daybook - Order Confirmation";
}
<h6>Sales Lines</h6>
<div id="SalesOrders">
#using (Ajax.BeginForm("ConfirmSalesOrder", new AjaxOptions()
{
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "SalesOrders",
OnBegin = "SalesOrderConfirm"
}))
{
#foreach(var item in Model.SalesLines)
{
<p>#item.ItemName</p>
<p>#item.Qty</p>
#* Other Properties *#
}
<input type="submit" value="Submit Sales Order" />
}
</div>
<h6>Lost Lines</h6>
<div id="LostOrders">
#using (Ajax.BeginForm("ConfirmLostOrder", new AjaxOptions()
{
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "LostOrders",
OnBegin = "LostOrderConfirm"
}))
{
#foreach(var item in Model.SalesLines)
{
<p>#item.ItemName</p>
<p>#item.Qty</p>
#* Other Properties *#
}
<input type="submit" value="Submit Lost Order" />
}
</div>
The problem is, in my [HttpPost] actions, both ConfirmSalesOrder and ConfirmLostOrder. The value of my Model passed as a parameter is null:
[HttpPost]
public ActionResult ConfirmSalesOrder(List<DayBookQuoteLines> quoteLines)
{
// Process order...
return PartialView("Sales/_ConfirmSalesOrder");
}
so quoteLines is null. How can I bind the form to my model?
You don't have any input field in your form that will send the values to the server. You are only displaying them. That's why they are null when you submit the form => nothing is sent to the server.
But if inside this form the user is not supposed to modify any of the values all you need to do is to pass an id to the controller action that will allow you to fetch the model from the exact same location from which you fetched it in your GET action that rendered this form.
In this case your action will look like this:
[HttpPost]
public ActionResult ConfirmSalesOrder(int id)
{
List<DayBookQuoteLines> quoteLines = ... fetch them the same way as in your GET action
// Process order...
return PartialView("Sales/_ConfirmSalesOrder");
}
If on the other hand the user is supposed to modify the values in the form you need to provide him with the necessary input fields: things like textboxes, checkboxes, radio buttons, dropdownlists, textereas, ... And in order to generate proper names for those input fields I would recommend you using editor templates instead of writing foreach loops in your views.
UPDATE:
Seems like the user is not supposed to edit the data so there are no corresponding input fields. In this case in order to preserve the model you could during the AJAX request you could replace the Ajax.BeginForm with a normal Html.BeginForm an then manually wire up the AJAX request with jQuery. The advantage of this approach is that now you have far more control and you could for example send the entire model as a JSON request. To do this you could store the model as a javascript encoded variable inside the view:
<script type="text/javascript">
var model = #Html.Raw(Json.Encode(Model));
</script>
and then AJAXify the form:
$('#formId').submit(function() {
$.ajax({
url: this.action,
type: this.method,
contentType: 'application/json',
data: JSON.stringify({ quoteLines: model }),
success: function(result) {
$('#someTargetIdToUpdate').html(result);
}
});
return false;
});

MVC3 WebGrid CheckBox

I'm trying to add a checkbox to a column on a web grid, and I'm finding it hard using Html.CheckBox to get it to render. If I use input type="checkbox" it renders, but I can't seem to save the value in the view model.
I have a rather complex view, which has two webGrids, and you select items in one to move to the other, when moved to grid1, you can check a box against each of the rows if you want. Everything is working, except I can't get the value of the checkbox to save.
The code for my grid that has the checkbox looks like this:
var grid1 = new WebGrid(source: Model.FieldsInTemplate, canSort: false, defaultSort:"FieldName");
#grid1.GetHtml(headerStyle:"gridGroupRow", tableStyle: "gridGroup", rowStyle: "gridRow", alternatingRowStyle: "gridRowAlt", columns: grid1.Columns(
grid1.Column("FieldName", "Field Name"),
grid1.Column(header: "Required", format: #<text><input name="IsRequired" type="checkbox" value="#item.IsRequired" /></text>),
grid1.Column(format: (item) => new HtmlString("<a href='#' id='test' onclick='updateTemplate(false," + item.FieldId.ToString() + ");'>Remove</a>"))
))
So using the above, the grid renders with a checkbox, but on submission the entity is always false. The view uses a viewModel of:
public class TemplateFieldInteractViewModel
{
public IList<MetadataTemplateFieldInstanceDisplayViewModel> FieldsInTemplate
{
get;
set;
}
public IList<MetadataTemplateFieldInstanceDisplayViewModel> FieldsNotInTemplate
{
get;
set;
}
}
The MetadataTemplateFieldInstanceDisplayViewModel looks like:
public class MetadataTemplateFieldInstanceDisplayViewModel
{
public int FieldId {get;set;}
public string FieldName {get;set;}
public bool IsRequired {get;set;}
}
Please let me know if this is a little vague, I'm new here, and don't want to overload you with too much unnecessary code.
Cheers
Mark
The value of a checkbox does not determine if it's "checked" or not. You'll need to use checked="checked".
I'm not 100% learned with Razor, but here's an attempt:
<input name="IsRequired" type="checkbox" #if(item.IsRequired) { <text>checked="checked"</text>} value="#item.IsRequired" />
Does this solve your problem?
If you declare the column like so:
grid.Column("Select", "Select", format: #<input type="checkbox" name="selectedrows" value="#item.WedNo" />)
then in your action the form posts to you can access these selected item like so:
public ActionResult Selections(string[] selectedrows)
Here selectedrows will contain all the checkboxes checked.
I figured out how to do this the way I wanted:
grid.Column("Select", header: "", format: (item) => #Html.Raw("<a href='" + item.GetSelectUrl() + "' /><img src='" + ((grid.SelectedRow == item) ? "../../Content/images/AdminSelect-ON.png" : "../../Content/images/AdminSelect-OFF.png") + "' />")),

MVC3 & Razor: How to structure forms & actions to allow for postback-like functionality?

I have a view with a drop down list. The default value for this is stored in a session variable. However, the user change change this, in which case new data is entered.
I have a change handler on the drop down:
#using (Html.BeginForm())
{
#Html.DropDownListFor(model => model.SelectedID,
new SelectList(Model.SelectValues, "Key", "Value",
Model.SelectedID), "", new { onchange = "this.form.submit()" });
... more fields ...
<input type="submit" name="Save" />
}
[HttpPost]
public ActionResult Index(ViewModel vm)
{
... decide if I update my data or save the changes ...
}
I tried wrapping the select in a separate form tag, but then the value of my SelectedID not updated in my view model.
How can I determine when the form is posted from a drop down change, and when it is posted from a button click?
If you don't want to reload the entire page when the user changes the selection of the dropdown you could use AJAX to silently trigger a request to a different controller action that will do the necessary updates. For example:
#Html.DropDownListFor(
model => model.SelectedID,
new SelectList(Model.SelectValues, "Key", "Value"),
"",
new {
id = "myddl",
data_url = Url.Action("update")
}
)
and then in a separate javascript file:
$(function() {
$('#myddl').change(function() {
var form = $(this).closest('form');
$.ajax({
url: $(this).data('url'),
type: 'POST',
data: form.serialize(),
success: function() {
alert('update success');
}
});
});
});
and finally you could have a controller action responsible for the update:
[HttpPost]
public ActionResult Update(ViewModel vm)
{
... this will be triggered everytime the user changes some value in the
droipdown list
}
The simplest way would be to simply attach some behavior to those element's events and set a hidden field with the event target (which by now, should sound very familiar to __EVENTTARGET).
Like so:
$('#someButton').click(function()
{
$('#someHiddenField').val('someButton');
});
$('#someDropDown').change(function()
{
$('#someHiddenField').val('someDropDown');
});
And then your action method could inspect this value and act appropriately.
HOWEVER
It sounds like you're thinking in an outmoded concept for MVC. If you really needed some new information, you should consider using some Ajax and then having one of your action methods return a partial view if you want to update part of the page.

mvc3 how to pass selected item of a dropdown list from one view to another viaction link

I have a drop down list
in Razor View
#Html.DropDownList("ddlAccount", items)
this drop down list is binded with items.
I want to pass this selected list item to 'Create' Method of "TaskManagement" Controller on click of action link.
#Html.ActionLink("Create New Task", "Create", "KTTaskManagement")
The semantically correct way to handle this case is to use a form instead of an anchor:
#using (Html.BeginForm("Create", "KTTaskManagement"))
{
#Html.DropDownList("ddlAccount", items)
<button type="submit">Create New Task</button>
}
This way the selected value of the dropdown will be automatically sent to the controller action:
public ActionResult Create(string ddlAccount)
{
// the action argument will contain the selected value
...
}
And while your at it please use the typed equivalence
#Html.DropDownListFor(m => m.SelectedItemId, new
SelectList(Model.Items, "ItemId", "ItemName", Model.SelectedItemId))

How to get my Action method to give me back my model from web grid with checkboxes

I have a strongly typed view which is uses an IEnumerable as its model.
There's a bool property on the model which I'm rendering in a MVC WebGrid in a checkbox which the user can then check or uncheck.
On submit it gets to my action method but how do I get the checked checkboxes?
If I look at the Request.Params, I see all the checked checkboxes coming back as parameters. Is there any easy way for the DefaultModelBinder to convert these back into my IEnumerable, or do I have to do this by hand?
Here's my View so far:
#model IEnumerable<XXX.XXXItemDto>
<div id="items">
#using (Ajax.BeginForm("SaveEvents", "MyController", new AjaxOptions { UpdateTargetId = "items" }))
{
var grid = new WebGrid(Model, canPage: false, canSort: false);
#grid.GetHtml(columns: grid.Columns(
grid.Column("itemDescription", header: "Event"),
grid.Column("acknowledged", format: #<text><input name="Acknowledged_#(item.staffItemOid)" type="checkbox" value="#item.staffItemOid" #(item.acknowledged ? "Checked" : null)/> </text>, header: "Acknowledged")
))
#Html.SubmitButton("Save")
}
</div>

Resources