I'm creating a table.I want to get selected checkbox value.
<tr>
<td>
#item
<input type="hidden" value="#item" name="#item" class="chkbx" id="ControllerName" />
</td>
<td>
<input type="checkbox" id="Iscreate" value="#Create" class="chkbx" />
</td>
<td>
<input type="checkbox" id="IsDelete" value="#Delete" class="chkbx" />
</td>
<td>
<input type="checkbox" id="IsView" value="#View" class="chkbx" />
</td>
<td>
<input type="checkbox" id="IsEdit" value="#Edit" class="chkbx" />
</td>
<td>
<input type="checkbox" id="IsDownload" value="#Download" class="chkbx" />
</td>
</tr>
Jquery code I use
<script type="text/javascript">
$('input[type=checkbox]').change(function () {
var vales = $("#ControllerName").val();
var vals = $('input[class=chkbx]:checked').map(function () {
return $(this).val();
}).get().join(',');
$('#debug').val(vals);
});
</script>
Basically this code create a Value in hidden Field Like this
3-Create-Account,3-Delete-Account,3-View-Account,3-Edit-Account,3-Download-Account
But Actually i need this
3-Account-Create-Delete-Edit-Download-view,4-Account-Create-Delete-Edit-Download-view, 5-Account-Create-Delete-Edit-Download-view
I'm totally Confused :(
Make a view model with your wanted properties:
public class YouViewModelName()
{
public bool IsView {get; set;}
public bool IsDeleted{get; set;}
public bool IsCreated{get; set;}
public bool IsEdited{get; set;}
......... and so on
}
Then use this view model in your view:
#Html.CheckBoxFor(x => x.IsView)
#Html.CheckBoxFor(x => x.IsDeleted)
#Html.CheckBoxFor(x => x.IsCreated)
#Html.CheckBoxFor(x => x.IsEdited)
and so on...
When you post the form to your post action, you will get the values.
[HttpPost]
public ActionResult PostActionName(ViewModelName viewModel)
{
//use values here
}
Related
This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 4 years ago.
I am trying to post a list of objects from View to controller.
Below is my code:
View :
#using Models
#model IList<Add>
#{
ViewData["Title"] = "AddNewFields";
}
<form asp-controller="Trans" asp-action="InsertFields" method="post" class="form-horizontal card-body" role="form">
<td><input type="text" class="form-control" value="Field Size" asp-for="#Model[i].TypeFlag"/></td>
<td><input type="text" class="form-control" value="Field Value" asp-for="#Model[i].FieldValue"/></td>
<td><input type="text" class="form-control" value="Field Format" asp-for="#Model[i].FieldFormat"/></td>
</form>
I will be adding mo these text fields again on button click.
Model:
public class Add
{
public string TypeFlag { get; set; }
public string FieldValue { get; set; }
public string FieldFormat { get; set; }
}
Controller:
public string InsertFields(IList<Add> fields)
{
//some logic
}
When I run the application, I am getting the below error:
NullReferenceException: Object reference not set to an instance of an object.
AspNetCore.Views_Trans_Add.<ExecuteAsync>b__27_0() in AddNewFields.cshtml
#for (int i = 0; i < Model.Count; i++)
Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperExecutionContext.GetChildContentAsync(bool useCachedResult, HtmlEncoder encoder)
Microsoft.AspNetCore.Mvc.TagHelpers.RenderAtEndOfFormTagHelper.ProcessAsync(TagHelperContext context, TagHelperOutput output)
Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner.RunAsync(TagHelperExecutionContext executionContext)
Please help me...I am stuck here from 2 days..
2 issues:
Model is null
Action will not get values.
solution:
Your HTML should be this style
#{
var fields = (Model ?? Enumerable.Empty<Add>()).ToList(); //this variable must be same with the parameter in action.
}
<form asp-action="Test" method="post">
<table class="table">
<tbody>
<tr>
<td>
<div class="form-group">
<input type="submit" value="Submit" />
</div>
</td>
</tr>
#for (var i = 0; i < fields.Count; i++) //you must use for, not foreach
{
<tr>
<td>
<div class="form-group">
<input type="hidden" asp-for="#fields[i].Id" />
<input asp-for="#fields[i].Name" class="form-control" />
</div>
</td>
</tr>
}
</tbody>
</table>
</form>
your controller should be this:
[HttpPost]
public async Task<IActionResult> Test(IEnumerable<Add> fields)
//be aware: the parameter name "fields" must be same with your html
//the type should be "IEnumerable<Add>", more compatible with different versions of MVC
{
.....your logic
return Json(new { ... });
}
the generated html is this style:
<tr>
<td>
<div class="form-group">
<input type="hidden" id="fields_0__Id" name="fields[0].Id" value="14">
<input class="form-control" type="text" id="fields_0__Name" name="fields[0].Name" value="xxxxx">
</div>
</td>
</tr>
<tr>
<td>
<div class="form-group">
<input type="hidden" id="fields_1__Id" name="fields[1].Id" value="1">
<input class="form-control" type="text" id="fields_1__Name" name="fields[1].Name" value="xxxx">
</div>
</td>
</tr>
you will see the reason: the parameter fields is just a field of html form, they must match each other.
I can't figure out how to get selected checkboxes to become "true" and unselected checkboxes to become "false" bool values. Here is a sample of the code I am working on.
Note: My put function is getting a 200 response but the checkboxes just are not updating the bool.
Model
public class AccountFeatures
{ public bool? FormCopy { get; set; }
public bool? FormRename { get; set; }
public bool? FormTransfer { get; set; }
public bool? FormDelete { get; set; }
public bool? FormEdit { get; set; }
public bool? FormComplete { get; set; }
}
View
`$('.ui.form.accountfeatures').form({
on: 'blur',
inline: true,
onSuccess: function () {
$('#features').dimmer('show');
$.ajax({
method: 'PUT',
data: { FormRename: $("#FormRename").val() ? true : false,
FormTransfer: $("#FormTransfer").val() ? true : false,
FormDelete: $("#FormDelete").val() ? true : false,
FormEdit: $("#FormEdit").val() ? true : false,
FormComplete: $("#FormComplete").val() ? true : false}
HTML
<tr>
<td>Form Copy</td>
<td class="center aligned">
<input type="checkbox" name="FormCopy" id="FormCopy" value="False" checked="#Model.Account.Features.FormCopy">
</td>
</tr>
<tr>
<td>Form Rename</td>
<td class="center aligned">
<input type="checkbox" name="FormRename" id="FormRename" value="FormRename" checked="#Model.Account.Features.FormRename">
</td>
</tr>
<tr>
<td>Form Transfer</td>
<td class="center aligned">
<input type="checkbox" name="FormTransfer" id="FormTransfer" value="FormTransfer" checked="#Model.Account.Features.FormTransfer">
</td>
</tr>
<tr>
<td>Form Delete</td>
<td class="center aligned">
<input type="checkbox" name="FormDelete" id="FormDelete" value="FormDelete" checked="#Model.Account.Features.FormDelete">
</td>
</tr>
<tr>
<td>Form Edit</td>
<td class="center aligned">
<input type="checkbox" name="FormEdit" id="FormEdit" value="FormEdit" checked="#Model.Account.Features.FormEdit">
</td>
</tr>
<tr>
<td>Form Complete</td>
<td class="center aligned">
<input type="checkbox" name="FormComplete" id="FormComplete" value="FormComplete" checked="#Model.Account.Features.FormComplete">
</td>
</tr>
I typically use an EditorFor and it just works:
#Html.EditorFor(m => m.CheckBoxProperty)
However, I also typically only use bool, not bool? for my checkbox properties.
Something to note regarding the checked attribute - you usually either use just the attribute name, as in:
<input type="checkbox" name="FormComplete" id="FormComplete" value="FormComplete" checked />
Or you use checked="checked", as in:
<input type="checkbox" name="FormComplete" id="FormComplete" value="FormComplete" checked="checked" />
Any other way, like putting checked="true" or checked="false" doesn't produce the outcome that you would expect, or at the very least, is not consistent amongst all browsers. What these use cases usually result in are checked boxes, regardless of whether you wanted that, or not. Here's a quick mock up to demonstrate:
<input type="checkbox" value="test" name="test1" /> Test 1<br />
<input type="checkbox" value="test" name="test2" checked /> Test 2<br />
<input type="checkbox" value="test" name="test3" checked="checked" /> Test 3<br />
<input type="checkbox" value="test" name="test4" checked="true" /> Test 4<br />
<input type="checkbox" value="test" name="test5" checked="false" /> Test 5
And a screenshot of the output under Chrome 57:
Essentially, you want to use logic to determine whether to insert the checked attribute altogether, rather than inserting it and having the logic set it to true or false.
I have a controller in which I put both the get and post methods. Both methods work fine but when I introduce #ModelAttribute annotation to the POST method, it starts giving me Status 400 -- The request sent by the client was syntactically incorrect.
I do not know what I am doing wrong. The View looks like:
<form:form method="post" action="createIdeaPublic" commandName="idea">
<table class="form">
<tr>
<td align="right"><label for="title">Idea Title</label></td><td align="left"><form:input type="text" path="title" id="title"></form:input></td>
<td align="right"><label for="email">Your Email</label></td><td align="left"><form:input type="text" path="requestorEmail" id="requestorEmail" class="emails"></form:input></td>
</tr>
<tr>
<td align="right"><label for="partnerEmail">CI Contact Email</label></td><td align="left"><form:input type="text" path="cIInitialContact" id="cIInitialContact" class="emails"></form:input></td>
<td align="right"><label for="sponsorEmail">Sponsor Email</label></td><td align="left"><form:input type="text" path="sponsorEmail" id="sponsorEmail" class="emails"></form:input></td>
</tr>
<tr>
<td align="right"><label for="requestedDeliveryDate">Requested Delivery Date</label></td><td align="left"><form:input type="text" path="requestedDeliveryDate" id="requestedDeliveryDate" class="datepicker"></form:input></td>
<td align="right"><label>Classification</label></td><td align="left">
<label for="discretionary" class="radio">Discretionary</label>
<form:radiobutton path="stateDescription" id="discretionary" value="Discretionary"></form:radiobutton>
<label for="mandatory" class="radio">Mandatory</label>
<form:radiobutton path="stateDescription" id="mandatory" value="Mandatory"></form:radiobutton>
<label for="regulatory" class="radio">Regulatory</label>
<form:radiobutton path="stateDescription" id="regulatory" value="Regulatory"></form:radiobutton>
</td>
</tr>
<tr>
<td colspan="4" align="right"><input type="submit" class="ui ui-button ui-corner-all ui-widget" style="margin-top: .6em; margin-right: 1em;font-weight: bold;font-size: 1.2em; width: 150px;" value="Create Idea" /></td>
</tr>
</table>
</form:form>
I tried changing the commandName="idea" to modelAttribute="idea" but no benifit.
The Spring controller looks like
#Controller
#RequestMapping ("/createIdeaPublic")
public class CreateIdeaPublicController{
#RequestMapping(method = RequestMethod.GET)
public ModelAndView view(ModelMap model) {
model.addAttribute("areas",Utils.areas);
return new ModelAndView("createIdeaPublic", "idea", new Idea());
}
#RequestMapping(method = RequestMethod.POST)
public String submit(#ModelAttribute("idea")Idea idea, ModelMap model) {
// System.out.println(idea.getTitle());
System.out.println("Hello World");
return "redirect:createIdeaPublic";
}
}
But as soon as I remove the #ModelAttribute("idea")Idea idea, from the submit method, the form submission starts working.
I figured it out. It was issue with the date field. If I dont enter a value into the date field, I would get 400 page. So here is what I did in the Controller class. Copy as it is if you have this issue (Just change the date format accordingly).
#InitBinder
public void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy");
dateFormat.setLenient(false);
// true passed to CustomDateEditor constructor means convert empty String to null
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
}
Can you have a #Initbinder on several data in the same form?
I have a spring form which contains a select dropdown of an object and two datafields, I have an Initbinder on the dates otherwise I get an error on submit. But I also need to bind the dropdown to an object.
I have a Type which has two dates and a Category, and it is the Category I need to bind because it can not be empty on save.
I think it will help me to validate the form to.
So can I have this in my Type controller?
#InitBinder
public void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateFormat.setLenient(false);
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
binder.registerCustomEditor(Category.class, "category", new CategoryEditor(CategoryService));
}
And this is the Editor:
public class CategoryEditor extends PropertyEditorSupport {
private CategoryService categoryService;
public CategoryEditor(CategoryService categoryService) {
this.categoryService = categoryService;
}
#Override
public void setAsText(String text) throws IllegalArgumentException {
if (text.equals("0")) {
this.setValue(null);
} else {
Category sc = categoryService.getCategory(Integer.parseInt(text));
this.setValue(sc);
}
}
#Override
public String getAsText() {
Category parent = new Category();
if (this.getValue() != null) {
parent = (Category) this.getValue();
}
return "";
}
}
And my jsp-page
<s:url value="/mvc/type/save" var="actionUrl" />
<sf:form method="POST" modelAttribute="type" action="${actionUrl}">
<fieldset>
<legend><s:message code="${heading}" /></legend>
<table>
<tr>
<th><label for="category"><s:message code="category" />:</label></th>
<td><sf:select path="category.ID" id="category">
<sf:option value="0"> </sf:option>
<sf:options items="${listOfCategories}" itemLabel="name" itemValue="ID" />
</sf:select></td>
</tr>
<tr>
<th><label for="name"><s:message code="name" />:</label></th>
<td><sf:input path="name" id="name" />
<sf:hidden path="ID" />
<sf:hidden path="version" /></td>
</tr>
<tr>
<th><label for="marketing"><s:message code="marketing" />:</label></th>
<td><sf:input path="marketingFunction" id="marketing" /></td>
</tr>
<tr>
<th><label for="status"><s:message code="status" />:</label></th>
<td><sf:select path="lifeCycleStatus">
<sf:option value="0"> </sf:option>
<sf:options items="${listOfEnums}" />
</sf:select></td>
</tr>
<tr>
<th><label for="validfrom"><s:message code="validfrom" />:</label></th>
<td><sf:input path="validFrom" id="validfrom" /></td>
</tr>
<tr>
<th><label for="validuntil"><s:message code="validuntil" />:</label></th>
<td><sf:input path="validUntil" d="validuntil" /></td>
</tr>
<tr>
<td colspan="2">
<input id="saveButton" class="right" type="submit" title="<s:message code="save" />" value=" [ <s:message code="save" /> ] " />
</td>
</tr>
</table>
</fieldset>
</sf:form>
So my question: Can I have multiple binder in the same initBinder in my controller? It seems like I can't because I never enter the CategoryEditor. How do I do this?
There aren't multiple binders, there are multiple PropertyEditors.
Your custom one is never called because you are binding the wrong path.
<sf:select path="category.ID" id="category">
You must bind to category and not category.ID
<sf:select path="category" id="category">
I have a Form which is filled with some grid like structure with CheckBoxes and DisplayField.
I want to fetch rows with Checked CheckBoxes. Problem is i am getting null in Controller's post method.
Models
public class RegisterModuleSelection
{
[Display(Name = "ID")]
public int mID { get; set; }
[Display(Name = "Module")]
public string Module { get; set; }
[Display(Name = "Buy")]
public bool Buy { get; set; }
}
View
#model IEnumerable<MAK_ERP.Models.RegisterModuleSelection>
#{
ViewBag.Title = "Register - Modules Selection";}
<h2>
Register - Modules Selection</h2>
#using (Html.BeginForm("RegisterModules", "UserAccount", FormMethod.Post, new { id = "RegisterModules", #class = "generalForm" }))
{
<table class="Grid Module">
<tr>
<th>
#Html.DisplayNameFor(model => model.Module)
</th>
<th>
#Html.DisplayNameFor(model => model.Price)
</th>
<th>
#Html.DisplayNameFor(model => model.Duration) (Months)
</th>
<th>
#Html.DisplayNameFor(model => model.Buy)
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.HiddenFor(modelItem => item.mID)
#Html.DisplayFor(modelItem => item.Module)
</td>
<td>
#Html.DisplayFor(modelItem => item.Price)
</td>
<td>
#Html.EditorFor(modelItem => item.Duration)
</td>
<td>
#Html.CheckBoxFor(modelItem => item.Buy)
</td>
</tr>
}
<tr>
<td colspan="4">
<input type="submit" value="Next" class="button3" />
<input type="reset" value="Reset" class="button4" />
</td>
</tr>
</table>
}
Controller
[HttpGet]
public ActionResult RegisterModules()
{
IEnumerable<MAK_ERP.Models.RegisterModuleSelection> model = reg.getModules();
return View(model);
}
[HttpPost]
public ActionResult RegisterModules(IEnumerable<Models.RegisterModuleSelection> regMod)
{
//regMod is null here
...
Unfortunately you cannot bind in this way. Model binding depends upon how generated html looks like. In this particular case it should look something like:
<input id="item_Buy" type="checkbox" value="true" name="item[0].Buy" checked="checked">
If you are okay with some workarounds, you can use a for loop instead of foreach loop where you can add an index to each control name and model binder could bind them properly.
There are some really helpful discussions available, you can check here: ASP.NET MVC - Insert or Update view with IEnumerable model. And also Model Binding To A List. Another one is: Modelbinding IEnumerable in ASP.NET MVC POST?
You should use EditorTemplates to solve the problem.
The accepted answer at ASP.NET MVC Multiple Checkboxes would help you.