MVC4: Two radio buttons for a single boolean model property - asp.net-mvc

I'm attempting to find the correct Razor syntax for mutually exclusive radio buttons that both reflect the value of a boolean property on my model. My model has this:
public bool IsFemale{ get; set; }
I would like to display this with two radio buttons, one "Male" and the other "Female," but everything I've tried so far has not reflected the actual value of the IsFemale property on the model. Currently, I have this:
#Html.RadioButtonFor(model => model.IsFemale, !Model.IsFemale) Male
#Html.RadioButtonFor(model => model.IsFemale, Model.IsFemale) Female
This seems to persist the value correctly if I change and update, but does not mark the correct value as checked. I'm sure this is something stupid, but I'm stuck.

Try like this:
#Html.RadioButtonFor(model => model.IsFemale, "false") Male
#Html.RadioButtonFor(model => model.IsFemale, "true") Female
And here's the full code:
Model:
public class MyViewModel
{
public bool IsFemale { get; set; }
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View(new MyViewModel
{
IsFemale = true
});
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
return Content("IsFemale: " + model.IsFemale);
}
}
View:
#model MyViewModel
#using (Html.BeginForm())
{
#Html.RadioButtonFor(model => model.IsFemale, "false", new { id = "male" })
#Html.Label("male", "Male")
#Html.RadioButtonFor(model => model.IsFemale, "true", new { id = "female" })
#Html.Label("female", "Female")
<button type="submit">OK</button>
}

In MVC 6 (ASP.NET Core) this can also be achieved with tag helpers:
<label>
<input type="radio" asp-for="IsFemale" value="false" /> Male
</label>
<label>
<input type="radio" asp-for="IsFemale" value="true" /> Female
</label>

As far as September 2022.
Boolean radio button using: .NET Framework 4.7.2, MVC 5.2.7, Bootstrap 5.1.3.
Model
public class TheViewModel
{
public bool IndustrialDegree { get; set; }
}
View
<div class="col-4 col-md-2 mb-3">
#Html.Label("Industrial Degree", new { #class = "d-block form-label" })
<div class="btn-group d-flex" role="group" aria-label="Basic radio toggle button group">
#Html.RadioButtonFor(Model => Model.IndustrialDegree, true, new { #class = "btn-check", #id = "IndustrialDegreeTrue" })
#Html.Label("IndustrialDegreeTrue", "Yes", new { #class = "btn btn-outline-primary" })
#Html.RadioButtonFor(Model => Model.IndustrialDegree, false, new { #class = "btn-check", #id = "IndustrialDegreeFalse" })
#Html.Label("IndustrialDegreeFalse", "No", new { #class = "btn btn-outline-primary" })
</div>
</div>
Notice that I'm returning a pure boolean value to the controller.
Result
It works in both directions.
This is what you'll see on the controller when debugging the view model.
and

Related

Razor pages, detect text changes in textview

I have a razor page where the user can make some options from a dropdownlist and than enter some value.
See attached image
What i want to achieve is that as user change any of the textboxes, call the appropriate handler function.
So as soon user enter some value in the textfield 1, the one to the right of textlabel "Some value" i want to do some calculation and update the textfield 2, the one to the right of textlabel "Some other value" . And vice versa for the other textfield.
I have following code
#page
#model CurrencyConverter.Pages.ConvertModel
#{
ViewData["Title"] = "Convert";
}
<div>
#if (!string.IsNullOrEmpty(Model.ResultInfo))
{
<p>#Model.ResultInfo</p>
}
</div>
<form method="post">
<div>
#Html.DropDownListFor(m => m.CurencyModel.FirstCurrency, new SelectList(Model.Options, "Value", "Text"), "Select currency", new { #class = "css-class" })
<input asp-for="CurencyModel.TotalAmountFirstCurrency" />
</div>
<div>
#Html.DropDownListFor(m => m.CurencyModel.SecondCurrency, new SelectList(Model.Options, "Value", "Text"), "Select currency", new { #class = "css-class" })
<input asp-for="CurencyModel.TotalAmounSecondCurrency" />
</div>
<div>
<button type="submit" asp-page-handler="FirstCurrency">Submit first currency</button>
<button type="submit" asp-page-handler="SecondCurrency">Submit second currency</button>
</div>
</form>
the cshtml.cs file looks like this
public class ConvertModel : PageModel
{
[TempData]
public string ResultInfo { get; set; }
[BindProperty]
public CurrencyModel CurencyModel { get; set; }
[BindProperty]
public IEnumerable<SelectListItem> Options
{
get; set;
}
public ConvertModel()
{
//initalization
}
public async Task<IActionResult> OnPostFirstCurrency()
{
if(!ModelState.IsValid)
{
return Page();
}
//given first currency calculate the second from the first using some formula
}
public async Task<IActionResult> OnPostSecondCurency()
{
if (!ModelState.IsValid)
{
return Page();
}
//given second currency calculate the second from the first using some formula
}
}
what i want to achieve is in
<div>
#Html.DropDownListFor(m => m.CurencyModel.SecondCurrency, new SelectList(Model.Options, "Value", "Text"), "Select currency", new { #class = "css-class" })
<input asp-for="CurencyModel.TotalAmounSecondCurrency" onchanged=asp-page-handler="FirstCurrency"/>
But this seems not possible with only pure razor and c# syntax.

How to bind selected radio button value using MVC in view

<div class="row mt-4">
<div class="col-md-12 correct_answer">
<lable>Correct Answer</lable><br /><br />
<label class="radio-label">
#Html.RadioButtonFor(x => x.IsCorrectAnswerOption1, new { #class = "form-control", #type = "radio", id = "IsCorrectAnswerOption1", name = "IsCorrectAnswerOption1"})
<span>A</span>
</label>
<label class="radio-label">
#Html.RadioButtonFor(x => x.IsCorrectAnswerOption2, new { #class = "form-control", #type = "radio", id = "IsCorrectAnswerOption2", name = "IsCorrectAnswerOption2" })
<span>B</span>
</label>
<label class="radio-label">
#Html.RadioButtonFor(x => x.IsCorrectAnswerOption3, new { #class = "form-control", #type = "radio", id = "IsCorrectAnswerOption3", name = "IsCorrectAnswerOption3" })
<span>C</span>
</label>
<label class="radio-label">
#Html.RadioButtonFor(x => x.IsCorrectAnswerOption4, new { #class = "form-control", #type = "radio", id = "IsCorrectAnswerOption4", name = "IsCorrectAnswerOption4" })
<span>D</span>
</label>
<br />
<span id="CorrectAnswerError" class="error">Correct Answer is required</span>
</div>
</div>
Here i have four different radio buttons with different id's and name in that model i have one true value but here i am unable to bind the selected radio value i.e true.
Instead of using boolean variables for each option you can create an enum and give it as a property in a model. In post method you can directly map selected option by the user by
MyOptions Property itself.
Note: Do not change the name attribute of the element.
//Your Model
public class Answer
{
public Options MyOptions { get; set; }
}
public enum Options
{
None,
Option1,
Option2,
Option3,
Option4,
}
//Your Controller
public ActionResult SelectOption()
{
Answer ans = new Answer();
return View(ans);
}
[HttpPost]
public ActionResult SelectOption(Answer answer)
{
var selectedOption = answer.MyOptions;
return View();
}
//Your cshtml page
#model Answer;
#using (Html.BeginForm(FormMethod.Post))
{
#Html.RadioButtonFor(x => x.MyOptions, Options.Option1) <span>Option 1</span>
#Html.RadioButtonFor(x => x.MyOptions, Options.Option2)<span>Option 2</span>
#Html.RadioButtonFor(x => x.MyOptions, Options.Option3)<span>Option 3</span>
#Html.RadioButtonFor(x => x.MyOptions, Options.Option4)<span>Option 4</span>
<button type="submit">Submit</button>
}

Adding new attributes on RadioButton through MVC model variable

I have MVC class and one of the variables has been declared as:
[UIHint("YesNoRadio")]
[Required(ErrorMessage = "test")]
public bool? Emergency { get; set; }
this creates HTML as
<div class="radio-inline"><label>
<input data-val="true" data-val-required="Test" id="Emergency" name="Emergency" type="radio" value="true">Yes</label>
</div>
<div class="radio-inline"><label>
<input id="Emergency" name="Emergency" type="radio" value="false">No</label>
</div>
what i want is to add new attribute, lets say div-effect = "emergencyExplain" and radio button to come as
<label><input id="Emergency" name="Emergency" type="radio" value="false" div-effect = "emergencyExplain">No</label>
YesNoRadio.cshtml is below:
#model bool?
<div class="radio-inline">
<label>
#if (Model.HasValue && Model.Value)
{
#Html.RadioButtonFor(x => x, "true", new { #checked = "checked" });
}
else
{
#Html.RadioButtonFor(x => x, "true");
}
Yes
</label>
</div>
<div class="radio-inline">
<label>
#if (Model.HasValue && !Model.Value)
{
#Html.RadioButtonFor(x => x, "false", new { #checked = "checked" });
}
else
{
#Html.RadioButtonFor(x => x, "false");
}
No
</label>
</div>
and its called as:
#Html.EditorFor(m => m.Emergency, new { htmlAttributes = new { #class = "form-control" } })
New to MVC form creation so any help in pointing in right direction will be appreciated.
Thanks
Using the [UIHint] attribute just instructs the EditorFor() method to use that template. It does not pass any additional data to the template other that the modell property. You need to use this overload of EditorFor() where you pass the name of the template and an object representing the additionalViewData.
You have no shown the model property that contains the value that you want to add to the data-effect attribute, but assuming its
public string Effect { get; set; }
and you set its value in the GET method before you pass the model to the view, then delete the [UIHint] attribute from the Emergency property and modify the main view to
#Html.EditorFor(m => m.Emergency, "YesNoRadio", new { effect = Model.Effect })
Then change the YesNoRadio.cshtml template to
<div class="radio-inline">
<label>
#Html.RadioButtonFor(x => x, true, new { id = "", div_effect = ViewData["effect"] })
<span>Yes</span>
</label>
<label>
#Html.RadioButtonFor(x => x, false, new { id = "", div_effect = ViewData["effect"] })
<span>No</span>
</label>
</div>
Which will generate
<input data-val="true" data-val-required="Test" div-effect="emergencyExplain" name="Emergency" type="radio" value="True">
A few things to note about your current view code.
Using new { htmlAttributes = new { #class = "form-control" } }
wont do anything when using a custom EditorTemplate - its only
applicable using the built-in templates (how would it know which
element to apply that class to). If you want the class name applied
to the radio buttons, add that in the RadioButtonFor() method in
the template
You do not need to (and should not) set the checked attribute.
That attribute is set by the RadiobuttonFor() method based on the
value of the property (if its null, no buttons will be selected,
and if its true or false then the appropriate button will be
selected
Note also the use of new { id = "" } which removes the id
attribute which would other wise be generating duplicates which is
invalid html

how can i assign value to textbox in MVC - Sharepoint Provider-hosted

I want to get and assign value to my textbox from controller.
here is my textbox:
<input type="text" class="form-control" id="RegardingTo" name="RegardingTo" value="??????"/>
then i want to get the value from this action.
public ActionResult Edit(int? RequestID)
{
if (RequestID <= 0)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var ReqID = db.usp_RequestGetDetails(RequestID);
if (ReqID == null)
{
return HttpNotFound();
}
return View();
}
please help :)
Yes you can assign value to the textbox using Model, First of all create a model then link that model with your view. And In Controller assign the value to model and return to the view.
Or At runtime if you want to assign the value to your text box then you can use Ajax call to your controller and get the value.
Please revert in case of any query.
See what i am doing to do the same, Make a custom model with your relevant fields, then assign values to them in controller, and pass this values to View, And that's it. :)
Custom Model
public partial class QuoteParameter
{
public Nullable<System.DateTime> TripStartDateLimit { get; set; }
public Nullable<System.DateTime> TripEndDateLimit { get; set; }
public int PolicyId { get; set; }
}
Controller
public ActionResult Index()
{
QuoteParameter quote = new QuoteParameter();
quote.TripEndDateLimit = DateTime.Now;
quote.TripEndDateLimit = DateTime.Now;
quote.PolicyId = 5;
return View(quote);
}
View
#model EHIC.Models.Models.QuoteParameter
By Razor syntax
<div class="row-fluid span12">
<div class="span4">
<p><strong>Trip Start Date Limit :</strong></p>
</div>
<div class="span5">
#Html.TextBoxFor(model => model.TripStartDateLimit, "{0:dd/MM/yyyy}", new { #class = "form-control", #placeholder = "Policy StartDate Limit", #required = true })
</div>
</div>
<div class="row-fluid span12">
<div class="span4">
<p><strong>Trip End Date Limit :</strong></p>
</div>
<div class="span5">
#Html.TextBoxFor(model => model.TripEndDateLimit, "{0:dd/MM/yyyy}", new { #class = "form-control", #placeholder = "Policy EndDate Limit", #required = true })
</div>
</div>
By HTML Code
<input type="text" class="form-control" id="TripStartDateLimit" name="TripStartDateLimit" value="#Model.TripStartDateLimit"/>
<input type="text" class="form-control" id="TripEndDateLimit" name="TripEndDateLimit" value="#Model.TripEndDateLimit"/>
EDIT
By Click on this button you can send the PolicyId(as an example) to controller, and then you can do whatever you want there..!!!
<a href='../../controller/Edit?PolicyId=#Models.PolicyId'>
<span title='Edit'></span>
</a>
#Html.ActionLink("Edit","Edit", new { id = item.RequestID })
You can find the PolicyId which you sent from the Edit Page..
public ActionResult Edit(int id)
{
//Get your data from Store_procedure..
return View();
}

MVC3 EditorTemplate for a nullable boolean using RadioButtons

I have a property on one of my objects that is a nullable boolean, I want my logic to have true represent Yes, false to be No and null to be N/A. Now because I am going to have multiple properties like this on many different objects it makes the most sense to make an editor and display templates for these properties. I am going to use jQuery UI to apply a visual element of buttonset after this is all working but for now, that's beyond the scope of my problem. My editor template looks like this.
#model bool?
<div data-ui="buttonset">
#Html.RadioButtonFor(x => x, true, new { id = ViewData.TemplateInfo.GetFullHtmlFieldId("") + "Yes"}) <label for="#(ViewData.TemplateInfo.GetFullHtmlFieldId(""))Yes">Yes</label>
#Html.RadioButtonFor(x => x, false, new { id = ViewData.TemplateInfo.GetFullHtmlFieldId("") + "No" }) <label for="#(ViewData.TemplateInfo.GetFullHtmlFieldId(""))No">No</label>
#Html.RadioButtonFor(x => x, "null", new { id = ViewData.TemplateInfo.GetFullHtmlFieldId("") + "NA" }) <label for="#(ViewData.TemplateInfo.GetFullHtmlFieldId(""))NA">N/A</label>
</div>
My problem is that under no circumstances can I get this editor template to show the current value of the model correctly. Because I am not rendering a property of a model at this scope but the model itself, the built in logic in MVC3 will not set the checked property correctly because of a check that is made to verify the name is not empty or null (See MVC3 source, InputExtensions.cs:line#259). I can't set the checked attribute dynamically by comparing to the Model because the browser checks the radiobutton on the presence of the checked attribute not it's value, so even though my radio buttons would look like the following the last one is still the one selected.
<div class="span-4" data-ui="buttonset">
<input checked="checked" id="MyObject_BooleanValueYes" name="MyObject.BooleanValue" type="radio" value="True" /><label for="MyObject_BooleanValueYes">Yes</label>
<input checked="" id="MyObject_BooleanValueNo" name="MyObject.BooleanValue" type="radio" value="False" /><label for="MyObject_BooleanValueNo">No</label>
<input checked="" id="MyObject_BooleanValueNA" name="MyObject.BooleanValue" type="radio" value="null" /><label for="MyObject_BooleanValueNA">N/A</label>
</div><span class="field-validation-valid" data-valmsg-for="MyObject.BooleanValue" data-valmsg-replace="true"></span> </div>
I can't conditionally add the HtmlAttribute using something like if?truevalue:falsevalue becuase the true/false parts would be of different anonymous types and I get an error.
I'm struggling on how this should be done and am hoping one of you have a suggestion on how to tackle this problem?
#model bool?
<div data-ui="buttonset">
#{
Dictionary<string, object> yesAttrs = new Dictionary<string, object>();
Dictionary<string, object> noAttrs = new Dictionary<string, object>();
Dictionary<string, object> nullAttrs = new Dictionary<string, object>();
yesAttrs.Add("id", ViewData.TemplateInfo.GetFullHtmlFieldId("") + "Yes");
noAttrs.Add("id", ViewData.TemplateInfo.GetFullHtmlFieldId("") + "No");
nullAttrs.Add("id", ViewData.TemplateInfo.GetFullHtmlFieldId("") + "NA");
if (Model.HasValue && Model.Value)
{
yesAttrs.Add("checked", "checked");
}
else if (Model.HasValue && !Model.Value)
{
noAttrs.Add("checked", "checked");
}
else
{
nullAttrs.Add("checked", "checked");
}
}
#Html.RadioButtonFor(x => x, "true", yesAttrs) <label for="#(ViewData.TemplateInfo.GetFullHtmlFieldId(""))Yes">Yes</label>
#Html.RadioButtonFor(x => x, "false", noAttrs) <label for="#(ViewData.TemplateInfo.GetFullHtmlFieldId(""))No">No</label>
#Html.RadioButtonFor(x => x, "null", nullAttrs) <label for="#(ViewData.TemplateInfo.GetFullHtmlFieldId(""))NA">N/A</label>
</div>
How about some extension method fun to keep that "one line to rule them all". :-)
public static class DictionaryHelper
{
// This returns the dictionary so that you can "fluently" add values
public static IDictionary<TKey, TValue> AddIf<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, bool addIt, TKey key, TValue value)
{
if (addIt)
dictionary.Add(key, value);
return dictionary;
}
}
And then in your template file you simply change the signature of how you are adding the additional parameters including the checked="checked" attribute to the element.
#model bool?
<div data-ui="buttonset">
#Html.RadioButtonFor(x => x, true, new Dictionary<string,object>()
.AddIf(true, "id", ViewData.TemplateInfo.GetFullHtmlFieldId("") + "Yes")
.AddIf(Model.HasValue && Model.Value, "checked", "checked")
) <label for="#(ViewData.TemplateInfo.GetFullHtmlFieldId(""))Yes">Yes</label>
#Html.RadioButtonFor(x => x, false, new Dictionary<string,object>()
.AddIf(true, "id", ViewData.TemplateInfo.GetFullHtmlFieldId("") + "No")
.AddIf(Model.HasValue && !Model.Value, "checked", "checked")
) <label for="#(ViewData.TemplateInfo.GetFullHtmlFieldId(""))No">No</label>
#Html.RadioButtonFor(x => x, "null", new Dictionary<string,object>()
.AddIf(true, "id", ViewData.TemplateInfo.GetFullHtmlFieldId("") + "NA")
.AddIf(!Model.HasValue, "checked", "checked")
) <label for="#(ViewData.TemplateInfo.GetFullHtmlFieldId(""))NA">N/A</label>
</div>
The problem is that you need to set the checked attribute because the Html.RadioButtonFor does not check a radio button based on a nullable bool (which appears to be a flaw).
Also by putting the radio buttons inside of the label tag, you can select value by clicking the label.
Shared/EditorTemplates/Boolean.cshtml
#model bool?
<label>
<span>n/a</span>
#Html.RadioButtonFor(x => x, "", !Model.HasValue ? new { #checked=true } : null)
</label>
<label>
<span>Yes</span>
#Html.RadioButtonFor(x => x, true, Model.GetValueOrDefault() ? new { #checked = true } : null)
</label>
<label>
<span>No</span>
#Html.RadioButtonFor(x => x, false, Model.HasValue && !Model.Value ? new { #checked = true } : null)
</label>
You just need to handle the special null case like so:
<label class="radio">
#Html.RadioButtonFor(x => x.DefaultBillable, "", new { #checked = !this.Model.DefaultBillable.HasValue })
Not set
</label>
<label class="radio">
#Html.RadioButtonFor(x => x.DefaultBillable, "false")
Non-Billable
</label>
<label class="radio">
#Html.RadioButtonFor(x => x.DefaultBillable, "true")
Billable
</label>
You can use a #helper to simplify the accepted answer:
#model bool?
<div data-ui="buttonset">
#Radio(true, "Yes", "Yes")
#Radio(false, "No", "No")
#Radio(null, "N/A", "NA")
</div>
#helper Radio(bool? buttonValue, string buttonLabel, string buttonId)
{
Dictionary<string, object> attrs = new Dictionary<string, object>();
// Unique button id
string id = ViewData.TemplateInfo.GetFullHtmlFieldId("") + buttonId;
attrs.Add("id", id);
// Check the active button
if (Model == buttonValue)
{
attrs.Add("checked", "checked");
}
#Html.RadioButtonFor(m => m, buttonValue, attrs) <label for="#id">#buttonLabel</label>
}
using Canvas example above I built a customization model and view so you can control the values via a model and edit them in code, bools aren't always a yes/no/(n/a) so Here's how it looks in MVC5.
using a generic model for the nullable bool
public class Customisable_NullableRadioBool
{
public bool? Result { get; set; }
public string TrueLabel { get; set; }
public string FalseLabel { get; set; }
public string NullLabel { get; set; }
public string AttributeTitle { get; set; }
}
Here's the CSHTML to be stored in:
~/Views/Shared/EditorTemplates/Customisable_NullableRadioBool.cshtml
#model Customisable_NullableRadioBool
#Model.AttributeTitle<br />
<div class="control-group">
<label>
#Html.RadioButtonFor(x => x.Result, "", !Model.Result.HasValue ? new { #checked = true } : null)
<span>#Model.NullLabel</span>
</label>
<br />
<label>
#Html.RadioButtonFor(x => x.Result, true, Model.Result.GetValueOrDefault() ? new { #checked = true } : null)
<span>#Model.TrueLabel</span>
</label>
<br />
<label>
#Html.RadioButtonFor(x => x.Result, false, Model.Result.HasValue && !Model.Result.Value ? new { #checked = true } : null)
<span>#Model.FalseLabel</span>
</label>
</div>
And then you can reference the generic class and the editor template through the rest of your project and render the editor template like this.
#Html.EditorFor(m => m.YourCustomisable_NullableBool, "Customisable_NullableRadioBool")
And the rendered output examples

Resources