I have an MVC3 application with Razor and I created a View that inside renders a Partial View. This is how the main View looks like:
#{Html.RenderPartial("_SearchFilters", Model.SearchFilters);}
#* Other HTML elements *#
Inside the _SearchFilters Partial View I have the following DropDownLists inside a Form element:
Choose Year
#Html.DropDownListFor(m => m.Year, new SelectList(Model.YearsList, "Value", "Text"), DateTime.Now.Year)
Choose Month
#Html.DropDownListFor(m => m.Month, new SelectList(Model.MonthsList, "Value", "Text"), Model.Month.ToString(), new { #disabled = "disabled" })
<input type="submit" value="Display" />
I would like that upon Submit the two DropDownLists keep their status, namely the value selected by the user, when the View is reloaded with the filtered data.
Is there any way to do it without using AJAX?
UPDATE
The ViewModel is as follows:
public class TableSearchFiltersViewModel
{
public bool YTM { get; set; }
public int? Month { get; set; }
public int? Year { get; set; }
public IEnumerable<SelectListItem> YearsList
{
get
{
return Enumerable.Range(2011, (DateTime.Now.Year - 2011 + 4)).Select(m => new SelectListItem
{
Value = m.ToString(),
Text = m.ToString(),
}).OrderBy(m => m.Value);
}
}
public IEnumerable<SelectListItem> MonthsList
{
get
{
return Enumerable.Empty<SelectListItem>();
}
}
}
Thanks
Francesco
When you submit the form to the corresponding controller action, this action should take as input parameter some view model. This view model's properties will be bound from the input fields contained in the form including the selected value of the two dropdowns. Then the controller action could return the same view which will preserve the selected values of the dropdown boxes.
I would recommend you to use Editor Templates though instead of rendering partials as this will ensure proper naming of the dropdowns and eventually preserve selected values:
#Html.EditorFor(x => x.SearchFilters)
I don't have IDE at this time so couldn't test but this might work:
Choose Month
EDIT:
#Html.DropDownListFor(m => m.Month,
Model.MonthsList.Select(
t => new SelectListItem {
Text = t.Name,
Value = t.Value,
Selected = t.Value == Model.Month,
},
Model.Month.ToString(), new { #disabled = "disabled" })
Without ajax not, or you will have to repost the whole form. MVC is a web framework which is not dynamic like a winforms application. You will have to post the changes to your controller and reload the page with the necessary changes, or use ajax to reload these changes.
You could provide the default values for Year and Month properties (to be selected at the first request) and bind those instead of the hardcoded startup values you provided.
So instead of:
#Html.DropDownListFor(m => m.Year, new SelectList(Model.YearsList, "Value", "Text"), DateTime.Now.Year)
Which btw seems erroneous, as selected value (which I suppose DateTime.Now.Year is in your example) should be provided as SelectList's constructor (instead of DropDownListFor method's) argument. DropDownListFor method doesn't have a 'selected value' argument.
You could write:
#Html.DropDownListFor(m => m.Year, new SelectList(Model.YearsList, "Value", "Text", Model.Year))
and analogously in the second dropdown.
This will make dropdowns keeps the selected values when rendered using the posted model (as Model.Year and Model.Month would hold those). So you should make sure those values won't get overwritten with default ones after subsequent submits.
Related
I use JavaScript for populating a list called "groups".
Then I create a DropDownList:
<div class="form-group">
<div class="col-md-10">
#Html.DropDownList("groups", new SelectList(string.Empty, "Value", "Text"), "Choose...")
</div>
</div>
The DropDownList displays fine.
What I need to do is assign the chosen value from "groups" to the model.group_id.
I don't know how to get the item chosen in DropDownList in the controller method. Thank you for any advice.
If you need it to bind to group_id then use that as the name:
#Html.DropDownList("group_id", ...)
Or, even better, use the strongly-typed helper:
#Html.DropDownListFor(m => m.group_id, ...)
Assuming you have a form field in your form with the name group_id like this and you want to set the selected value from your dropdown to that field for some reason,
#Html.HiddenFor(s=>s.group_id)
<div class="form-group">
#Html.DropDownList("groups",new SelectList(string.Empty, "Value", "Text"), "Choose...")
</div>
You can listen to the change event of the dropdown and get the selected option value and set to the group_id
$(function(){
$("#groups").change(function(e){
var v=$(this).val();
$("#group_id").val(v);
});
});
I am not sure why you are loading the dropdown content via javascript, but there are other better ways to render a dropdown and pass the selected value back to your controller as explained in this post.
Add a SelectedGroup property to your view model
public class CreateSomethingViewModel
{
public int SelectedGroup {set;get;}
public List<SelectListItem> Groups {set;get;}
}
and in your GET action, If you want to load the Groups, you can do it
public ActionResult Create()
{
var vm = new CreateSomethingViewModel();
//Hard coded for demo. You may replace with your db entries (see below)
vm.Groups = new List<SelectListItem> {
new SelectListItem { Value="1","Chase bank" },
new SelectListItem { Value="2","PNCbank" },
new SelectListItem { Value="3","BOA" }
};
return View(vm);
}
And in your view
#model CreateSomethingViewModel
#using(Html.BeginForm())
{
#Html.DropDownListFor(s=>s.SelectedGroup,Model.Groups)
<input type="submi" />
}
With this you do not need to use any js code ( Even if you load the dropdown content via javascript), when user changes the dropdown option value, It will be set as the value of the SelectedGroup property.
[HttpPost]
public ActionResult Create(CreateSomethingViewModel model)
{
// check model.SelectedGroup
// to do : Save and return/redirect
}
I have a dropdown I want to add to my _Layout.cshtml page in MVC 5. This is returned from Reference data in my Database - it is for CarTypes. There are 4 different types of car model that can be selected - Saloon, 4X4, Estate and Hatchback.
I created a CarTypesViewModel as below:
public IEnumerable<SelectListItem> CarTypesList { get; set; }
public string SelectedCarType { get; set; }
I then have a view :
#using (Html.BeginForm("SomeAction", "SomeController", FormMethod.Get))
{
//Just a html div here perhaps?
#Html.DropDownListFor(model => model.SelectedCarType, Model.CarTypesList)
}
Within the layout i have the following:
<li id="selectedcar">#Html.Action("Index", "CarTypes")</li>
This then goes to this action in my CarTypes controller:
var model = new CarTypesViewModel
{
CarTypesList= products.Select(p => new SelectListItem
{
Value = p.Id.ToString(CultureInfo.InvariantCulture),
Text = p.Name
})
};
return View(model);
This is returning the data to the Dropdown list. However what I really want is for a Value to appear like Please Select Your Car Type as the first item in the list - what is the best way to achieve that as I dont want to store that as a value in my database?
#Html.DropDownListFor(model => model.SelectedCarType,
new SelectList(Model.CarTypesList, "Value", "Text"),
"--- Please Select Your Car Type ---",
new { #class = "form-control" }
)
Pass in the optionLabel argument to DropDownListFor.
See: http://msdn.microsoft.com/en-us/library/ee703561(v=vs.118).aspx
#using (Html.BeginForm("SomeAction", "SomeController", FormMethod.Get))
{
//Just a html div here perhaps?
#Html.DropDownListFor(model => model.SelectedCarType, Model.CarTypesList, "Please Select Your Car Type")
}
This should do it.. (Adding your custom text as 3th element.)
I have created a DropDownList which is initialized from code behind like that :
Code Behind :
List<SelectListItem> ddlIsActivated = new List<SelectListItem>
{
new SelectListItem
{
Text = "Activated",
Value = "0"
},
new SelectListItem
{
Text = "Not activated",
Value = "1"
}
};
ViewBag.ddlIsActivated = ddlIsActivated;
View :
<div class="row">
<div class="form-group col-xs-3">
#Html.DropDownList("IsActivated", ViewBag.ddlIsActivated as List<SelectListItem>, "Default")
</div>
</div>
When I click directly on the search button after the load, the DropDownList has "Default" as the first item and my URL looks like that :
http://localhost:51817/Log?SearchString=&IsActivated=
Is it possible to specify that all parameters with an empty value might not be passed on the URL ?
In case of the DropDownList, is it possible to avoid the param "IsActivated" when the "Default" is Selected ?
Sure one way is when the submit button is clicked or activated, you set the fields that are the default value to disabled. then they don't go in the post.
Example of using jQuery onsubmit:
How to use jQuery to onsubmit and check if the value is 2 - 5 characters?
You can try having a separate viewmodel, with properties for the list of options and the selected option. In the GET request action method, you can populate this list and render the view, and in the POST action method, you can exclude this property during model binding, so that only the selected item property will get bound. Thus, you don't need ViewBag or routeValues or querystring parameters, and your URL will always look clean.
EDIT:
This is how you might do it.
public class ViewModel
{
public int SelectedId { get; set; }
public Dictionary<int,string> OptionList { get; set; }
}
And then in your view,
#Html.DropDownListFor(model => model.SelectedId, new SelectList(Model.OptionList, "Key", "Value"), null, null)
In your GET action method,
Dictionary<int,string> OptionList = GetOptionList(); // Populate from DB
return View(new ViewModel { OptionList = OptionList });
Also, remember to [Bind(Exclude="OptionList")] in your POST action method.
I am working with a list of string items in mvc that needs to be selected from a drop down list. The drop down list is binding fine, and value's are setting fine, but even though the current item being iterated matches an item in the drop down list it isn't being pre-selected as it's value, can anyone point me in the right direction?
#for (var i = 0; i < Model.StringList.Count; i++)
{
if (BL.Helpers.StringHelpers.Validate(Model.DisplayStringSegments[i]))
{
<div id="editor-field">
#Html.DropDownListFor(m => m.StringList[i], Model.PosterOptions, String.Empty, new { })
</div>
}
else
{
<div id="editor-label">#Model.StringList[i]</div>
#Html.HiddenFor(model => model.StringList[i])
}
}
So for this case, the Options is a list of strings holding only one value, "Test" -> set both as Text and Value;
PosterOptions.Add(new SelectListItem() { Text = "Test", Value = "Test" });
Can anyone tell me why the current StringList[i] isn't being pre selected, even though it has the value of "Test" ?
For anyone that comes across this;
I had to "Hack" a solution, I did this by:
Changing my ViewModel's (Model.Options)
List<SelectListItem> to a List<string>
Changing my drop down list selection to the following, forcing the selected value;
<div id="editor-field">
#{
string currentString = Model.StringList.ElementAt(i).ToString();
}
#Html.DropDownListFor(m => m.StringList[i], new SelectList(Model.Options, currentString), String.Empty, new {})
</div>
Perhaps there is a better way, but this works!
Another way could be setting the current selected item during the list creation, like this:
PosterOptions.Add(new SelectListItem() { Text = "Test", Value = "Test", Selected = true });
I had the same issue and your response helped me. I don't think that's a "hack" though. Because in your question you were using the same SelectList for all the dropdownlists so even though you mention you didn't want to create multiple lists for the drop downs I can't see another way when you have multiple drop downs as you need to specify different selected values.
As a small refactoring you can get rid of the temp variable and access the selected value directly like this:
#Html.DropDownListFor(m => m.StringList[i], new SelectList(Model.Options, Model.StringList[i]), String.Empty, new {})
In your example you don't need to distinguish between text and value but in my case it was required. When that's necessary it can be accomplished by providing the value and text field names for the SelectList. For example, say you need multiple dropdowns with Country values such as:
Country class:
public class Country
{
public string Code { get; set; }
public string Name { get; set; }
}
Model:
public List<string> CustomerCountryList { get; set; }
public IEnumerable<Country> CountryList { get; set; }
and the View:
#Html.DropDownListFor(m => m.CustomerCountryList[i], new SelectList(Model.CountryList, "Code", "Name", Model.CustomerCountryList[i]))
I'm creating a question/answer page that contains multiple object types (radio button, dropdown, check boxes).
Id QuestionText AnswerId AnswerText ObjectType
1 text one 1 Personal DropDown
1 text two 2 Business DropDown
2 Text three 3 Direct Deposit CheckBox
2 text four 4 Some Answer CheckBox
I have a model that contains a list of all questions, answers, and object types.
How can I populate (as an example) the dropdownlistfor with only two items out of the list, then populate a group of related checkboxes, then populate a group of related radio buttons?
The dropdownlistfor looks to enumerate on a model.
My code which doesn't work:
#if (Model != null)
{
for (int i = 0; i < Model.Count; i++)
{
if (Model[i].AdditionalQuestionTypeId == 1)
{
#Html.DropDownListFor(model => model[i].AdditionalQuestionId, ((IEnumerable<Curo.Web.InterAcct.Models.AdditionalQuestionAnswerModel>)Model[i].AnswerText)
.Select(option => new SelectListItem
{
Text = (option == null ? "None" : option.Description),
Value = option.Id.ToString(),
Selected = (Model != null) && (option.Id == Model[i].AdditionalQuestionId)
}), "Choose...")
It's not the best idea to clog up your view with a bunch of logic. That is actually not the desired approach of MVC.
Use this logic in your controller and not the View.
Create you options in the controller that you want for the desired scenario and set the options to the property on the Model. Then your view will simply bind to that property.
public class MyModel {
public string MyValue { get; set;}
public List<SelectListItem> Options { get; set; }
}
public ActionResult MyAction(){
MyModel model = new MyModel();
// populate options here
model.Options = new List<SelectListItem>();
return View(model);
}
Then your view:
#Html.DropDownListFor(m => m.MyValue, m => m.Options)
It's hard to tell from your code, but I think you are almost there. You need to do the dropdownlistfor statement with an IEnumerable, but your syntax appears to be off:
#Html.DropDownListFor(model => model[i].AdditionalQuestionId, new SelectList(Model.Answers.Where(f=>**Some code to select what values you want**), "Id", "Description", Model[i].AdditionalQuestionId))
It would help to see an error message, but I think it is just syntax at this point.