I created my first project in ASP.Net framework with MVC and I am trying to include a dropdownlist with searching capabilities. I am trying to create something like this, but I keep ending up with this. I have tried bootstrap selectpicker, select2, and others but I can't seem to change the style of the dropdown.
Here is my code:
<script>
$(document).ready(function () {
$('.selectpicker').selectpicker({
liveSearch: true,
showSubtext: true
});
});
</script>
<div class="form-group">
#Html.LabelFor(model => model.MaterialPN, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#*#Html.EditorFor(model => model.MaterialPNID, new { htmlAttributes = new { #class = "form-control" } })*#
#Html.DropDownListFor(model => model.MaterialPNID, ViewBag.MaterialPNListItems as IEnumerable<SelectListItem>, new
{
#class = "form-control selectpicker",
data_show_subtext = "true",
data_live_search = "true"
})
</div>
</div>
EDIT:
I created a totally new, vanilla solution to test this out. In visual studio I created a new ASP.Net C# solution with MVC, then added the Bootstrap-select library in NuGet.
public class Student
{
public int StudentId { get; set; }
[Display(Name = "Name")]
public string StudentName { get; set; }
public Gender StudentGender { get; set; }
}
public enum Gender
{
Male,
Female,
Other
}
And added a dropdown to the about page:
#using SearchableDropdown.Models
#model Student
#{
ViewBag.Title = "About";
}
<script>
$(document).ready(function () {
$('.selectpicker').selectpicker({
liveSearch: true,
showSubtext: true
});
});
</script>
<h2>#ViewBag.Title.</h2>
<h3>#ViewBag.Message</h3>
<p>Use this area to provide additional information.</p>
#Html.DropDownList("StudentGender",
new SelectList(Enum.GetValues(typeof(Gender))),
"Select Gender",
new
{
#class = "form-control selectpicker",
data_show_subtext = "true",
data_live_search = "true"
})
I am still seeing the same thing, a dropdown without clear searching capability. When I have the dropdown selected and start typing, it will choose the item that starts with the letters that I type but this is not true searching capability.
Use below link
https://select2.org/getting-started/basic-usage#multi-select-boxes-pillbox
HTML
<select class="js-example-basic-multiple" name="states[]" multiple="multiple">
<option value="AL">Alabama</option>
...
<option value="WY">Wyoming</option>
</select>
JS
$(document).ready(function() {
$('.js-example-basic-multiple').select2();
});
Related
I am new to ASP.NET Core and Razor pages. I am trying to create a select drop-down list and get its value for further processing. I have the following in the view / Razor page (the .cshtml file):
<div class="field">
#Html.LabelFor(x => Model.FavouriteColour, htmlAttributes: new { #class = "label" })
<div class="control">
<div class="select">
#Html.DropDownListFor(x => Model.FavouriteColour, new SelectList(Model.FavouriteColoursList, "Value", "Text"), htmlAttributes: new { #id = "favouriteColour", #name = "favouriteColour" })
</div>
#Html.ValidationMessageFor(x => x.FavouriteColour, "", new { #class = "has-text-danger" })
</div>
</div>
And then I have the following in the OnPost() method of the view model (the .cshtml.cs file):
[Required]
[Display(Name = "My favourite colour is...")]
public string FavouriteColour { get; set; }
public IEnumerable<SelectListItem> FavouriteColoursList = new List<SelectListItem>()
{
new SelectListItem
{
Value = "White",
Text = "White"
},
(...)
}
The page is displayed correctly and all options are visible in the drop-down but the OnPost() method fails to retrieve the selected value. The following code:
Console.WriteLine("Colour: " + FavouriteColour);
Console.WriteLine("Colour (FORM): " + Request.Form["favouriteColour"] + " " + Request.Form["favouriteColour"].GetType());
Has the following output:
Colour:
Colour (FORM): White Microsoft.Extensions.Primitives.StringValues
When I also try to .GetType() of the model property, I get a System.NullReferenceException which, combined with the information above, shows that the data is transferred correctly but for some reason fails to be assigned to the model property.
What's the root cause and how to resolve it?
I am trying to create sub category for categories. User first select the categories from dropdownlist and then type the subcategory name and clicks submit. Even though dropdownlist elements are properly fill the dropdown list. When I click submit button It creates error. How can I solve this?
My View:
#model CETAPPSUGG.Models.CategorySubCategoryModel
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.HiddenFor(model => model.selectedId, new { id = "3" });
// #Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>SubCatagories</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.SubCategory.SubCategoryName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.SubCategory.SubCategoryName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.SubCategory.SubCategoryName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
Upper cat: <div class="col-md-10">
#Html.DropDownListFor(Model => Model.Categories, Model.categoryList)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
My Controller:
public ActionResult Create()
{
var categories = db.Categories.ToList();
CategorySubCategoryModel deneme = new CategorySubCategoryModel();
var list = new List<SelectListItem>();
deneme.Categories = categories;
foreach (Categories c in categories)
{
list.Add(new SelectListItem() { Text = c.CategoryName, Value = c.Id.ToString() });
}
deneme.categoryList = list;
return View(deneme);
}
// POST: SubCatagories/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
// [ValidateAntiForgeryToken]
public ActionResult Create( CategorySubCategoryModel model)
{
string strDDLValue = model.selectedId;
SubCatagories newSubCategory = new SubCatagories();
Categories cat = new Categories();
cat = db.Categories.Find(Convert.ToInt32(strDDLValue));
// cat = db.Categories.Find(Convert.ToInt32(strDDLValue));
newSubCategory.SubCategoryName = model.SubCategory.SubCategoryName;
newSubCategory.UpperCategory = Convert.ToInt32(strDDLValue);
newSubCategory.Categories = cat;
db.SubCatagories.Add(newSubCategory);
db.SaveChanges();
return View();
}
My Model
namespace CETAPPSUGG.Models
{
public class CategorySubCategoryModel
{
SubCatagories SubCatagories { get; set; }
public IEnumerable<Categories> Categories { get; set; }
public IEnumerable<SubCatagories> SubCategories { get; set; }
public IEnumerable<SelectListItem> categoryList { get; set; }
public SubCatagories SubCategory { get; set; }
public string selectedId;
}
}
It creates error in view
You have a bunch of problems here.
Your primary problem is that you are not passing a model back to the View on post, thus the model is null. So, when you attempt to dereference items from the model in the View, a null reference is generated.
First, you are using selectedId but do not set this anywhere. It doesn't get set by magic. What you probably want is #Html.DropDownListFor(model => model.selectedId, Model.categoryList) (note the lowercase m in model in the first parameter, and uppercase M in the second)
Second, don't use a Model in your lambda in the DropDownListFor, use the lowercase model, because uppercase Model is reserved for the actual Model instance. If you want to reference the Model instance, then do something like DropDownListFor(_ => Model.Foo, Model.Foos). Note that I replaced the Model before the lambda with an underscore or some other value that is not Model. Frankly i'm surprised this even works, but there's probably a scoping rule here that overrides the outer Model. Avoid this because it can cause you confusion down the road.
Third, you are passing an IEnumerable to the DropDownListFor as the selected item variable, this won't work on a number of levels. This needs to be a single string value in most cases (sometimes a numerical one, but always a single more basic type that can have ToString() called on it and get a sensible string since DropDownListFor can't display complex objects).
Fourth, You also need to re-populate your DropDownListFor in the Post action, because the contents of a dropdownlist are not posted back, and thus will be null in the model. This, along with the SubCategory derefences in your view are ultimately what is generating the Null Reference exception.
You also need to pass the model back to your view in the Post, but as stated above, it needs to be re-initialized with the Categories as well as SubCategories.
There are probably more problems here, but fix these and you should be on your way.
I am trying to add a state field to the user registration on the default MVC SPA template. I want to use a dropdown that doesn't link to a database field, or anyother crazy stuff other than having them statically/manually created as they are not going to change.
Is there any easy to implement solution or a way that I can implement this easily without altering the defaults too much?
You sound lazy ;-). This should do the job:
Add this property to the RegisterViewModel in the AccountViewModel.cs:
[Display(Name = "State")]
public string State { get; set; }
This will take take of posting the state value. Then add this to the Register.cshtml, below the confirm password field:
#{ var states = new List<SelectListItem>
{
new SelectListItem { Text = "Example 1", Value="Example1" },
new SelectListItem { Text = "Example 2", Value="Example2" }
};
}
<div class="form-group">
#Html.LabelFor(m => m.State, new {#class = "col-md-2 control-label"})
<div class="col-md-10">
#Html.DropDownListFor(m => m.State, states, "-- Select Status --", new { #class = "form-control"})
</div>
</div>
This results in:
I'm currently working on a website in MVC, I have created a partial view with a DropDownListFor everytime a value is selected in the DropDownListFor it goes to the HttpPost and adds the value to a List. I also have a ListBoxFor that is bound to this list.
What I would like to achieve:
Everytime a new value is added to the List with the DropDownListFor it should update the ListBoxFor automatically so the selected value gets added to this Listbox. I wonder what the best way would be to achieve this.
Code:
Submit.cshtml:
<div class="create-ingredient">
#Html.Partial("_CreateIngredient")
</div>
<br/>
<div class="add-ingredient">
#Html.Partial("_AddIngredient")
</div>
<br/>
<div class="ingredient-listbox">
#Html.LabelFor(model => model.Ingredients,"Current Ingredients")
#Html.ListBoxFor(model => model.Ingredients, new MultiSelectList(Model.SelectedIngredients), new { style = "width:50%;" })
</div>
_AddIngredient.cshtml (Partial View):
#model Recepten.Models.IngredientSelectModel
#using (Ajax.BeginForm("AddIngredient", "Recipe", new AjaxOptions() { UpdateTargetId = "add-ingredient", HttpMethod = "Post" }))
{
#Html.LabelFor(model => model.Ingredients, "Add Ingredient")
#Html.DropDownListFor(model => model.SelectedIngredient, Model.Ingredients, "Select Ingredient", new { #onchange = "$(this).parents('form').submit();" })
}
AddIngredient:
[HttpPost]
public ActionResult AddIngredient(IngredientSelectModel ing)
{
ing.SelectedIngredients.Add(ing.SelectedIngredient);
return PartialView(ing);
}
IngredientSelectModel:
public RecipeModel Recipe { get; set; }
public IEnumerable<SelectListItem> Ingredients { get; set; }
public int SelectedIngredient { get; set; }
public string addIngredient { get; set; }
public List<int> SelectedIngredients { get; set; }
public IngredientSelectModel()
{
SelectedIngredients = new List<int>();
}
Thank you for your time!
As I think you've figured, the reason the current approach isn't working is that the IngredientSelectModel created for and updated by the AddIngredient action is separate from the one used to populate the ListBox.
If Ajax and unobtrusive JQuery are set up correctly (the browser URL shouldn't change when you select an ingredient), #pinhead's answer will send the selected value to the action, but SelectedIngredients won't accumulate the values you select because its value isn't included in the ajax data. For that to work you need to change the multi-select to be bound to SelectedIngredients:
#Html.ListBoxFor(
model => model.SelectedIngredients,
new MultiSelectList(Model.SelectedIngredients),
new { style = "width:50%;" })
...and move it inside the form declaration so its value is posted to the action along with the new ingredient to add.
That said, I wouldn't say you're doing enough work to justify a round-trip to the server, so after making the above change you could just add the ingredient entirely on the client side like this:
#Html.DropDownListFor(
model => model.SelectedIngredient,
Model.Ingredients,
"Select Ingredient",
new { #onchange = "$('#SelectedIngredients').append('<option>' + $(this).val() + '</option>')" })
I believe one solution is to move your ListBoxFor helper into your partial view so that it is updated and recreated once your action returns the partial view.
Submit.cshtml:
<div class="create-ingredient">
#Html.Partial("_CreateIngredient")
</div>
<br/>
<div class="add-ingredient">
#Html.Partial("_AddIngredient")
</div>
_AddIngredient.cshtml (Partial View):
#model Recepten.Models.IngredientSelectModel
#using (Ajax.BeginForm("AddIngredient", "Recipe", new AjaxOptions() { UpdateTargetId = "add-ingredient", HttpMethod = "Post" }))
{
#Html.LabelFor(model => model.Ingredients, "Add Ingredient")
#Html.DropDownListFor(model => model.SelectedIngredient, Model.Ingredients, "Select Ingredient", new { #onchange = "$(this).parents('form').submit();" })
}
#Html.LabelFor(model => model.Ingredients,"Current Ingredients")
#Html.ListBoxFor(model => model.Ingredients, new MultiSelectList(Model.SelectedIngredients), new { style = "width:50%;" })
I have a form which includes 2 fields....Owner_ID and AQ_Manager. I want to make the AQ_Manager field default to a name, depending on what is entered into the Owner_ID field. For example, if user inputs "Company A" into the Owner_ID field, I want to default the AQ_Manager field to "John Smith". Is there a way for me to accomplish this?
Model Info:
[DisplayName("Owner ID")]
public string Owner_ID { get; set; }
[DisplayName("AQ Manager")]
public string AQ_Manager { get; set; }
View:
<div class="form-group">
#Html.LabelFor(model => model.Owner_ID, new { #class = "control-label col-md-2 required CreateEditFieldNamesSpan" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.Owner_ID (SelectList)ViewBag.VBProjectOwnerList, "--Select Owner--")
#Html.ValidationMessageFor(model => model.Owner_ID)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.AQ_Manager, new { #class = "control-label col-md-2 CreateEditFieldNamesSpan" })
<div class="col-md-10">
#Html.EditorFor(model => model.AQ_Manager)
#Html.ValidationMessageFor(model => model.AQ_Manager)
</div>
</div>
From your comments, you have indicated that there are only 3 options for Owner_ID, so you could add a property to your view model to store the associated defaults (say) public List<string> DefaultManagers { get; set; } and in the GET method, initialize the collection and add the 3 values (in the same order as the 3 options)
model.DefaultManagers = new List<string>{ "John", "Bob", "Jim" };
return View(model);
and in the view, include the following script
var defaults = #Html.Raw(Json.Encode(Model.DefaultManagers))
which will create a javascript array containing the 3 values. Then handle the .change() event of your dropdownlist an update the textbox
$('#Owner_ID').change(function() {
var index = $(this).children('option:selected').index();
$('#AQ_Manager').val(defaults[index]);
});
An alternative, if the view was more complex and you need to update multiple inputs, would be to use ajax to call a controller method that returns the result(s) you need
var url = '#Url.Action("GetDefaults")';
$('#Owner_ID').change(function() {
$.getJSON(url, { id: { $(this).val() }, function(data) {
$('#AQ_Manager').val(data.DefaultManager);
$(anotherElement).val(data.SomeOtherPropery);
});
});
and the controller method would be
public JsonResult GetDefaults(string id)
{
// get the values you need based on the selected option, for example
var data = new { DefaultManager = "Jim", SomeOtherPropery = someOtherValue };
return Json(data, JsonRequestBehavior.AllowGet);
}
as per your question you are entering a value in 'Owner_Id' field. we can easily set up a default value in 'AQ_Manager' field by using java script or JQuery. The syntax changes it depends up on what type of your fields