How to get selected values from bootstrap multi select dropdown? - razor

I am referencing bootstrap multiselect in my blazor client application.
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-multiselect/0.9.15/css/bootstrap-multiselect.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-multiselect/0.9.15/js/bootstrap-multiselect.min.js"></script>
I have a select control defined as below in my razor page which communicates with jQuery using IJSRuntime. I can see multi select dropdown with the right values and I see a comma separated list of values upon selection. How can I get this list of values in the razor page or is there a way to bind the result to a variable in the razor page? Thanks for any suggestions.
<select class="multipleselect" multiple #ref="selectMultiple">
#if (Days != null)
{
foreach (var d in Days)
{
<option value="#d.Name">#d.Code</option>
}
}
</select>
#inject IJSRuntime JsRuntime;
#code{
private ElementReference selectMultiple;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await selectMultiple.LoadMultiSelect(JsRuntime);
}
}
public static async Task LoadMultiSelect(this ElementReference elementRef, IJSRuntime jsRuntime)
{
await jsRuntime.InvokeAsync<string>("testscripts.initMultiSelect", elementRef);
}
(function (window) {
window.testscripts = {
initMultiSelect: () => {
console.log('init multi select');
$('.multipleselect').multiselect();
}
})(window);

Here is a solution without jQuery:
<div class="mb-3">
<label for="mslct" class="form-label">Things: #selection.Count</label>
<select id="mslct" class="form-select" #onchange="OnChangeSelection" multiple style="width:auto;">
<option value="0"></option>
#if (Options != null)
{
foreach (var option in Options)
{
<option selected="#(selection.Contains(option.Id))" value="#option.Id">#option.Name</option>
}
}
</select>
</div>
#code {
private List<int> selection = new();
[Parameter]
public List<Thing> Options { get; set; } = new();
[Parameter]
public List<Thing> Value { get; set; } = new();
[Parameter]
public EventCallback<List<Thing>> OnChange { get; set; }
protected override void OnInitialized()
{
selection = Value.Select(o => o.Id).ToList();
}
private async void OnChangeSelection(ChangeEventArgs e)
{
selection = (e.Value as string[])?.Select(x => int.Parse(x)).ToList() ?? new();
await OnChange.InvokeAsync(Options.Where(o => selection.Contains(o.Id)).ToList());
}
public class Thing
{
public int Id { get; set; }
public string? Name { get; set; }
}
}

Related

ASP.NET MVC not passing select list

I have the following form:
#using (Html.BeginForm())
{
#Html.LabelFor(a => a.SomeText)
#Html.TextBoxFor(a => a.SomeText, new { #class = "form-control" })
#Html.ValidationMessageFor(a => a.SomeText)
<select name="ListOne" id="ListOne">
#foreach (var item in Model.ListOne)
{
<option value="#item.Id">#item.Name</option>
}
</select>
#Html.DropDownListFor(a => a.ListTwo, listTwo, null);
<input type="submit" value="Do Stuff" class="btn-primary"
asp-controller="My" asp-action="DoStuff"/>
. . .
}
On the server side, I have a simple controller method:
public async Task<IActionResult> DoStuff(MyViewModel myViewModel)
{
// ...
}
A breakpoint here shows that neither select list gets passed through, despite them both being visible in the HTML.
The VM looks like this:
public class MyViewModel
{
public string? SomeText { get; set; }
public SelectList? ListOne { get; set; } = new(new List<SelectListItem>());
public SelectList? ListTwo { get; set; } = new(new List<SelectListItem>());
}
ListOne and ListTwo are both null.
Please - could someone tell me why?

Blazor Telerik Grid set cell color from data

Trying to set cell background color based on hex code from dataset. Not seeing a property for the grid itself so I am trying binging style to the object Course.ColorHex value for each row with some sort of property binding.
Course Object
public class Course
{
public int Id { get; set; }
public string CourseTitle { get; set; }
public string CourseDescription { get; set; }
public string ColorHex { get; set; }
}
Controller
[ApiController]
[Route("[controller]")]
public class CourseController : ControllerBase
{
private static readonly string[] colorList = new[] { "#ff0000", "##ffff00", "#00ff00", "#00ffff", "#0000ff", "#ff00ff" };
[HttpGet]
public IEnumerable<Course> GetCourses()
{
var courses = new List<Course>();
for (var i = 0; i < colorList.Length; i++)
{
var idCount = i + 1;
var course = new Course()
{
Id = idCount,
CourseTitle = $"Course {idCount}",
CourseDescription = $"Course {idCount} description",
ColorHex = colorList[i]
};
courses.Add(course);
}
var result = courses.ToArray();
return result;
}
}
Blazor
#page "/grid"
#using TelerikGridColorTest.Shared
#inject HttpClient Http
<h3>Courses</h3>
<TelerikGrid Data="courses">
<GridColumns>
<GridColumn Field="#(nameof(Course.CourseTitle))" />
<GridColumn Field="#(nameof(Course.CourseDescription))" />
<GridColumn>
<Template>
<div style="background-color: #(nameof(Course.ColorHex)); padding: 10px;"></div>
</Template>
</GridColumn>
</GridColumns>
</TelerikGrid>
#code {
Course[] courses { get; set; }
protected override async Task OnInitializedAsync()
{
courses = await Http.GetFromJsonAsync<Course[]>("Course");
}
}
Figured it out. Forgot to one address the field I was working with in the Field property.
#page "/grid"
#using TelerikGridColorTest.Shared
#inject HttpClient Http
<h3>Courses</h3>
<TelerikGrid Data="courses">
<GridColumns>
<GridColumn Field="#(nameof(Course.CourseTitle))" />
<GridColumn Field="#(nameof(Course.CourseDescription))" />
<GridColumn Field="#(nameof(Course.ColorHex))">
<Template>
#{
var color = context as Course;
<div style="background-color: #(color.ColorHex); padding: 10px;"></div>
}
</Template>
</GridColumn>
</GridColumns>
</TelerikGrid>
#code {
Course[] courses { get; set; }
protected override async Task OnInitializedAsync()
{
courses = await Http.GetFromJsonAsync<Course[]>("Course");
}
}

How do I populate a DropDown List using Razor Pages with No Controller

I am stuck on this one part. When I do a search all that comes up is examples with controllers, viewbags and other examples in MVC.
I am trying to populate a dropdown list from a database. Here is my code so far
Category.cs
public class Category
{
[Key]
public int CategoryID { get; set}
public string CategoryName { get; set; }
}
Editor.cshtml.cs
public class Editor : PageModel
{
private readonly DatabaseContext _context;
public Editor(DatabaseContext databasecontext)
{
_context = databasecontext;
}
public void OnGet()
{
List<Category> categoryList = new List<Category>();
categoryList = (from Category in _context.Category select Category).ToList();
categoryList.Insert(0, new Category { CategoryID = 0, CategoryName = "Select" });
}
}
What would be my next steps in attaching the dropdownlist to my Razor View Page?
You can use the select tag helper with razor pages as well.
Add 2 other public properties to your page model. One for the collection of items to be used to display the option items and the other for storing/passing the selected value.
public class Editor : PageModel
{
private readonly DatabaseContext _context;
public Editor(DatabaseContext databasecontext)
{
_context = databasecontext;
}
[BindProperty]
public int SelectedCategoryId { set; get; }
public List<SelectListItem> CategoryItems { set; get; }
public void OnGet()
{
CategoryItems = _context.Category
.Select(a=> new SelectListItem {
Value = a.CategoryId.ToString(),
Text = a.CategoryName })
.ToList();
}
}
Now in your view, use the SELECT tag helper.
#page
#model Editor
<form method="post">
<select asp-for="SelectedCategoryId" asp-items="#Model.CategoryItems">
<option>Select one</option>
</select>
<div>
<button type="submit" class="btn">SAve</button>
</div>
</form>
When user submits the form, You can read the selected option value in the SelectedCategoryId property of the page model.
public IActionResult OnPost()
{
var selectedCategoryId = this.SelectedCategoryId;
// to do : return something
}

ASP.NET Core select tag

I am learning asp .net core, and for that purpose I am developing simple blogging application. I want to edit existing post and I want to have dropdown with categories of posts but to have selected by default current category of the post. I am failing to do it on the view.
Here is my ViewModel:
namespace Blog.Models.ViewModels
{
public class CategoryViewModel
{
public int Id { get; set; }
public string Title { get; set; }
public IEnumerable<Posts> Posts { get; set; }
public IEnumerable<Categories> Categories { get; set; }
}
}
Here is my controller action:
[HttpGet]
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var posts = _db.Posts.ToList();
var post = posts.Where(m => m.Id.Equals(id));
var cats = _db.Categories.ToList();
CategoryViewModel categoryViewModel = new CategoryViewModel();
categoryViewModel.Posts = post;
categoryViewModel.Categories = cats;
return View(categoryViewModel);
}
And finally here is my view:
<label for="postCategory">Category</label>
<select>
#foreach (var cats in Model.Categories)
{
<option value="#Html.DisplayFor(m => cats.Id)">
#Html.DisplayFor(m => cats.Title)
</option>
}
</select>
My question is how to make something like this in view:
<option value="#Html.DisplayFor(m => cats.Id)" **if(post.Category = cats.Id){ print selected }**>
#Html.DisplayFor(m => cats.Title)
</option>
Try and change your ForEach Loop like this:
#foreach (var cats in Model.Categories)
{
<!option value="#cats.Id" #((#Model.Posts.FirstOrDefault == cats.Id) ? "selected" : string.Empty)>#cats.Title()</!option>
}
Important ist the ! in the tag.

Use Enum Values in DropDownListFor

This is my ViewModel:
public class EntityViewModel
{
[Required(ErrorMessage = "Title is required")]
[StringLength(255)]
[DisplayName("Title")]
public string Title { get; set; }
[Required(ErrorMessage = "Description is required")]
[DisplayName("Description")]
public string Description { get; set; }
[Required]
public DateTime StartTime { get; set; }
[Required]
public DateTime EndTime { get; set; }
[Required]
public Decimal InstantSellingPrice { get; set; }
public Nullable<Decimal> ShippingPrice { get; set; }
public Int64 Views { get; set; }
public Int32 UserId { get; set; }
public int RegionId { get; set; }
public short SelectCategoryId { get; set; }
public SelectList Categories { get; set; }
public IEnumerable<HttpPostedFileBase> Files { get; set; }
public Condition? Condition { get; set; }
}
public enum Condition
{
New=1,
Used=2
}
This is my Create Action in my Controller:
public ActionResult Create()
{
ViewBag.DropDownList = ReUzze.Helpers.EnumHelper.SelectListFor<Condition>();
var model = new ReUzze.Models.EntityViewModel
{
Categories = new SelectList(this.UnitOfWork.CategoryRepository.Get(), "Id", "Name")
};
return View(model);
}
In my Create View:
<div class="form-group">
#Html.LabelFor(model => model.Condition)
#Html.DropDownListFor(model => model.Condition, ViewBag.DropDownList as SelectList, null)
</div>
I am using the Enumhelper that you can find here.
But now I always get this error in my Create View on this rule:
#Html.DropDownListFor(model => model.Condition, ViewBag.DropDownList as SelectList, null)
The error:
Error 1 The call is ambiguous between the following methods or properties: 'System.Web.Mvc.Html.SelectExtensions.DropDownListFor(System.Web.Mvc.HtmlHelper, System.Linq.Expressions.Expression>, System.Collections.Generic.IEnumerable, string)' and 'System.Web.Mvc.Html.SelectExtensions.DropDownListFor(System.Web.Mvc.HtmlHelper, System.Linq.Expressions.Expression>, System.Collections.Generic.IEnumerable, System.Collections.Generic.IDictionary)' c:\Users\Niels\Documents\Visual Studio 2012\Projects\ReUzze\ReUzze\Views\Entity\Create.cshtml 57 30 ReUzze
I use code like this usually.
public static class Enums {
public static IList<SelectListItem> SelectListOf<TEnum>(bool empty = false)
{
var type = typeof(TEnum);
if (type.IsEnum)
{
var list = Enum.GetValues(type)
.Cast<TEnum>()
.OrderBy(x => x)
.Select(x => new SelectListItem { Text = GetDescription(x), Value = x.ToString() })
.ToList();
if (empty)
{
list.Insert(0, new SelectListItem());
}
return list;
}
return new List<SelectListItem>();
}
private static string GetDescription(object enumerator)
{
try
{
//get the enumerator type
Type type = enumerator.GetType();
//get the member info
MemberInfo[] memberInfo = type.GetMember(enumerator.ToString());
//if there is member information
if (memberInfo != null && memberInfo.Length > 0)
{
//we default to the first member info, as it's for the specific enum value
object[] attributes = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
//return the description if it's found
if (attributes != null && attributes.Length > 0)
return ((DescriptionAttribute)attributes[0]).Description;
}
//if there's no description, return the string value of the enum
return enumerator.ToString();
}
catch (Exception e)
{
return string.Empty;
}
}
}
Then you can use it like this:
Conditions = Enums.SelectListOf<Condition>();
Check out my blog post on this very subject.
http://jnye.co/Posts/4/creating-a-dropdown-list-from-an-enum-in-mvc-and-c%23
Here is an enum helper I use that turns an enum into a select list. Note: If the enum has a description (using the DescriptionAttribute) it will use that as its display text
public static class EnumHelper
{
// Get the value of the description attribute if the
// enum has one, otherwise use the value.
public static string GetDescription<TEnum>(this TEnum value)
{
var fi = value.GetType().GetField(value.ToString());
if (fi != null)
{
var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes.Length > 0)
{
return attributes[0].Description;
}
}
return value.ToString();
}
/// <summary>
/// Build a select list for an enum
/// </summary>
public static SelectList SelectListFor<T>() where T : struct
{
Type t = typeof(T);
return !t.IsEnum ? null
: new SelectList(BuildSelectListItems(t), "Value", "Text");
}
/// <summary>
/// Build a select list for an enum with a particular value selected
/// </summary>
public static SelectList SelectListFor<T>(T selected) where T : struct
{
Type t = typeof(T);
return !t.IsEnum ? null
: new SelectList(BuildSelectListItems(t), "Value", "Text", selected.ToString());
}
private static IEnumerable<SelectListItem> BuildSelectListItems(Type t)
{
return Enum.GetValues(t)
.Cast<Enum>()
.Select(e => new SelectListItem { Value = e.ToString(), Text = e.GetDescription() });
}
}
Once you have this helper class in place you can do the following.
In your controller:
//If you don't have an enum value use the type
ViewBag.DropDownList = EnumHelper.SelectListFor<MyEnum>();
//If you do have an enum value use the value (the value will be marked as selected)
ViewBag.DropDownList = EnumHelper.SelectListFor(MyEnum.MyEnumValue);
In your View:
#Html.DropDownList("DropDownList")
#* OR *#
#Html.DropDownListFor(m => m.Property, ViewBag.DropDownList as SelectList, null)
if you want a quick workaround just for this one view you can do something like this. Although Khalid's approach is recommended.
<select id = 'myenumdropdown' class='something'>
#foreach(var item in Enum.GetValues(typeof('yourenumtype')))
{
<option value=item.ToHashCode()>item.ToString()</option>
}
</select>