radiobuttonfor grouping razor mvc5 - asp.net-mvc

The selected values are not getting posted back when I group my radio buttons,
So, with this the SelectedQuestionId is blank
<div class="row">
<div class="col-md-4">
<div class="form-group">
#Html.HiddenFor(x => x.UserResponses[0].QuestionId)
#Html.RadioButtonFor(x => x.UserResponses[0].SelectedQuestionId, Model.UserResponses[0].QuestionId, new { Name ="selectone"})
#Html.DisplayTextFor(x => x.UserResponses[0].QuestionText)
#Html.HiddenFor(x => x.UserResponses[0].QuestionText)
#Html.HiddenFor(x => x.UserResponses[0].InputType)
#Html.HiddenFor(x => x.UserResponses[0].Points)
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<span class="text-muted">#Html.DisplayTextFor(x => x.UserResponses[0].Points)</span> #Html.LabelFor(x => x.UserResponses[0].Points, new { #class = "text-muted" })
</div>
</div>
</div>
<div class="row">
<div class="col-md-4">
<div class="form-group">
#Html.HiddenFor(x => x.UserResponses[1].QuestionId)
#Html.RadioButtonFor(x => x.UserResponses[1].SelectedQuestionId, Model.UserResponses[1].QuestionId, new { Name = "selectone"})
#Html.DisplayTextFor(x => x.UserResponses[1].QuestionText)
#Html.HiddenFor(x => x.UserResponses[1].QuestionText)
#Html.HiddenFor(x => x.UserResponses[1].InputType)
#Html.HiddenFor(x => x.UserResponses[1].Points)
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<span class="text-muted">#Html.DisplayTextFor(x => x.UserResponses[1].Points)</span> #Html.LabelFor(x => x.UserResponses[1].Points, new { #class = "text-muted" })
</div>
</div>
</div>
But the moment i remove the grouping from the radiobuttonfor then all works well, and the SelectedQuestionId is populated with questionid. So, replacing the RadioButtonFor above with these allow the SelectedQuestionId to be populated when the form is posted.
The code above is based on this question and though I have asked a related question here - this question is entirely separate.
#Html.RadioButtonFor(x => x.UserResponses[0].SelectedQuestionId, Model.UserResponses[0].QuestionId)
#Html.RadioButtonFor(x => x.UserResponses[1].SelectedQuestionId, Model.UserResponses[1].QuestionId)

found a solution to this rather intractable problem.
#Html.RadioButtonFor(x => x.UserResponses[0].SelectedQuestionId, Model.UserResponses[0].QuestionId)
#Html.RadioButtonFor(x => x.UserResponses[1].SelectedQuestionId, Model.UserResponses[1].QuestionId)
with the code above each radiobutton had a unique name during the deserialization process the SelectedQuestionId property would be populated for a given item if it was selected as one would expect. However, for the radiobutton to belong to a group they would need to have the same name attribute and since this was not the case in the above scenario one could select both the radio buttons. Which also meant that with multiple radiobuttons being selcted selectedId property for all the selected radio buttons would be populated with their respective QuestionId.
To get around this one could always write code as so,
#Html.RadioButtonFor(x => x.UserResponses[0].SelectedQuestionId, Model.UserResponses[0].QuestionId, new { Name = "selectone"})
#Html.RadioButtonFor(x => x.UserResponses[1].SelectedQuestionId, Model.UserResponses[1].QuestionId, new { Name = "selectone"})
And, now one gets the ability to select only one radiobutton but then during the deserialization process in the HttpPost method the SelectedQuestionId property for each item in the collection would be null. Obviously, the name of the radiobuttons were now "selectone" and so in the key/value pairing for SelectedQuestionId the value would not be getting populated, in other words the SelectedQuestionId would always be null even for the radio button that was selected.
So, the solution was the following:
#Html.RadioButtonFor(x => x.SelectedId, Model.UserResponses[i].QuestionId)
x.SelectedId lies in the ParentModel, and gets populated with the QuestionId of the question that is selected and since both the radio button share the same name they therefore belong to the same group and hence only one of the radio buttons can be selected.

Related

How can I change input field to Datepicker based on radio button selection?

I have an input field and it accepts strings inputted by the user. It looks for the string based on a radio button. Pic of Form
Basically I want that input field to turn into a date picker if the DOB or DOJ radio button is selected.
This is how my view looks like currently
<div class="row">
<div class="col-md-4">
<form asp-action="Find">
#Html.TextBoxFor(m => m.input)<br />
#Html.RadioButtonFor(m => m.radio, "ID")<aspan>ID</aspan><br />
#Html.RadioButtonFor(m => m.radio, "FirstName")<aspan>First Name</aspan><br />
#Html.RadioButtonFor(m => m.radio, "LastName")<aspan>Last Name</aspan><br />
#Html.RadioButtonFor(m => m.radio, "DOB")<aspan>DOB</aspan><br />
#Html.RadioButtonFor(m => m.radio, "DOJ")<aspan>DOJ</aspan><br />
#Html.RadioButtonFor(m => m.radio, "Phone")<aspan>Phone</aspan><br />
#Html.RadioButtonFor(m => m.radio, "Email")<aspan>Email</aspan><br />
<div class="form-group">
<input type="submit" value="Find" class="btn btn-default" />
</div>
</form>
</div>
</div>
<div>
Firstly, you should not use #Html.RadioButtonFor in that way. It will generate all the inputs with the same id. That would not be nice, as per specification ID-s should be unique.
Do it like this (give a different id for each input)
#Html.RadioButtonFor(model => model.radio, "FirstName", new { id = "FirstName" })
Secondly, you need to use JavaScript for what you want to achieve.
I am going with JQuery, but you can do it without it also. Use change method so you get the selected value for the radio button each time the user changes it. Then you can use .prop() to change the input type.
$('input[name=radio]').change(function() {
if (this.value=== 'DOB' || this.value=== 'DOJ') {
$('input[name=input]').prop('type', 'date');
} else {
$('input[name=input]').prop('type', 'text');
}
});

posting list to the controller from partial view

I have a partial view, which generates rows dynamically and from where I want to submit the data to the controller. So I am binding the model properties with a list, but on httppost my list is always null.Using form collection I am able to get the data. How can I solve this issue?
<td data-title="Product Name">
<div class="row">
<div class="col-xs-10" style="padding-right:0px;">
<div class="form-group">
#Html.DropDownListFor(model => model._list[Model.id].detail_prod_id, Model._Product, "Please Select Product", new { #class = "chosen-select form-control", #id = "ddlproducts" + Model.id ,#Name= "ddlproducts" +Model.id})
#Html.ValidationMessageFor(model => model._list[Model.id].detail_prod_id, "", new { #class = "text-danger" })
</div>
</div>
<div class="col-xs-2" style="padding-right:25px; padding-left:5px;"><a class="popup-sm fancybox.iframe" href="../pages/add-product.html"><u>Add</u></a></div>
</div>
</td>
Try to put code inside form tag and then try..it may work.

Kendo UI Grid Popup Editor Data Binding

I am trying to bind a list to the Popup Editor screen.
The object is coming back as...
public IEnumerable<SystemUserRole> UserRoles { get; set; }
I am trying to get the list bound to the popup editor..
<div>
#Html.LabelFor(model => model.FirstName)
</div>
<div>
#Html.EditorFor(model => model.FirstName)
#Html.ValidationMessageFor(model => model.FirstName)
</div>
<div>
#Html.LabelFor(model => model.LastName)
</div>
<div>
#Html.EditorFor(model => model.LastName)
#Html.ValidationMessageFor(model => model.LastName)
</div>
<div>
#Html.LabelFor(model => model.EmailAddress)
</div>
<div>
#Html.EditorFor(model => model.EmailAddress)
#Html.ValidationMessageFor(model => model.EmailAddress)
</div>
There is a property on the SystemUserRole that states whether it is selected or not.
What I want to show is a list of checkboxes with a label of SystemUserRole.RoleName and and the checked html property bound to the IsSelected property on the model.
Anybody have any clue how to do this?

Custom entry on #Html.DropDownListFor

The code below will only accept the colors contained in the model. How can it allow for the user to enter one that is not listed in the model ?
<div class="form-group input-group-sm">
#Html.LabelFor(m => m.CarColor, new { #class = "control-label col-md-5" })
<div class="col-md-7">
#Html.DropDownListFor(m => m.CarColor, ViewBag.CarColorList as SelectList })
</div>
</div>
The way that I would do it would to be to use Select2. Select2 is basically an awesome drop down list. The 'Loading Data' example shows you where to start.

MVC - Editing a list of objects

I have the following class layout in MVC:
public class ReportModel
{
List<SomeItem> items;
string value;
string anotherValue;
}
now I create a strongly typed view in MVC of this type and make editable text fields to edit each value as well as use a foreach loop to populate text fields to edit the items in the list of someitem.
when I submit to the httppost method the singular values come back fine in the reportmodel object but the list does not get returned in the object. How should this be done?
When I say httppost I am referring to the method that MVC is posting back to
[HttpPost]
public ActionResult EditReport(ReportModel report)
{
// Save the report in here after the update on the UI side
}
View code for posting the list of someitem
if (Model.items != null && Model.items.Count > 0)
{
for (int i = 0; i < Model.items.Count; i++)
{
<div class="editrow">
<div class="edititem">
<div class="editor-label">
#Html.LabelFor(m => m.items.ElementAt(i).propertyOne)
</div>
<div class="editor-field">
#Html.TextBoxFor(m => m.items.ElementAt(i).propertyOne)
#Html.ValidationMessageFor(m => m.items.ElementAt(i).propertyOne)
</div>
</div>
<div class="edititem">
<div class="editor-label">
#Html.LabelFor(m => m.items.ElementAt(i).propertyTwo)
</div>
<div class="editor-field">
#Html.TextBoxFor(m => m.items.ElementAt(i).propertyTwo)
#Html.ValidationMessageFor(m => m.items.ElementAt(i).propertyTwo)
</div>
</div>
<div class="edititem">
<div class="editor-label">
#Html.LabelFor(m => m.items.ElementAt(i).propertyThree)
</div>
<div class="editor-field">
#Html.TextBoxFor(m => m.items.ElementAt(i).propertyThree)
#Html.ValidationMessageFor(m => m.items.ElementAt(i).propertyThree)
</div>
</div>
</div>
}
}
Don't use ElementAt(1) in your lambda expressions => this ruins your input field names. Please read the blog post that Kirill suggested you.
So you could use indexed access:
for (int i = 0; i < Model.items.Count; i++)
{
<div class="editrow">
<div class="edititem">
<div class="editor-label">
#Html.LabelFor(m => m.items[i].propertyOne)
</div>
<div class="editor-field">
#Html.TextBoxFor(m => m.items[i].propertyOne)
#Html.ValidationMessageFor(m => m.items[i].propertyOne)
</div>
</div>
<div class="edititem">
<div class="editor-label">
#Html.LabelFor(m => m.items[i].propertyTwo)
</div>
<div class="editor-field">
#Html.TextBoxFor(m => m.items[i].propertyTwo)
#Html.ValidationMessageFor(m => m.items[i].propertyTwo)
</div>
</div>
<div class="edititem">
<div class="editor-label">
#Html.LabelFor(m => m.items[i].propertyThree)
</div>
<div class="editor-field">
#Html.TextBoxFor(m => m.items[i].propertyThree)
#Html.ValidationMessageFor(m => m.items[i].propertyThree)
</div>
</div>
</div>
}
Of course in order to have indexer access to the collection this assumes that your items property is declared as either List<SomeItem> or SomeItem[]. If it is an IEnumerable<SomeItem> it won't work. So simply change the type of this property on your view model.
Kirill's reference to Scott Hanselman's blog entry is correct, but you're reading it too narrowly. In the example shown, he passes the array to the action method, but it could just as easily be contained within the parent model as well. The same concept applies.
However, one thing to know is that the default model binder does not instantiate nested classes, so it will not create an instance of the List class, which means it will always be null. To fix this, you must instantiate the empty list class in the constructor.
This is only part of the problem, though as the data must be formatted in the correct way for the model binder to bind it. This is where Scott's blog post comes in, as it provides the format needed for the model binder to recognize the data as a list.
This is typically handled for you if you use an EditorTemplate and use Html.EditorFor(m => m.Items) and then have a SomeItem.cshtml EditorTemplate. This deals with the issues of collection item naming (so long as you also use strongly typed helpers in the template as well).

Resources