I'm doing a management application users have a part where I have a form with a <select></select>
Which is filled from a
#{ Html.RenderAction ("ListaTipoDeUsuarios", new {selected = 0}); }
This (Index.cshtml):
...
<div class="lg-xs-12">
<label>Tipo Usuario</label>
<select name="tipoUsuario" class="form-control" >
#{Html.RenderAction("ListaTipoDeUsuarios", new { selected = 0 });}
</select>
</div>
....
I have my function in the controller which performs the query to bring the list of types of users (HomeController.cs)
[ChildActionOnly]
public PartialViewResult ListaTipoDeUsuarios()
{
string dtTipoUser = client.GetTiposUsuario("{}");
DataTable dt = (DataTable)JsonConvert.DeserializeObject(dtTipoUser, typeof(DataTable));
List<TipoUsuarioBO> listaTiposUsuarios = new List<TipoUsuarioBO>();
foreach (DataRow row in dt.Rows)
{
TipoUsuarioBO tipoUsuario = new TipoUsuarioBO();
tipoUsuario = TiposUsuarioBR.MapeoTipoUsuario(row, tipoUsuario);
listaTiposUsuarios.Add(tipoUsuario);
}
return PartialView(listaTiposUsuarios);
}
And my view with the list (ListaTipoDeUsuarios.cshtml)
#foreach (var item in Model)
{
<option value="#item.Id">#item.Id - #item.Descripcion</option>
}
My question is, how to make when loading the list brings one of the selected item.Currently when charging the view brings selected by default the first item in the list.
NOTE: Try changing the "0" of the "new selected = {0}" but does nothing.
You will need to change the Model of the PartialView which is rendering the options. You have 2 options.
Change the existing TipoUsuarioBO object to add another property named SelectedID,
OR
Create a new Model with the following declaration.
public class OptionsModel <-- Rename to naming conventions
{
public List<TipoUsuarioBO> TipoUsuarioBO { get; set; }
public int SelectedID {get; set; }
}
And, while rendering option elements, use the following
#foreach (var item in Model.TipoUsuarioBO)
{
<option value="#item.Id" #Html.Raw(#item.Id == Model.SelectedID ? "selected" : "") >#item.Id - #item.Descripcion</option>
}
Why you don't try using List<SelectListItem> as the model of ListaTipoDeUsuarios.cshtml view.
[ChildActionOnly]
public PartialViewResult ListaTipoDeUsuarios()
{
string dtTipoUser = client.GetTiposUsuario("{}");
DataTable dt = (DataTable)JsonConvert.DeserializeObject(dtTipoUser, typeof(DataTable));
List<SelectListItem> listaTiposUsuarios = new List<SelectListItem>();
foreach (DataRow row in dt.Rows)
{
TipoUsuarioBO tipoUsuario = new TipoUsuarioBO();
tipoUsuario = TiposUsuarioBR.MapeoTipoUsuario(row, tipoUsuario);
listaTiposUsuarios.Add(new SelectListItem()
{
Text = tipoUsuario.Id+"-"+tipoUsuario.Descripcion,
Value = tipoUsuario.Id.ToString(),
Selected = true //if you want this item selected otherwise false
});
}
return PartialView(listaTiposUsuarios);
}
and your view
#Html.DropDownList("The name of the field", Model, new { #class = "any-class"})
Related
I have come across a problem. I am currently attempting to make a users page in which some of the dropdowns are variable and determined by their 'access level'. I then want to save the data from the view into a list and then handle it in the 'Post' controller method. I found this link about a possible solution (Assign selectlist to dynamically created dropdown in MVC) but I am still running into problems.
Here is my controller code I am using to set up the data that needs to generate the dropdowns:
var permData = db.LabPermissions.Where(x => x.AccessLevel == 1).ToList();
//sets up generic dropdown data used for all dropdowns
ViewBag.DropDownData = new List<SelectListItem>
{
new SelectListItem{ Value = "0",Text = "No"},
new SelectListItem{ Value = "1",Text = "Yes"},
};
ViewModel obj = new ViewModel();
obj.DataFromController = permData;
//other viewmodel data
return("MyView",obj);
I then pass the data to my view which looks like this (this is also how the stack overflow link set up the view)
#for(int i = 0; i < Model.DataFromController.Count(); i++)
{
<div class="row">
<div class="col-md-2">
<b>#Html.DisplayFor(m => m.DataFromController[i].Lab.LabName)</b>
</div>
<div class="col-md-2">
#Html.DropDownListFor(m => m.DataFromController[i].Assigner, (SelectList)ViewBag.DropDownData, "Select One")
</div>
<div class="col-md-8">
</div>
</div>
}
After I get this set up, and run the application, this is the error I receive:
Additional information: Cannot convert type 'System.Collections.Generic.List<System.Web.Mvc.SelectListItem>' to 'System.Web.Mvc.SelectList'
And the error is placed on my #Html.DropDownListFor line of code in my view.
Thank you for any help!
Try creating a new selectlist instead and put your selectlistitems in it.
#Html.DropDownListFor(m => m.DataFromController[i].Assigner,
new SelectList(ViewBag.DropDownData, "Value", "Text", "Select One")
Or, since you got a ViewModel you can add a public property that can hold your selectlistitems.
public class ViewModel
{
public IEnumerable<SelectListItem> DropDownData { get; set; }
}
Controller:
var permData = db.LabPermissions.Where(x => x.AccessLevel == 1).ToList();
var vm = new ViewModel();
var list = new List<SelectListItem>
{
new SelectListItem{ Value = "-1", Text = "Select One", Selected = true},
new SelectListItem{ Value = "0",Text = "No"},
new SelectListItem{ Value = "1",Text = "Yes"}
};
vm.DropDownData = list;
vm.DataFromController = permData;
return View(vm);
View:
#model YourNameSpace.Models.ViewModel
#for(int i = 0; i < Model.DataFromController.Count(); i++){
#Html.DropDownListFor(m => m.DataFromController[i].Assigner, Model.DropDownData)
}
I believe that you're trying to cast SelectListItem to SelectList and that is the reason why you're getting that error. I've done the same feature as a part of my project and I'm taking the values for the dropdownlist from the database.
and for displaying, here is my code(modified a bit based on your model variables
My Controller method
public ActionResult GetDropDownList()
{
List<SelectListItem> dropDownList= new List<SelectListItem>();
using (var context = new assessmentEntities())
{
//getting data from the DB
var result = context.getDataFromDB().toList();
foreach (var item in result)
{
dropDownList.Add(new SelectListItem() { Text = item.Variable1, Value = item.Variable2});
}
ViewBag.DropDownData = dropDownList;
}
return View();
}`
Here is my View
#Html.DropDownListFor(m => m.DataFromController[i].Assigner,, new SelectList(ViewBag.DropDownData, "Value", "Text")
Hope so this works for you
I am building a shopping portal where I need to accept quantity of products and pass it to an action named order
As you can see in picture above, I added a textbox for accepting quantity for each of the product, then I built an actionlink using following code
#Html.ActionLink("Order Now", "OrderNow", "ShoppingCart", new { id = item.prod_id, qty = #quantity }, new { style = "color: white;" })
to get quantity I added new int quantity attribute to view, as
int quantity = 1;
but how to update this quantity variable when users change the text in qty textbox.
Below is my View code:
#Html.TextBox("qty","", new { id=#item.prod_name, placeholder="Qty", style="width:20px; height:15px; font-size:small;" })
<script type="text/javascript">
$('##item.prod_name').change(function () {
}
});
</script>
#Html.ActionLink("Order Now", "OrderNow", "ShoppingCart", new { id = item.prod_id, qty = #quantity }, new { style = "color: white;" })
Here is my controller action method
public ActionResult OrderNow(int id, int qty)
{
if (Session["cart"] == null)
{
List<Item> cart = new List<Item>();
cart.Add(new Item(p.FirstOrDefault(), qty));
Session["cart"] = cart;
return RedirectToAction("ViewCart", new { ids = p.FirstOrDefault().prod_sub_cat_id });
}
else
{
List<Item> cart = (List<Item>)Session["cart"];
cart[index].quantity = qty;
Session["cart"] = cart;
return RedirectToAction("ViewCart", new { ids = p.FirstOrDefault().prod_sub_cat_id });
}
}
You don't really want a link to a GET method here. Your modifying data (and would not want this to be added to the browser history) so you should be posting the data. For each product, add a form element with a textbox for the quantity and a submit button for the 'Order Now` action (style it to look like a link if you want)
#using (Html.BeginForm("OrderNow", "ShoppingCart", new { id = item.prod_id })
{
<input type="text" class="???" name="qty" placeholder="Qty" />
<input type="submit" value="Order Now" class="???" />
}
Side notes:
Add class names and use css rather than including inline styles such
as style="width:20px; height:15px; font-size:small;"
You could also use #Html.TextBox("qty", new { id = "",
#class="???", placeholder = "Qty"), but note the id = "" which
removes the id attribute to prevent invalid html due to duplicates
I am generating the radiobutton list and then trying to select one option on load as below.
Foreach loop in View
#foreach (var myListItem in Model.MyList)
{
#Html.RadioButtonFor(m => m.MyType,myListItem.MyType, new {id = myListItem.MyType, #Checked = (Model.MyTypeId == myListItem.MyTypeId) })
#myListItem.MyType
}
Eventhough the HTML is generated correctly(refer below). The second option is checked instead of 1st even when Model.MyTypeId = 0.
Generated HTML for view
<input id="0" name="MyType" value="Option One" CHECKED="True" type="radio">Option One
<input id="1" name="MyType" value="Option Two " CHECKED="False" type="radio">Option Two
Please suggest how else I can select the desired radio button option by deafult.
The HTML isn't correct actually. You need to do something more along these lines:
#foreach (var myListItem in Model.MyList)
{
if (Model.MyTypeId == myListItem.MyTypeId)
{
#Html.RadioButtonFor(m => m.MyType,myListItem.MyType,
new
{
id = myListItem.MyType,
#Checked = ""
})
}
else
{
#Html.RadioButtonFor(m => m.MyType,myListItem.MyType,
new
{
id = myListItem.MyType,
})
}
#myListItem.MyType
}
Though I can't verify the exact output, it should look something like this:
<input id="0" name="MyType" value="Option One" CHECKED type="radio">
You may have to use null to get it to generate the CHECKED without the ="", but that would be okay too. See, it's not the value that's recognized, it's the attribute itself, so that's why the second one is checked.
Anytime I need a list of radio buttons created from a query, I always reach for this RadioButtonListFor extension method. Works like a charm:
// jonlanceley.blogspot.com/2011/06/mvc3-radiobuttonlist-helper.html
public static MvcHtmlString RadioButtonListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> listOfValues)
{
var metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
var sb = new StringBuilder();
sb.Append("<span class='RadioButtonListFor'> ");
if (listOfValues != null)
{
// Create a radio button for each item in the list
foreach (SelectListItem item in listOfValues)
{
// Generate an id to be given to the radio button field
var id = string.Format("{0}_{1}", metaData.PropertyName, item.Value);
// Create and populate a radio button using the existing html helpers
var htmlAttributes = new Dictionary<string, object>();
htmlAttributes.Add("id", id);
if (item.Selected)
htmlAttributes.Add("checked", "checked");
var radio = htmlHelper.RadioButtonFor(expression, item.Value, htmlAttributes);
// Create the html string that will be returned to the client
// e.g. <label<input data-val="true" data-val-required="You must select an option" id="TestRadio_1" name="TestRadio" type="radio" value="1" />Line1</label>
sb.AppendFormat("<label>{0} {1}</label> ", radio, HttpUtility.HtmlEncode(item.Text));
}
}
sb.Append(" </span>");
return MvcHtmlString.Create(sb.ToString());
}
Now, you can generate your Radio Buttons from any collection you have in memory, usually as a property on your ViewModel like this:
public int SelectedPaymentMethodId { get; set; }
public IEnumerable<SelectListItem> PaymentMethodChoices
{
get
{
return from x in dataSourceFoo
select new SelectListItem {
Text = x.TextThing, Value = x.Id, Selected = (x.Id == SelectedPaymentMethodId)
};
}
}
And your View is as simple as:
#Html.RadioButtonListFor(model => model.SelectedPaymentMethodId, Model.PaymentMethodChoices)
I'm a brand new user here - but I've been searching for a couple of hours now to solve following problem:
I've got 2 Entities - Category and Item.
Each Item should belong to a Category - therefore I would like to have a DropDownList which shows all existing Categories when Creating a new Item.
So far my code shows the DropDownList with all the Categories, but when I select a Category and Submit the form (POST) the value for Category is always null.
This naturally causes ModelState.IsValid to be false, because Category isn't nullable.
How can I get the User-Selected-Value into my Create(POST) method?
I've got a Controller with following Methods to Create a new Item:
// GET Method
public ActionResult Create()
{
ViewBag.Category = new SelectList(db.CategorySet, "Id", "CategoryName");
return View();
}
[HttpPost]
public ActionResult Create(Item item)
{
if (ModelState.IsValid)
{
db.ItemSet.Add(item);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(item);
}
And this is the DropDownList in my View (Create.cshtml):
<div class="editor-field">
#Html.DropDownList("Category", (IEnumerable<SelectListItem>) ViewBag.Categories, "--Select Category--")
</div>
Finally I ended up with a custom view model - that way I got it working...
For those of you who don't know what a custom view model is:
You create a new class which contains all the values you need to create your new object, in my example a class which contains a SelectList (property) of available Categories, an integer value (property) for SelectedCategoryId and the Item (property) you want to create.
In your cshtml file you add this class as #model ....CustomCreateItemModel and use it in your DropDownList
If your Item has a CategoryId property:
public class Item
{
public int CategoryId {get;set;]
}
You will need to name your DropDownList to "CategoryId" so that the ModelBinder will be able to bind the value correctly
Or use the strongly typed helper:
Html.DropDownListFor(x=>x.CategoryId...)
Thanks Armen.
I had the same issue with my dropdown list being populated OK from the database but the OrganisationID (in my case) not making it to the database when a new record was created (in my case only 0 was always captured) - until I just changed the name of the ViewBag to be identical to the value in the dropdown (i.e. both OrganisationID) - as you had helpfully pointed out - and now it works!
For what it's worth, for anyone else going through the frustration that "Desperate coder" and I went through when our naming wasn't consistent to enable binding, here's what I have used to get a dropdown list working (sorry - NOT using the Entity Framework, but the principle should still be clear and easy to adapt if you are using the EF):
But the key takeaway is identical naming to enable binding. Thanks again Armen!
MODEL
public class Organisation_Names
{
public DataSet GetOrg_Names()
{
SqlConnection cn = new SqlConnection(#"Data Source=XXXXXXXXX;User ID=XXXXXXXXX;Password=XXXXXXXXXXX;Initial Catalog=XXXXXXXXXXXX");
SqlCommand cmd = new SqlCommand("sp_GetOrg_Names", cn);
cn.Open();
cmd.CommandType = CommandType.StoredProcedure;
cmd.ExecuteNonQuery();
DataSet ds = new DataSet();
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(ds);
return ds;
}
}
CONTROLLER
//
// GET: /Services/Create
**public ActionResult Create(Organisation_Names organisation_names)
{
DataSet ds = organisation_names.GetOrg_Names();
ViewBag.OrganisationID = ds.Tables[0];
List<SelectListItem> items = new List<SelectListItem>();
foreach (System.Data.DataRow dr in ViewBag.OrganisationID.Rows)
{
items.Add(new SelectListItem { Text = #dr["OrganisationName"].ToString(), Value = #dr["OrganisationID"].ToString() });
}
ViewBag.OrganisationID = items;
return View();
}
//
// POST: /Services/Create
[HttpPost]
[ValidateAntiForgeryToken]
**public ActionResult Create(CreateServiceModel createservicemodel, Organisation_Names organisation_names, FormCollection selection)
{
DataSet ds = organisation_names.GetOrg_Names();
if (ds == null)
{
return HttpNotFound();
}
ViewBag.OrganisationID = ds.Tables[0];
List<SelectListItem> items = new List<SelectListItem>();
foreach (System.Data.DataRow dr in ViewBag.OrganisationID.Rows)
{
items.Add(new SelectListItem { Text = #dr["OrganisationName"].ToString(), Value = #dr["OrganisationID"] + 1.ToString() });
}
ViewBag.OrganisationID = items;**
if (this.IsCaptchaVerify("Answer was incorrect. Please try again."))
{
try
{
int _records = createservicemodel.CreateService(createservicemodel.OrganisationID, createservicemodel.ServiceName, createservicemodel.ServiceDescription, createservicemodel.ServiceComments, createservicemodel.ServiceIdentificationNumber, createservicemodel.CreatedBy, createservicemodel.NewServiceID);
if (_records > 0)
{
return RedirectToAction("Index", "Services");
}
}
catch
//else
{
ModelState.AddModelError("", "Cannot Create");
}
}
{
return View(createservicemodel);
}
}
VIEW
#model WS_TKC_MVC4.Models.CreateServiceModel
#using CaptchaMvc.HtmlHelpers
#using WS_TKC_MVC4.Models
#{ViewBag.Title = "Service added by " ;} #User.Identity.Name
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"> </script>
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>CreateServiceModel</legend>
<div class="editor-label">
<p>Select Organisation</p>
</div>
<div class="editor-field">
#Html.DropDownList("OrganisationID")
#Html.ValidationMessageFor(model => model.OrganisationID)
#Html.EditorFor(model => model.OrganisationID)
</div>
(Some more fields)
<div class="editor-label">
#Html.LabelFor(model => model.MathCaptcha)
</div>
#Html.MathCaptcha("Refresh", "Type answer below", "Answer is a required field.")
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
I'm constructing a web page based on ASN.NET MVC3 with Razor templates and Entity. The task is to populate a #Html.DropDownList from the database, so far so good but now I want to insert a static value in the DropDownList.
The code looks as follows
The create method
public ActionResult Create()
{
var parents = db.Organizations.OrderBy(o => o.Title).ToList();
var organization = new Organization();
return View(organization);
}
Extract from the Razor template
<div class="editor-field">
#Html.DropDownList("ParentGuid",
new SelectList(ViewBag.Organizations as System.Collections.IEnumerable,
"ParentGuid", "Title", Model.ParentGuid))
</div>
So, the above code works but Im stuck in figuring out how to insert an empty row in the dropdown.
I am not much familiarize with # however, if you tried the overload?
#Html.DropDownList("ParentGuid",
new SelectList(ViewBag.Organizations as System.Collections.IEnumerable,
"ParentGuid", "Title", Model.ParentGuid), "Your empty option text here")
You could add a row with an empty string to your model before passing it to the view, no?
You could recreate the array previous to adding it to the list. Something like this:
List<SelectListItem> itms = new List<SelectListItem>();
var blank = new SelectListItem();
blank.Selected = true;
itms.Add(blank);
foreach (var stat in model)
{
var s = new SelectListItem();
s.Text = stat.Text;
s.Value = stat.FeedBackTypeID + "";
itms.Add(s);
}
and then use that
In your controller Create(), just add an empty string to the head of the "parents" list.
I ended up using
<div class="editor-field">
#Html.DropDownListFor(model => model.ParentGuid,
new SelectList(ViewBag.Organizations as System.Collections.IEnumerable,
"OrganizationGuid", "Title", Model.ParentGuid), "")
</div>
The method serving the template looks like this
public ActionResult Create()
{
try
{
ViewBag.Organizations = db.Organizations.OrderBy(o => o.Title).ToList();
var organization = new Organization();
return View(organization);
}
catch (Exception e)
{
ViewData["error"] = string.Concat(e.Message, " ", e.StackTrace);
return RedirectToAction("Index");
}
}