ASP.net MVC Razor - binding checkboxs to bool values - asp.net

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.

Related

How to pass model list to controller [duplicate]

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.

Spring #ModelAttribute not working

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));
}

Get Checkbox value in mvc5

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
}

springmvc how to send multi dimensional radiobutton array to controller

I am trying to make a feedback from but i am not able to get any example on how to send multidimensional int array from form to controller.
feedback from pic : http://oi58.tinypic.com/p1z10.jpg
Controller
#RequestMapping(value = "/submitfeedback", method = RequestMethod.POST)
public String postsubmitfeedback(#ModelAttribute("answer") #RequestParam("email") String email,
#RequestParam("feedback_id") Integer feedback_id, #RequestParam(value="myanswer[]") int [] myanswer, Answer answer,
Locale locale) {
for(int i=0; i<myanswer.length;i++) {
System.out.println(myanswer[i]);
}
return "submitfeedback";
}
Jsp Form
<form:form commandName="feedback">
<c:forEach items="${questionList}" var="question">
<c:set var="counter" value="${counter + 1}"/>
<tr>
<td>${counter}</td>
<td>${question.question}</td>
<td><input type="radio" name="myanswer[${count}]" id="radio" value="1" /> 1</td>
<td><input type="radio" name="myanswer[${count}]" id="radio" value="2" /> 2</td>
<td><input type="radio" name="myanswer[${count}]" id="radio" value="3" /> 3</td>
<td><input type="radio" name="myanswer[${count}]" id="radio" value="4" /> 4</td>
<td><input type="radio" name="myanswer[${count}]" id="radio" value="5" /> 5</td>
</tr>
<c:set var="count" value="${count+1}"/>
</c:forEach>
</form:form>
First, I strongly recommend you to encapsulate your parameters in an object.
class FeedbackForm {
private String email;
private Integer feedbackId;
private Integer answer;
/** Getters and setters. */
}
The html form inputs' names should match the field names.
Secondly, you have a radio button control, I doubt you will end up with an array of ints, since you can only have one radio button selected at all times. In the bean above, I've corrected it to a single answer. Radio buttons are a bit bizarre, since they're multiple inputs inside the form. you should probably have something like this :
<input type="radio" name="answer" value="1" onClick="changeMyHiddenField()" />1
<input type="radio" name="answer" value="2" onClick="changeMyHiddenField()" />2
<input type="radio" name="answer" value="3" onClick="changeMyHiddenField()" />3
<form {...}> <input id="myHiddenField" type="hidden" name="answer" /> </form>
Thirdly, You have no validation of the client's input. You should take advantage of Spring's bean validation.
#Min(value = 1, message = "Min is 1.")
#Max(value = 5, message = "Max is 5.")
private Integer answer;
Finally, your method signature should look like this:
public String postFeedback(#ModelAttribute #Valid FeedbackForm form, HttpServletRequest request, Locale locale);

InitBinder on multiple form objects

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">

Resources