I have a table of experiments, and for each experiment I need to be able to turn it on or off. I pass in a list of my experiments to my view, and iterate over them to create table rows.
Table row creation:
<tr>
<td>#experiment.ExperimentId</td>
<td>#experiment.ExperimentName</td>
<td>#experiment.StartDate</td>
//radio button code goes here
</tr>
I've decided to use the radio button helper to generate the two radio buttons for each experiment.
<td>#Html.RadioButton(experiment.ExperimentName, true, false)ON #Html.RadioButton(experiment.ExperimentName, false, false)OFF</td>
I've used the 'ExperimentName' as the input name, as I want each set of radio buttons to be in their own group.
My question is, when I submit this form, how should I bind the data to the post model. I'm looking to create something like this in the model
Experiments
ExperimentOne -> selected radiobutton value
ExperimentTwo -> selected radiobutton value
I'm assuming i'll need to create a Dictionary object, but i'm not sure how to bind the name and the selected value to this. Any help will be greatly appreciated
Since you are dealing with an enabled/disabled situation, I would recommend using a checkbox over two radio buttons. In either case, your model might look something like this:
public class ExperimentsViewModel
{
// other properties
public IDictionary<int, bool> ExperimentStatus { get; set; }
}
And you would bind to this in your view like so:
<td>#Html.CheckBox("ExperimentStatus[0]", Model.ExperimentStatus[0]) Enabled</td>
The model binder treats dictionaries like an array or a list; use can use indexes (keys in this case) to bind to a value. You can also use a string key instead of an integer.
If you must use radio buttons, your view would look like this:
<td>
#Html.RadioButton("ExperimentStatus[0]", true, Model.ExperimentStatus[0], new {id = "ExperimentStatus_0_ON"})#:ON
#Html.RadioButton("ExperimentStatus[0]", false, Model.ExperimentStatus[0], new {id = "ExperimentStatus_0_OFF"})#:OFF
</td>
You'll have to manually include the id attributes like this because otherwise the ON and OFF inputs would have the same ids, which is invalid HTML.
Related
I have a question about a user control I am creating.
The user control is only a ComboBox (with personal settings), with a datasource from a list from a database.
This list is very simple, it’s a list of vehicule type.
Currently, my database looks like this :
Id_Vehicule_Type Type Description
1 Car Car description
2 Truck Truck description
3 SUV SUV description
I can link my data to my user control, there’s no problem with that.
What I want is an option (property) to add or remove an “All” field.
If I create a new vehicule, I would like to be able to choose between Car/Truck/SUV.
If I search for a vehicule, I would like to be able to choose between Car/Truck/SUV/All. All will search for any vehicule type.
I already add a property to my user control, but for the moment, I retrieve the list from my database in the «Set» section of my property. It check if the _IncludeAll is true, then add a new item in the list before binding it, but I don’t find this really « well-made ».
List<VehiculeType> vehiculeTypes = Database.GetAllVehiculeType();
if (this._IncludeAll)
{
vehiculeTypes.Add(new VehiculeType(-1, "(All)"));
this.cbVehiculeTypes1.SelectedValue = -1;
}
I have no problem retrieving the id / type / description from my user control. I only can’t figure out how to manage this « option ».
Thank you and have a nice day.
In my model class for view, I have an enum type property SubjectType:
[Required(ErrorMessage = "This field is required.")]
public SubjectType SubjectType { get; set; }
I would like to create drop-down list for this property. But by default I would like it to be set to null so that user has to choose something, and the validation message will be shown if he would try to submit form without choosing any option.
What is the best approach to achieve this?
I was trying to change SubjectType property to nullable, and setting the default value to null, but the validation still passed on this field (somehow) and the form was submitted to the server. By default the value of this field was set to the first value from enum definition. No JavaScript allowed, I'd like to keep everything in code-behind. I will be grateful for any advice.
so far i render it this way:
#Html.DropDownList("SubjectType", EnumHelper.GetSelectList(typeof(SubjectType)))
#Html.LabelFor(model => model.SubjectType)
#Html.ValidationMessageFor(model => model.SubjectType)
You are able to solve problem doing this:
Change submit button to button with onclick action, then validate it in javascript and if form and this enum field is valid submit the form using jQuery.
Edit: I think the problem was three fold. first your attribute is named SubjectType but your dropdown is named Type so it cannot be bound to SubjectType.
second, Apparently you have to use #HTML.dropdownlistfor(). I did a viewsource with my two different versions dropdown and dropdownlistfor and dropdownlistfor is the only one that adds the validation classes (see below)
third, we needed to add the option label parameter "Select a Type" as a default value. I'm sure it'll work for you now.
In Model:
[Required(ErrorMessage = "Error!")]
public string SubjectType{ get; set; }
In Html:
#Html.DropDownListFor(m => m.SubjectType, new SelectList(Enum.GetNames(typeof(SubjectType))), "Select a Type", new { #class = "pretty" } )
now I see you have a helper that furnishes an enumerable I think that will be just fine if you replace my second param with that.
Dropdownlist vs DropdownlistFor Rendering of Select Element:
DropdownList:
<select name="SubjectType" class="pretty" id="SubjectType">...</select>
DropdownListFor:
<select name="SubjectType" class="pretty" id="SubjectType" data-val-required="Error!" data-val="true">...</select>
As you can see data-val-required and data-val classes are missing when doing a simple dropdown thus not turning on validation FOR that attribute. Sorry for all the pain of getting here. Don't forget to mark me right if it works.
This is a two part question. First, I understand that if use this in my Model:
[Required(ErrorMessageResourceType = typeof(Resources.CustomerSatisfactionSurvey), ErrorMessageResourceName = "Page1Question1Required")]
public int? LikelyToReturn { get; set; }
And then this in my View:
#for (var c = 0; c < 11; c++)
{
#Html.RadioButtonFor(model => Model.LikelyToReturn, #c)
}
That I have now created an association between the object in the model "LikelyToReturn" and the radio button group by the same name in the view. When the user selects a radio button and clicks the Submit button, the model is updated, and LikelyToReturn is filled with the selected value. That happens without me having to specifically emaciate the two.
Question 1: How and why does that work? I'm thinking it has to do with the [Required...] tag, but I'd like to be sure.
Question 2: How would one create such an association with the field is NOT required? I have other model variables & form fields that have matching names, but are not required, and they are not associated automatically.
Thanks!
This has nothing to do with your [Required] attribute. When you submit a form, a series of name/value pairs are sent back to your controller method based on the name attribute of your form controls (input, select and textarea elements).
In your case you have a radio button group (your generating 11 controls with <input type="radio" name="LikelyToReturn" ... />) with values 0 - 10. If you select the 3rd radio button and submit, the posted form data will be LikelyToReturn: 2.
On the controller side, the DefaultModelBinder is responsible for reading the form data (and other values such as route data) and matching up the posted values with your model properties. If your model contains a property named LikelyToReturn then its value will be set to 2.
The [Required] attribute is a validation attribute and is used to validate your property. In your case, if you manually included an additional radio button
<input type="radio" name="LikelyToReturn" value="" />
and selected it, then validation would fail because it would set LikelyToReturn=null; and an error would be added to ModelState
If you have other properties in your model that are not being bound, then it is most likely because (1) the name attribute of the control does not match your property name, which is why you should always use the strongly typed html helpers to generate the html in your forms, or (2) your trying to bind to fields rather than properties (i.e. no { get; set; })
I am creating a options list using knockout data-binding. Basically on my server side i have an enum
public enum CarType
{
Saloon = 1,
Hatch = 2,
Convertable = 3,
SUV = 4
}
This basically get created into a dictionary on the server side and is sent back to the client side.
So the above enum will return to the client side as an object with a key and value.
My viewmodel is like so:
this.carName= ko.observable();
this.carType = ko.observable();
My options binding is as below:
<select class="form-control" data-bind="options: $root.carTypes, optionsText: 'value', optionsValue: 'key', value: carType"></select>
So basically when i press the edit button this view will get rendered correctly first time round. But if i cancel the edit page and re-open it then it selects the first element in the options list.
Not sure if i am doing anything wrong or if knockout behaves differently with dictionarys?
The car type object returned is an array of dictionary elements example below
[{key="1", value="Saloon"}, {key="2", value="Hatch"} .......
I'm not sure if I understand your problem. Do you wish to avoid the first item being selected? If so, take a look at the optionsCaption in the docs: http://knockoutjs.com/documentation/options-binding.html#parameters
optionsCaption
Sometimes, you might not want to select any particular option by
default. But a single-select drop-down list usually starts with some
item selected, so how can you avoid preselecting something? The usual
solution is to prefix the list of options with a special dummy option
that just reads “Select an item” or “Please choose an option” or
similar, and have that one selected by default.
This easy to do: just add an additional parameter with name
optionsCaption, with its value being a string to display. For example:
<select data-bind='options: myOptions, optionsCaption: "Select an item...", value: myChosenValue'></select>
KO will prefix the list of items with one that displays the text
“Select an item…” and has the value undefined. So, if myChosenValue
holds the value undefined (which observables do by default), then the
dummy option will be selected. If the optionsCaption parameter is an
observable, then the text of the initial item will update as the
observable’s value changes.
I am creating an invoice application and in the section where the user can enter line items, some of the fields will include: Quantity, Price, Extended Price, Description, etc.
If the user enters something into any of the fields, the corresponding fields are required, but if no data is entered into any field, then nothing is required in the corresponding fields. What is an efficient and clean way of doing this without doing a bunch of if statements?
I guess this is like doing validation if only one textbox has text.
You could try something like this in the ServerValidate event of a CustomValidator.
// test for all textboxes having some text in them...
e.IsValid = (from TextBox c in this.Controls
where c is TextBox
select c).All(tb => !string.IsNullOrEmpty(tb.Text));
That might need some tinkering to get right - but you get the idea. Change accordingly to test for all textboxes being blank.
You could also use jQuery for the client side validation in your CustomValidator
function clientValidate(sender, e) {
// get array of textboxes with a common css class
var textBoxes = $("#SomeCssSelector input").val();
// loop here to test for having text or no text.
e.IsValid = ... ;
}
You could create a TextBox array and store references to all related text boxes in the array. When ever you need to you could then iterate over the array in a for loop looking for the first item with a value. As soon as you find one with a value you know all the other items in that array also need values.
Additionally, if you have other groups of related text boxes you could create additional arrays to help keep them grouped.
Several ways if this is ASP.NET.
Use field validators that are available in ASP.NET.
Use JavaScript for Windows Forms.
For Windows Forms, also use control validators, or you could use a simple function where you pass a control array. If any item in the array is filled then it requires all items to be filled by returning which fields are not filled, etc.