I have a dropdown list rendered from a database, just need to be able to set an existing value (if it exists). _jobService.GetTenancyForJob gets a value if one already exists and the other service just returns an id and value for each item. I need to be able to set the selected list item here in the controller but just struggling with the syntax (yeah it's using viewbag just for testing will be using ViewModel).
I've done this before in a wide variety of ways just wondering how it would be done in this scenario... Any pointers appreciated.
var jobTenancies = _jobService.GetTenancyForJob(id);
var getTenancies = _jobService.GetAllJobTenancies();
var tenancyList = getTenancies.Select( t => new SelectListItem()
{
Text = t.JobTenancyName,
Value = t.Id.ToString()
}).ToList();
tenancyList.Insert(0, new SelectListItem() { Text="", Value = "" } );
Viewbag.TenancyList = tenancyList;
Edit: in the view
<div class="control-group">
#Html.BootstrapLabelFor(model => model.TenancyName)
<div class="controls">
#Html.DropDownListFor(x=>x.TenancyId, (List<SelectListItem>)ViewBag.TenancyList)
#Html.BootstrapValidationMessageFor(model => model.TenancyId)
</div>
</div>
You need to set the value of property TenancyId in the controller before you return the View. If the value matches the value of one of your options then that option will be selected when the view is displayed. Note also you should not be adding a 'empty' option by inserting an additional SelectListItem (which adds <option value="">), but rather use the overload of DropDownListFor() that accepts optionLabel which correctly adds an option with a null value (<option value>). As you indicated you intend to use a view model, it might include
public class TenancyVM
{
[Required(ErroMessage = "Please select tenancy")]
[Display(Name = "Tenancy")]
public int? TenancyID { get; set; }
....
public SelectList TenancyList { get; set; }
}
Controller
public ActionResult Edit(int id)
{
TenancyVM model = new TenancyVM();
model.TenancyID = jobService.GetTenancyForJob(id);
ConfigureEditModel(model);
return View(model);
}
// Gets called in the GET and in POST method if the view is returned
private void ConfigureEditModel(TenancyVM model)
{
var tenancies = _jobService.GetAllJobTenancies();
model.TenancyList = new SelectList(tenancies , "Id", "JobTenancyName");
}
View
<div class="control-group">
#Html.BootstrapLabelFor(m => m.TenancyID)
<div class="controls">
#Html.DropDownListFor(m => m.TenancyID, Model.TenancyList, "-Please select-")
#Html.BootstrapValidationMessageFor(m => m.TenancyID)
</div>
</div>
You need to cast your ViewBag data to SelectList as follow:
var data = (SelectList)Viewbag.TenancyList;
You need to do this because ViewBag carry object data type.
After casting you can get your tenacyList from data.Items.
Related
Here is the Syntax of My Dropdown.
#Html.DropDownListFor(model => model.DealerIdRef, Model.Ddllist, " Select Dealer ", new { #class = "form-control"})
i want its default selected value and make it read-only so that user can not update selection. For this i'm using Jquery.
$('#DealerIdRef').val('#Session["MyID"]').trigger('change');
$("#DealerIdRef").attr('disabled', 'true');
this is setting the value and also exists in Console
At Controller it is still null
Edit
if i'm making some mistake then please help.
thanks in advance
Your javascript is setting the disabled attribute of the dropdownlist. Disabled form controls do not submit a value so the value of DealerIdRef in your model is its default (i.e. null because its int?).
If you want the value of the dropdownlist to be submitted, do not disabled it.
But based on i want its default selected value and make it read-only so that user can not update selection, then there is no point generating a dropdownlist, and in anycase, you set selected option by setting the value of the property your binding to. That is you set the value of DealerIdRef in the GET method before you pass the model to the view.
Since all you want is to display a value and have it posted back, then include a hidden input for the value and display the text
#Html.HiddenFor(m => m.DealerIdRef)
<div>...the txt you want to display...</div>
There is no point degrading performance by generating a SelectList and extra html when its not needed.
As a side note, your POST method would have throw this exception because you have not repopulated the SelectList in the POST method before you return the view.
I wrote a simple mock your question.
It can work. The simple code is on DropDownController
Here is the Source Code,I Upload to github.
ViewModel
public class DropDownViewModel
{
[Display(Name = "Dealer")]
public int? DealerIdRef { get; set; }
public IEnumerable<SelectListItem> Ddllist { get; set; }
}
Index View
Mock Your Submit action
#model Sample.Models.DropDownViewModel
#using (Html.BeginForm("ShowDDL", "DropDown", FormMethod.Post))
{
#Html.DropDownListFor(model => model.DealerIdRef, Model.Ddllist, " Select Dealer ", new { #class = "form-control" })
<button>Submit</button>
}
ShowDDL View
Show your select data.
#model Sample.Models.DropDownViewModel
<b>Your Select Value: </b> #Model.DealerIdRef
DropDownController
public ActionResult Index()
{
DropDownViewModel model = new DropDownViewModel()
{
Ddllist = GetDDL(),
DealerIdRef = 1
};
return View(model);
}
[HttpPost]
public ActionResult ShowDDL(DropDownViewModel viewModel)
{
return View(viewModel);
}
private IEnumerable<SelectListItem> GetDDL()
{
return new List<SelectListItem>()
{
new SelectListItem()
{
Text = "One",
Value = "1"
},
new SelectListItem()
{
Text = "Two",
Value = "2"
}
};
}
Hi i have three Fields in my view.That three fields are drop down. I want to pass the value to these fields when edit button is clicked. That is the values need to pass to that drop down fields. My view is mentioned below
In my view i have many drop downs but once i know how to pass the value to one drop down means i will do for another drop downs.
For Edit i create one view in sql and connect that view as EDMX file in my application.In this view(table) i have all fields which is in Visitors Form. That view name is View_VisitorsForm.
My Model(VisitorsViewModel)
public Nullable<System.DateTime> Date { get; set; }
public System.Guid VisitingID { get; set; }
public Nullable<System.Guid> EmployeeID { get; set; }
public string EmployeeName { get; set; }
public string Description { get; set; }
My Edit Code
public ActionResult Edit(Guid ?id)
{
WafeERPNEWEntities db = new WafeERPNEWEntities();
SelectList typelist = new SelectList(db.Employees.ToList(), "EmployeeID", "DisplayName", db.Employees);
ViewData["EmployeeName"] = typelist;
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
VisitorsViewModel ObjVisitorsviewModel = new VisitorsViewModel();
View_VisitorsForm visit = db.View_VisitorsForm.Find(id);
visit.VisitingID = ObjVisitorsviewModel.VisitingID;
visit.VisitingDate = ObjVisitorsviewModel.Date;
visit.Description = ObjVisitorsviewModel.Description;
if (ObjVisitorsviewModel == null)
{
return HttpNotFound();
}
return View(ObjVisitorsviewModel);
}
My View Code
#Html.LabelFor(model => model.Date)
#Html.EditorFor(model => model.Date)
#Html.ValidationMessageFor(model => model.Date)
#Html.LabelFor(model => model.VisitingID)
#Html.EditorFor(model => model.VisitingID)
#Html.ValidationMessageFor(model => model.VisitingID)
#Html.LabelFor(model => model.EmployeeName)
#Html.DropDownList("EmployeeID", (IEnumerable<SelectListItem>)ViewData["EmployeeName"])
#Html.ValidationMessageFor(model => model.EmployeeName)
Now when i click the edit button it pass the value to this line
View_VisitorsForm visit = db.View_VisitorsForm.Find(id);
and also it getting visit.visitingID. But it is not getting the value in viewmodel .so the value will be empty in view.All values are empty VisitingID, Description, Date Fields are empty and in Employee drop down it won't show the value which i passed to this field it shows the first value in dropdown. so please any one tell me how to solve this issue. Actually I try to explain my issue as per my level best and if you didn't understand my issue or any one need my full code or need more code tell me . i ready to update my code again. but i need solution.
Advance Thanks..
use:
#Html.DropDownListFor(model => model.EmployeeID,(IEnumerable<SelectListItem>)ViewData["EmployeeName"])
The important part being "DropDownListFor". You are using "DropDownList".
Use the DropDownListFor helper method.
#Html.DropDownListFor(model => model.EmployeeID,
(IEnumerable<SelectListItem>)ViewData["EmployeeName"])
Now in your GET action, you need to set the EmployeeID property value of your view model.
public ActionResult Edit(int id)
{
var objVisitorsviewModel = new VisitorsViewModel();
// I am hard coding to 25.
// You may replace it with a valid Employee Id from your db table for the record
ObjVisitorsviewModel.EmployeeID= 25;
return View(objVisitorsviewModel);
}
A more clean solution is to not use ViewData to transfer the data you need to render the dropdown option. You can make your code more strongly typed by simply adding a new property to your view model
public class VisitorsViewModel
{
public List<SelectListItem> Employees { set;get;}
public Guid? EmployeeID { get; set; }
// Your existing properties goes here
}
Now in your GET action(create/edit), Instead of storing the data in ViewData, we will load to the Empenter code hereloyees property.
public ActionResult Edit(int id)
{
var vm = new VisitorsViewModel();
vm.Employees = db.Employees.Select(s=> new SelectListItem {
Value=s.EmployeId.ToString(), Text=s.DisplayName }).ToList();
return View(vm);
}
And in your view, we will use the DropDownListFor helper method with the Employees property
#model VisitorsViewModel
#using(Html.BeginForm())
{
#Html.DropDownListFor(s=>s.EmployeeID,Model.Employees,"Select")
}
You are using a DropDownList(...) instead of a DropDownListFor(...)
Your Model
You must add a SelectList:
public SelectList Employees { get; set }
Your Edit
You must get your employees list and add it to your model:
// Get employees list from the database
var employees = db.Employee.Select(x => x.Id, x.Name).Tolist();
// Put the employees in a SelectList
var selectList = new SelectList(employees .Select(x => new { value = x.Id, text = x.Name }), "value", "text");}).ToList();
// Pass the list to your ViewModel
ObjVisitorsviewModel.Employees = selectList;
Your View
Finally, change your DropDownListFor line for this:
#Html.DropDownListFor(model => model.EmployeeID,
model.Employees)
By using DropDownList(...), your object data is not bound to the DropDown. You must manage its selected value manually.
Html.CheckBox("SelectedStudents", false, new { #class = "check-item", id = x.Id, value = x.Id })
which produce
<input checked="checked" class="check-item" id="4507" name="SelectedStudents" value="4507" type="checkbox">
<input checked="checked" class="check-item" id="4507" name="SelectedStudents" value="4508" type="checkbox">
<input checked="checked" class="check-item" id="4507" name="SelectedStudents" value="4509" type="checkbox">
In mvc model I have
public IEnumerable<string> SelectedStudents { get; set; }
but when I post back, SelectedStudents are always null. Why?
In this howto http://benfoster.io/blog/checkbox-lists-in-aspnet-mvc
is written:
The ASP.NET MVC modelbinder is smart enough to map the selected items
to this property.
but in my example is always null. Why? How to write more checkboxes and bind it back
You should be using a strongly typed editor to be able to pass the result to the controller (Model binder).
I prefer to do it this way.
Model
public class YourViewModel
{
public List<SelectListItem> Students
{
get;
set;
}
}
Controller Get
Students= service.GetStudents(); //Fill the list
View
#for (var i = 0; i < Model.Students.Count; i++)
{
#Html.CheckBoxFor(m => m.Students[i].Selected)
#Html.HiddenFor(m => m.Students[i].Text)
#Html.HiddenFor(m => m.Students[i].Value)
<span>#Model.Students[i].Text</span>
}
Controller Post
[HttpPost]
public ActionResult Create(YourViewModel model)
{
foreach(var student in model.Students)
{
if(student.Selected) { // Do your logic}
}
}
Alternatively
You could use an array or List of string. A ListBox is used in this example.
public string[] SelectedStudents{ get; set; }
#Html.ListBoxFor(s => s.SelectedStudents, new MultiSelectList(Model.Students, "Value", "Text", Model.SelectedStudents), new { #class = "form-control", style = "height:250px; width:100%" })
See my answer here How to bind checkbox values to a list of ints?.
The nice thing about this is that it separates concerns between your controller and ui nicely. The html extension methods also create correct html using label and input for the checkbox. and there is no need for hidden fields.
Do you try it with CheckBoxListFor?? You need to associate the checkbox with model and should not have the same ID and name
#Html.CheckBoxListFor(model => model.SelectedSources, Model.SubscriptionSources)
You need to use a mutable type, like List<string>.
public List<string> SelectedStudents { get; set; }
I have a DropDownListFor control that I am wanting to show a display value that resides in a property within a model/class (this is the Rule class.) The view's model is actually a collection of these model/classes. However, when I select the item from the DropDownList, I want to send back the entire model as a parameter. I have this working perfectly with the following code, but the Name property within the parameter is coming back as null. The other properties all have appropriate values.
View Code:
#model List<StockTrader.Web.Data.Rule>
#{
ViewBag.Title = "Configure Rules";
}
<h2>#ViewBag.Title</h2>
<h4>Choose a rule to edit:</h4>
<form method="post" id="rulesform" action="SaveRules">
#Html.DropDownListFor(m => m.First().RuleID, new SelectList(Model.AsEnumerable(), "RuleID", "Name"))
<div style="margin-bottom: 15px;">
<label>Value:</label><br />
<input type="number" name="Value" style="margin-bottom: 15px;" /><br />
<button>Save Value</button>
</div>
Controller Code:
public ActionResult SaveRules(Rule model)
{
//do something
}
Rule Class:
public class Rule
{
public int RuleID { get; set; }
public string Name { get; set; }
public int Value { get; set; }
public bool IsDeleted { get; set; }
}
We do have Kendo controls, so if another control would be more appropriate, that is an option.
I would be glad to provide anymore code or information you might need.
Any thoughts or ideas?
EDIT:
So it turns out this is what I needed to do, the accepted answer got me to this point so I'm going to leave it checked.
View Code (w/script included):
#Html.DropDownListFor(m => m.First().RuleID, new SelectList(Model.AsEnumerable(), "RuleID", "Name"), new { id = "ruleid", #onchange = "CallChangefunc(this)" })
#Html.HiddenFor(m => m.First().Name, new { id = "rulename" })
function CallChangefunc(e) {
var name = e.options[e.selectedIndex].text;
$("#rulename").val(name);
}
You will need a hidden field for it,and use dropdownlist on change event on client side to update hidden field:
#Html.DropDownListFor(m => m.First().RuleID, new SelectList(Model.AsEnumerable(), "RuleID", "Name"),new { id= "ruleid" })
#Html.HiddenFor(m=>m.First().Name,new { id="rulename" })
and jquery code:
$("#ruleid").change(function(){
$("#rulename").val($(this).text());
});
Second option isif Rule collection is coming from database you can fetch RuleName by using id to by querying db in action.
it can be achieved by using UIHint
On your model class, on the RuleID property, add an annotation for UIHint. It basically lets you render a partial (cshtml) for the property. So, on the partial, you can have the template for generating the dropdwon with required styling. When Page is generated. Now you can use the same Html.DropDownListFor for RuleID and UI generates a dropdown for it.
This will avoid having additional jQuery code to get the dropdown value, and code is more concise and testable.
Based on Darin's answer to my question Ho to display multiple checkbox selection based on user's selection from dropdown?
I am displaying multiple checkboxes based on dropdown selection.
Now, once the user post the form (with multiple inputs) that i have on my page, i collect all the data using FormCollection. And the problem i have is how can i pull those selected checkbox values from formcollection? The number of checkbox will change on different selection from the drop-down, so i think requesting each checkbox value will not work.
Can anyone help me with this problem.
The flow is as shown below:
Properties in Model
public class Subcategory
{
public string Name { get; set; }
public int ID { get; set; }
public bool Flag { get; set; }
}
Displaying PartialView in actual view where other form inputs are there:
<div id="checkboxlist">
#if (Model.SubCategories != null)
{
#Html.Partial("SubCategories", Model.SubCategories)
}
</div>
PartialView SubCategories.cshtml
#model IEnumerable<MyProject.Entities.Subcategory>
#{
// we change the HTML field prefix so that input elements
// such as checkboxes have correct names in order to be able
// to POST the values back
ViewData.TemplateInfo.HtmlFieldPrefix = "checkboxlist";
}
<span>subcategory</span>
<div id="subcategories" style="margin-left: 130px;margin-top: -20px;" data-role="fieldcontain">
<fieldset data-role="controlgroup">
#Html.EditorForModel()
</fieldset>
</div>
EditorTemplates Subcategory.cshtml
#model MyProject.Entities.Subcategory
<div class="editor-label">
#Html.CheckBoxFor(c => c.Flag, new { type = "checkbox" })
<label for="#Model.ID">#Model.Name</label>
#Html.HiddenFor(c => c.Flag)
#Html.HiddenFor(c => c.ID)
#Html.HiddenFor(c => c.Name)
</div>
jquery to display checkboxes based on dropdown selection:
$('#Category').change(function () {
var subcategoriesUrl = $(this).data('subcategoriesurl');
var categoryId = $(this).val();
$('#checkboxlist').load(subcategoriesUrl, { category: categoryId });
});
Don't use FormCollection. That's weakly typed. Use view models. Like this:
[HttpPost]
public ActionResult Foo(MyViewModel model)
{
// model.BusinessSubCategories should contain a list of Subcategory
// where for each element you could use the Flag property to see if
// it was selected or not
...
}
Also notice that you have an inconsistency between the field prefix that you are using in your partial:
ViewData.TemplateInfo.HtmlFieldPrefix = "checkboxlist";
and the view model collection property: Model.BusinessSubCategories. So make sure you fix the prefix to use the correct property name if you want the default model binder to be able to populate this property when you post back.