I have an Enum list. I create these check boxes with the Enum list dynamically.
Here is the Enum list:
[LocalizableDescription(#"BankPos", typeof(Resources.DisplayNames))]
BankPos = 1,
[LocalizableDescription(#"PrarkingPlace", typeof(Resources.DisplayNames))]
PrarkingPlace = 2,
[LocalizableDescription(#"OutdoorPlace", typeof(Resources.DisplayNames))]
OutdoorPlace = 4`
I created the check box with foreach in Html tag .
Here are the check boxes:
<div class="checkbox-container">
<% foreach (var feature in Model.Features)
{%>
<label>
<input type="checkbox" name="q5" />
<span><%= feature.Text %></span>
</label>
<%}
%>
</div>
Up to here every thing is fine. My check boxes are create in correctly .
My problem is, how can I pass these check box values into controller?
As I said I want to pass them multiple.
Here is my controller
[HttpPost]
public ActionResult Review(ReviewMemberRatingViewModel model, HttpPostedFileBase picUpload)
{
return null;
}
You need to include the checkboxes in your model, and bind the values to them. So when you change a value on the model, it will be available in your action result. You could generate your inputs with numerical indexes or there is a great example of what you are doing while taking it a step further with an editor template here.
Related
Experimenting with Blazor (Server, if that makes any difference), and I'm having difficulty getting binding to a MultiSelectList to work....
Bit of background: I'm dealing with EF Core and have a Many-to-Many relationship, let's say between people and cars. I'm currently loading a page that shows the existing details, and allowing the user to update this page.
So in my Service, I load my Person entity from the DB, and this includes the details of all the cars they currently own. I also load the list of all the available cars. My Service method then creates a MultiSelectList and adds it to my ViewModel (to be returned to the Razor Page):
Service method
vm.CarSelector = new MultiSelectList(
allCars,
nameof(Car.CarId),
nameof(Car.Name),
person.OwnedCars.Select(oc => oc.CarId));
This is fictitious code, but I hope you get the picture. When debugging this (in the Service method) I can see that this MultiSelectList has an entry for every car, and the ones that are already selected are showing as Selected. Great!
Blazor Razor Page
So, this is where I come unstuck.... I can't work out how to do the two-way data-binding of a Razor control to this object.
I'm trying to use an <InputSelect />, but that might not be the best control to use.
ideally (actually, that's more of a "must have"), each option should have CheckBox.
I'm wondering whether the use of a MultiSelectList really buys me anything
Checkboxes are a bit different in blazor. Normally you would use the bind-value attribute on an input element as shown below, however, this is not recommended as you will only be able to read the value and NOT update the UI by changing the boolean value via code:
<input type="checkbox" #bind-value="#item.Selected"/>
Instead, use the #bind syntax for checkboxes, which is much more robust and will work both ways (changing the bound boolean value from code & interacting with the checkbox on the UI). See the syntax below:
<input type="checkbox" #bind="#item.Selected"/>
The bind attribute will automatically bind your boolean value to the "checked" property of the html element.
Also make sure you are binding to the "Selected" property rather than the "Value" property.
Using the built in bind will prevent the need to manually setup events as you did in your answer. You can also get rid of the if/else block and merge your code into a single code flow since you are now binding to the boolean rather than setting the checked property manually. If you still need to tap into an event to fire off some process(maybe hiding parts of UI on checking a box), I'd suggest using the onclick event and manually passing in the multiselect Item for each line. Here is the final code:
#foreach(var item in list)
{
<input type="checkbox" #bind="item.Selected" #onclick="(()=>handleClick(item))" />
}
#foreach(var item in list.Where(x=>x.Selected))
{
<p> Item #item.Text is Selected</p>
}
#code {
MultiSelectList list = new MultiSelectList(new List<Car> { new Car { Year = 2019, Make = "Honda", Model = "Accord" }, new Car { Make = "Honda", Model = "Civic", Year = 2019 } });
private void handleClick(SelectListItem item)
{
//Do something crazy
}
}
I got this to work with a component that takes the MultiSelectList as a parameter. There may be more elegant ways to achieve this (please do update if you know of a better way).
#using Microsoft.AspNetCore.Components
#using Microsoft.AspNetCore.Mvc.Rendering
<div class="multiselect">
<div id="checkboxes">
#foreach (var item in this.Items)
{
<div>
<label for="#item.Value">
#if (item.Selected)
{
<input type="checkbox" id="#item.Value" checked="checked" #onchange="#((e) => CheckboxChanged(e, item.Value))" />
}
else
{
<input type="checkbox" id="#item.Value" #onchange="#((e) => CheckboxChanged(e, item.Value))" />
}
#item.Text
</label>
</div>
}
</div>
</div>
#code
{
[Parameter]
public MultiSelectList Items { get; set; } = null!;
private void CheckboxChanged(ChangeEventArgs e, string key)
{
var i = this.Items.FirstOrDefault(i => i.Value == key);
if (i != null)
{
i.Selected = (bool)e.Value;
}
}
}
I have data in a particular view page(collected from the user) which I need to send to another view page which has a form needing this data. Now I can use:-
1. post method of javascript(jquery)
$().redirect('/Events/Create', {'arg1': 'value1', 'arg2': 'value2'});
or
A form:-
$('#inset_form').html(' < form action="/Events/Create"
method="post"style="display:none;">< input type="text" name="lat"
value="' + latitude + '" />< /form>');
document.forms['vote'].submit();
Now my question is, which method should be chosen?
Also, the '/Events/Create' page has form in the following way:-
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<div class="editor-label">
#Html.LabelFor(model => model.lat)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.lat)---------> THIS field accepts the POSTed data
#Html.ValidationMessageFor(model => model.lat)
</div>
<div>
....OTHER INPUT FIELDS.....
</div>
<p>
<input type="submit" value="Create" />
</p>
}
So, my next question is how do I make the text box 'lat' created by #Html.EditorFor in the form show the POSTed data as its default value. Then, the user can fill other fields and then submit the form.
As per HTTP standards, if a call is not changing the state of the website (i.e. data), you should use a GET request. This means you should provide the user with a link including the proper query string to populate the form on the /Events/Create page.
Also, keep in mind you never send data from view to view in MVC. Everything goes through a controller action so make sure your "Create" action on the "Events" controller accepts the proper arguments to populate the form for submission. If the Model.lat variable has a value in it when rendering the view, the text box will be prepopulated with that value.
Why do you want to POST the data to the second form? If you want to show the form and load it with default values, create a GET action method for it and pass the default values in the url. Although there's nothing stopping you having two POST methods for the same view, the normal approach would be to load the form using a GET, then POST back the data after editing.
[HttpGet]
public ActionResult Create(string lat)
{
MyView view = new MyView();
view.lat = lat;
View(view);
}
[HttpPost]
public ActionResult Create(MyView view)
{
//process posted data after editing
}
The view object here is a ViewModel class containing properties for the data that you will edit on the form. Make your View strongly typed to this ViewModel type.
To invoke the GET method from your jQuery (above):
window.location = "Events/Create?lat=myValue";
I viewed some topics here but I still have a problem with getting values from checkboxes.
Part of Model :
public Dictionary<Language, bool> TargetLanguages { get; set; }
Part of View :
<div class="editor-label">
<label for="TargetLanguages">select target languages</label>
</div>
<div class="editor-field">
<form>
#foreach (var item in Model.TargetLanguages)
{
#Html.CheckBox("TargetLanguages["+item.Key.Name+"]", item.Value)
#item.Key.Name
}
</form>
</div>
Part of Controller :
[HttpPost, ActionName("AddDictionary")]
public ActionResult AddDictionary(FormCollection collection)
{
...
}
And the problem is I don't get any trace of TargetLanguages in my FormCollection. I tried CheckBoxFor but it wasn't help. I tried write check-box manually also.
EDITED : Okay, I just noticed where the problem was. I've got messed up markers and that was the reason why I can't get data from FormCollection.
Create all the checkboxes with the same name. In this sample I'm using 'SelectedTargetLanguages'.
#using (Html.BeginForm())
{
foreach (var item in Model.TargetLanguages)
{
<label>
#Html.CheckBoxFor(m => m.SelectedTargetLanguages, item.value)
#item.KeyName
</label>
}
<br/>
#Html.SubmitButton("Actualizar listado")
}
Then, in your action the parameter must be an array of strings like this:
public ActionResult AddDictionary(string[] selectedTargetLanguages)
Note that the name of the argument is the same name of the checkboxes. (It works even with the different casing).
You should use explicit arguments like this, rather than the generic FormCollection. Anyway, if you use FormCollection, you shpuld also receive the array.
I have asked same type of question previously. Please check the following links
MVC3 #Html.RadioButtonfor Pass data from view to controller
MVC3 #html.radiobuttonfor
I think this might helps you.
Is there any way to mark an option as selected by default, much like the selected attribute in the HTML option tag like <option value="value1" selected>?
If the path value of the tag matches the value of options value it will automatically be selected. You don't need anything special
Is there any way to mark an option as selected by default ???
Just use <spring:option Taglib The first one will be automatically selected
<spring:select name="someProperty">
<spring:option value="">Select one</spring:option>
<spring:option value="someValue">Some value<spring:select>
<!--And so on...-->
<spring:select>
or
<spring:select name="someCollection">
<spring:option value="">Select one</spring:option>
<!--Here goes some List added to request-->
<spring:options itemLabel="propertyNameUsedAsLabel" itemValue="propertyNameUsedAsValue"/>
<!--And so on...-->
<spring:select>
I am assuming you are also using Spring MVC. If you have business logic that requires a certain option to be selected by default, move that business logic to the controller - not the JSP.
#RequestMapping(method = RequestMethod.GET)
public ModelAndView helloWorld(){
ModelAndView model = new ModelAndView("HelloWorldPage");
// first we need to give the countries list to the model
model.addObject("countries", countryService.getAllCountries());
// creating the form
ExampleForm form = new ExampleForm();
// setting the default to Germany (de)
form.setCountryCode = "de";
// adding the form (with the default country set) to the model
model.addObject("form", form);
return model;
}
In the JSP, we pass in the countries to the options and spring will automatically have germany selected:
<form:form method="post" commandName="form">
<%-- other fields ... --%>
<form:select path="countryCode">
<form:options items="${countries}" itemValue="countryCode" itemLabel="countryName"/>
</form:select>
<%-- other fields ... --%>
</form:form>
I need a dropdown list on my page that will allow a user to select their state. Since this is probably a control that will be used elsewhere, I thought it would be a good idea to create an MVC View User Control that could be reused.
I was thinking the control would look something like this:
<select name="" id="">
<option value="AL">Alabama</option>
<option value="AK">Alaska</option>
</select>
And the code in my view would be something like:
<%= Html.RenderPartial("StateDropdownControl") %>
My question is, what's the best way to set the name and id on the control? I'd want to make sure I could have multiple instances of this control on one page, if needed. Also, I'd want to be able to send in the state that should be selected by default.
Would I do it with ViewData somehow?
Corey is on to the right solution. I think declaring specific Model objects for your view makes the views VERY simple and as a side bonus makes them dirt easy to test.
So instead of just passing the ID as the object, you'd probably want to create your own Model object to pass in.
It could look something like this:
public class StateDropDownPresentationModel
{
public string DropDownID { get; set; }
public string SelectedState { get; set; }
}
Obviously, keep adding whatever you need to this model to make your view correct.
Then, you could call it like this:
<%= Html.RenderPartial("/someDirectory/SomeControl.ascx", new StateDropDownPresentationModel { DropDownID = "MyID", SelectedState = "IL" } %>
Then just make sure you put in checks for things like ID being null/blank (that should probably throw an error) and SelectedState being null/blank.
Well you can pass object data to the RenderPartial method in conjunction to the User Control to render, so you could easily do the following:
<%= Html.RenderPartial("/someDirectory/SomeControl.ascx", "MyID") %>
and in the UserControl do the following:
<select name="<%=ViewData.Model%>" id="<%=ViewData.Model%>">
....
Just to be sure, a better way to handle it is to make a simple DTO (data transfer object) to hold that information so you can pass more information to your user control, that you will inevitably need.
Example:
class ComboData
{
string ID {get;set;}
string CssClass {get;set;}
//Other stuff here
}
<%
var comboData = new ComboData {ID = "myID", CssClass = "comboStyle" }
%>
<%= Html.RenderPartial("/someDirectory/SomeControl.ascx", comboData) %>
<select name="<%=ViewData.Model.ID%>" id="<%=ViewData.Model.ID%>" class="<%=ViewData.Model.CssClass%>">
....
Make sure you set the Code behind for the user control to be a generic of type ComboData for this example.
Take a look at the Html.DropDownList helper method. It has a number of overloads that allow you to pass the list data and set the selected item. the simplest version just sets the name of the select.
<%= Html.DropDownList("SelectStates"); %>
If there is a value in the ViewData["SelectStates"] that is of type MultiSelectList then the list will be automatically populated.