Set selected items in asp.core razor pages - html

I'm using ASP Core Razor pages.
This my Edit.cshtml.cs:
[BindProperty]
public List<Microsoft.AspNetCore.Mvc.Rendering.SelectListItem> CCusers { get; set; }
and here I fill CCusers with data:
CCusers =new List<Microsoft.AspNetCore.Mvc.Rendering.SelectListItem>() {
new Microsoft.AspNetCore.Mvc.Rendering.SelectListItem() { Value = "1", Text = "HR", Selected = true },
new Microsoft.AspNetCore.Mvc.Rendering.SelectListItem() { Value = "2", Text = "IT", Selected = false },
new Microsoft.AspNetCore.Mvc.Rendering.SelectListItem() { Value = "3", Text = "Account", Selected = false },
};
In Razor Page, I used two different select:
<select asp-for="CCusers" asp-items="#Model.CCusers" id="CCusers" multiple="multiple" class="selectpicker"> </select>
//and this:
#Html.DropDownList("NewSelect", Model.CCusers, new { #class = "selectpicker", #multiple = "multiple" })
and this the result of both of them:
<select id="CCusers" multiple="multiple" class="selectpicker" name="CCusers">
<option value="1">HR</option>
<option value="2">IT</option>
<option value="3">Account</option>
</select>
<select class="selectpicker" id="NewSelect" multiple="multiple" name="NewSelect">
<option selected="selected" value="1">HR</option>
<option value="2">IT</option>
<option value="3">Account</option>
</select>
The Core Select didn't set the selected item while the #Httml.DropDownList did it.
What I'm missing in the first select?

For Select Tag Helper, you will need to set asp-for which specifies the model proprety name for the select element.
For your issue, you need to define new property for selected CCusers instead of binding the CCusers to asp-for directly.
You could refer code below:
Page
public class EditModel : PageModel
{
[BindProperty]
public int[] SelectedCCuserIds { get; set; }
[BindProperty]
public List<SelectListItem> CCusers { get; set; }
public void OnGet()
{
SelectedCCuserIds = new int[] { 1, 2 };
CCusers = new List<SelectListItem>() {
new SelectListItem() { Value = "1", Text = "HR" },
new SelectListItem() { Value = "2", Text = "IT" },
new SelectListItem() { Value = "3", Text = "Account" },
};
}
public IActionResult OnPost()
{
var result = SelectedCCuserIds;
return RedirectToAction("OnGet");
}
}
View
#page
#model CoreRazor.Pages.EditModel
#{
ViewData["Title"] = "Edit";
}
<h2>Edit</h2>
<form method="post">
<select asp-for="#Model.SelectedCCuserIds" asp-items="#Model.CCusers"
multiple="multiple" class="selectpicker"> </select>
#*#Html.DropDownList("NewSelect", Model.CCusers, new { #class = "selectpicker",
#multiple = "multiple" })*#
<div class="form-group">
<input type="submit" value="Save" class="btn btn-default" />
</div>

Related

MultiSelectList displaying only one selected value out of Selectedvalues

For httppost method MultiSelectList shows only one value in view side.
My view
<div class="col-md-6 form-group">
<select class="form-control selectpicker" required="" asp-for="DomID" asp-items=" ViewBag.DomList as MultiSelectList" multiple data-live-search="true"
placeholder="Select Categories"
onchange="console.log($(this).children(':selected').length)">
</select>
</div>
MY Controller
[HttpPost]
public IActionResult controllerAction([Bind]LogModel logmodel)
{
logmodel.selectedvals= // Has Submitted/selected values
List<LogModel> domList = new List<LogModel>();
domList = ;//getting values for dropdown
ViewBag.DomList = new MultiSelectList(domList , "DomID", "Dom", logmodel.selectedvals);
return view(logmodel);
}
My dropdown shows only one value selected from out of all selected values i.e.. from
logmodel.selectedvals in post action.
If I set hardcode selected values in httpget method for multiselectlist then it's shows
selected values properly. What I'm doing wrong here?
Updated
Log Model
public Int64 DomID { get; set; }
public string Dom { get; set; }
public List<Int64> selectedvals { get; set; }
Try to remove logmodel from return view(logmodel);
Below is a work demo, you can refer to it , hope it can help.
In Controller:
public IActionResult SetList()
{
return View();
}
[HttpPost]
public IActionResult ShowMList(LogModel logmodel)
{
List<LogModel> domList = new List<LogModel>();
domList.Add(new LogModel() { DomID = 1, Dom = "AA" });
domList.Add(new LogModel() { DomID = 2, Dom = "BB" });
domList.Add(new LogModel() { DomID = 3, Dom = "CC" });
ViewBag.DomList = new MultiSelectList(domList, "DomID", "Dom", logmodel.selectedvals);
return View();
}
SetList.cshtml:
#model LogModel
<form asp-action="ShowMList">
<select name="selectedvals" class="form-control" multiple>
<option value="1">AA</option>
<option value="2">BB</option>
<option value="3">CC</option>
</select>
<input type="submit" value="submit" />
</form>
ShowMList.cshtml:
#model LogModel
<div class="col-md-6 form-group">
<select class="form-control selectpicker" required="" asp-for="DomID" asp-items=" ViewBag.DomList as MultiSelectList" multiple data-live-search="true"
placeholder="Select Categories"
onchange="console.log($(this).children(':selected').length)">
</select>
</div>
result:
In aspfor int was using int instead of <int>

How to give a range in search in html and ASP.NET Core

I get data from database using SQL in ASP.NET Core. I can search area and price just giving the number but now I have to give range like 10 to 20 or etc. In search a web site zameen.com in which it exactly match with my requirements. But I do not know how to do this.
This is what I want:
My view:
<input list="Input.area.list"asp-for="Input.area" placeholder="Please Select area" style="height :50px; border-style:solid ;border-color: black;border-radius:5px; margin-left:20px;">
<datalist id="Input.area.list">
<option value="10"></option>
<option value="12"></option>
<option value="15"></option>
<option value="20"></option>
<option value="25"></option>
<option value="30"></option>
<option value="35"></option>
<option value="40"></option>
<option value="45"></option>
<option value="50"></option>
<option value="55"></option>
</datalist>
</input>
Controller:
public IActionResult Rent(inputModel input, int PageNumber = 1)
{
var data = rdb.GetDataHouse();
var datas = rdb.GetDataHouse();
ViewBag.Data = datas.ToList().Take(7);
ViewBag.Totalpages = Math.Ceiling(data.Count() / 6.0);
if (!string.IsNullOrEmpty(input.areaunit))
{
data = data.Where(x => x.areaUnit == input.areaunit & x.area <= input.area & x.price <= input.price).ToList();
}
data = data.Skip((PageNumber - 1) * 6).Take(6).ToList();
var viewModel = new RentModel
{
Data = data,
//SearchList = List<string>(),
Input = new inputModel(),
};
return View(viewModel);
}
Demo:
Here is a simple demo about it, Hope it can give you some help:
Model:
public class TestModel
{
public int Id { get; set; }
public string Name { get; set; }
public int Area { get; set; }
}
public class TestViewModel
{
[Required(ErrorMessage ="Please select a min value")]
public string min { get; set; }
[Required(ErrorMessage = "Please select a max value")]
public string max { get; set; }
}
Action:
public IActionResult Range()
{
List<SelectListItem> test = new List<SelectListItem>();
//generate some options for use to select
test.Add(new SelectListItem { Text = "10 ", Value = "10 " });
test.Add(new SelectListItem { Text = "20 ", Value = "20 " });
test.Add(new SelectListItem { Text = "30 ", Value = "30 " });
test.Add(new SelectListItem { Text = "40 ", Value = "40 " });
test.Add(new SelectListItem { Text = "50 ", Value = "50 " });
test.Add(new SelectListItem { Text = "60 ", Value = "60 " });
ViewBag.data = test;
return View();
}
[HttpPost]
public IActionResult Range(TestViewModel model)
{
var result = _dbContext.testModels.Where(x => x.Area >= Int32.Parse(model.min) && x.Area<= Int32.Parse(model.max)).ToList();
//....code......
return View();
}
View:
#model TestViewModel
<form method="post">
<h1>Please select a Range for Area</h1>
<div class="form-group">
<label asp-for="min" class="control-label"></label>
<select asp-for="#Model.min" asp-items="#ViewBag.data">
<option value="">Please select a value</option>
</select>
<span asp-validation-for="min" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="max" class="control-label"></label>
<select asp-for="#Model.max" asp-items="#ViewBag.data" placeholder="Please Select area">
<option value="">Please select a value</option>
</select>
<span asp-validation-for="max" class="text-danger"></span>
</div>
<button type="submit">Submit</button>
</form>
#section Scripts {
#{
await Html.RenderPartialAsync("_ValidationScriptsPartial");
}
}
Demo:
Note:
You also need to set the maximum value in the drop-down list cannot be less than or equal to the minimum value. You can use javascript or fluent validation to achieve it.

Get value from selected option and pass it to the function

Hi im making a reservation page in razor pages asp.net. On my page I have two drop downlist. One for the location other for the rooms of that specific location. I want to pass the value of that selected location to the function which shows the rooms (function is named showRoom()), so that the rooms will be shown depending on which location you selected. How do i do that with html? I tried something but didnt really work. Here is the html code
<td>Select location</td>
<div class="form-group">
<select id="locations" name="Location">
#foreach(var reservations in #Model.PopulateReservations())
{
<option>#Html.DisplayFor(m => reservations.LocationName)</option>
}
</select>
</div>
<td>Select Room</td>
<div class="form-group">
<select id="rooms" name="Room">
#foreach(var reservations in #Model.ShowRoom(string LocationName))
{
<option>#Html.DisplayFor(m => reservations.RoomName)</option>
}
</select>
</div>
Here is the function showRoom
public List<WorkspaceModel> ShowRoom(string loc)
{
var cs = Database.Database.Connector();
List<WorkspaceModel> res = new List<WorkspaceModel>();
using var con = new NpgsqlConnection(cs);
{
string query = "Select room FROM workspaces WHERE location = '"+ loc +"'";
using NpgsqlCommand cmd = new NpgsqlCommand(query, con);
{
cmd.Connection = con;
con.Open();
using (NpgsqlDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
{
res.Add(new WorkspaceModel { RoomName = dr["room"].ToString() });
}
}
con.Close();
}
}
Here is a demo(I use fake data to test):
class:
public class PopulateReservation
{
public string LocationName { get; set; }
}
public class WorkspaceModel
{
public string RoomName { get; set; }
}
TestDropDown.cshtml:
<td>Select location</td>
<div class="form-group">
<select id="locations" name="Location">
#foreach (var reservations in #Model.PopulateReservations)
{
<option>#Html.DisplayFor(m => reservations.LocationName)</option>
}
</select>
</div>
<td>Select Room</td>
<div class="form-group">
<select id="rooms" name="Room">
#foreach (var reservations in #Model.Rooms)
{
<option>#Html.DisplayFor(m => reservations.RoomName)</option>
}
</select>
</div>
<form>
#Html.AntiForgeryToken()
</form>
#section scripts{
<script>
$('#locations').on('change', function () {
var arr = [];
$.ajax({
type: "POST",
url: '?handler=ShowRoom',
headers: {
RequestVerificationToken: $('input:hidden[name="__RequestVerificationToken"]').val()
},
data: { "loc": $("#locations").val() },
dataType:"json"
}).done(function (data) {
$("#rooms").empty();
$.each(data, function (i, item) {
$("#rooms").append('<option> ' + item["roomName"] + ' </option>');
});
});
});
</script>
}
TestDropDown.cshtml.cs:
public class TestDropDownModel : PageModel
{
[BindProperty]
public List<PopulateReservation> PopulateReservations { get; set; }
[BindProperty]
public List<WorkspaceModel> Rooms { get; set; }
public IActionResult OnGet()
{
PopulateReservations = new List<PopulateReservation> {
new PopulateReservation { LocationName = "location1" },
new PopulateReservation { LocationName = "location2" },
new PopulateReservation { LocationName = "location3" }
};
Rooms = new List<WorkspaceModel> {
new WorkspaceModel { RoomName = "Room1" },
new WorkspaceModel { RoomName = "Room2" },
new WorkspaceModel { RoomName = "Room3" },
};
return Page();
}
public IActionResult OnPost()
{
return Page();
}
public IActionResult OnPostShowRoom(string loc)
{
List<WorkspaceModel> l= new List<WorkspaceModel> {
new WorkspaceModel { RoomName = loc + "Room1" },
new WorkspaceModel { RoomName = loc + "Room2" },
new WorkspaceModel { RoomName = loc + "Room3" },
};
return new JsonResult(l);
}
}
result:

Blazor Two Way Binding <select>/<option>

Running into issues trying to update list options in a select. When Function One button is clicked, it fires functionTwo which returns a new list, that should now be the updated list shown in the <select>/<option>
Can someone educate me on what I am not getting correct?
<button ... #onclick="functionOne">Function One</button>
<select #bind="#SelectedValue">
#foreach (var val in updatedList)
{
<option value="#val">#val</option>
}
</select>
public void functionOne()
{
...
List<string> updatedList ...
updatedList = functionTwo();
...
}
public List<string> functionTwo()
{
...
return strList ;
}
Copy this into index.razor of blazor see if it works
#page "/"
<p>#SelectedValue</p>
<button #onclick="functionOne">Function One</button>
<select #bind="#SelectedValue">
#foreach (var val in updatedList)
{
<option value="#val">#val</option>
}
</select>
#code
{
string SelectedValue { get; set; }
List<string> updatedList = new List<string>();
private void functionOne()
{
updatedList = functionTwo();
}
public List<string> functionTwo()
{
return new List<string> { "AAA", "BBB", "CCC" };
}
}

MVC view code for bool type input

In one of my first MVC projects I encountered the following part of code in my "Create" view.
<div class="form-group">
#Html.LabelFor(model => model.Attend, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
#Html.EditorFor(model => model.Attend)
#Html.ValidationMessageFor(model => model.Attend, "", new { #class = "text-danger" })
</div>
</div>
</div>
This was scaffolded based on the following property in my model:
public virtual bool? Attend { get; set; }
What this will show for me on the "Create" view is a dropdown with the following values: Not Set; True; False;
Is there a way I can change these values in the dropdownlist for my bool so that it says something more readable/understandable for a user like: Yes; No;?
I tried to search for a solution and I think it has something to do with the following line:
#Html.EditorFor(model => model.Attend)
As #Stephen Muecke said you can create your own selectlist. You can do it with your own editor template .
Here is how i have done it:
Create EditorTeplates folder in Views/Shared
Create YesNoNotSelected.cshtml in this folder with this code:
#model bool?
#Html.DropDownList("", new SelectListItem[]
{
new SelectListItem()
{
Text = "Not set",
Value = String.Empty,
Selected = !Model.HasValue
},
new SelectListItem()
{
Text = "True",
Value = "true",
Selected = Model.HasValue && Model.Value
},
new SelectListItem()
{
Text = "False",
Value = "false",
Selected = Model.HasValue && !Model.Value
}
})
In your model add UIHintAttribute above Attend property like this:
[UIHint("YesNoNotSelected")]
public virtual bool? Attend { get; set; }
Now EditorFor helper should render your property according to this template.
I like the best of all worlds scenario:
I don't want to always require a UIHint
I don't want to use UIHint at all, it's not descriptive
I want bools to be extensible; yes/no, true/false, etc
Here is how I implemented it:
/Models/BooleanType.cs
public enum BooleanDisplay
{
undefined = 0,
YesNo = 1,
TrueFalse = 2,
GoodEvil = 3
}
/MVC/UIBooleanType.cs
[AttributeUsage(AttributeTargets.Property)]
public class UIBooleanAttribute : UIHintAttribute
:base("boolean", "MVC")
{
public UIBoolean(BooleanType displayAs)
{
DisplayAs = displayAs;
}
public BooleanDisplay DisplayAs { get; set; }
}
/Views/Shared/EditorTemplates/boolean.cshtml
#model boolean?
#{
// default
var displayAs = BooleanDisplay.TrueFalse;
var uiBoolean = ViewData
.ModelMetadata
.ContainerType
.GetProperty(ViewData.ModelMetadata.PropertyName)
.GetCustomAttributes(typeof(UIBooleanAttribute))
.Select(ca => ca as UIBooleanAttribute)
.FirstOrDefault(ca => ca != null);
if (uiBoolean != null)
{
displayAs = uiBoolean.DisplayAs;
}
var values = new List<SelectListItem>()
{
new SelectListItem()
{
Text = "Not set",
Value = String.Empty,
Selected = !Model.HasValue
}
};
switch(displayAs)
{
default:
throw new NotImplementedException(displayAs.ToString()
+ " is not implemented in boolean.cshtml";
YesNo:
values.Add(new SelectListItem()
{
Text = "Yes",
Value = "true",
Selected = Model.HasValue && Model.Value
});
values.Add(new SelectListItem()
{
Text = "No",
Value = "false",
Selected = Model.HasValue && !Model.Value
});
TrueFalse:
// etc
}
}
#Html.DropDownList("", values)
usage:
ViewModel:
public class Person
{
// defaults to True/False
public bool AreYouHappy { get; set; }
[UIBoolean(BooleanDisplay.GoodEvil)]
public bool IsInherently { get; set; }
}
View:
#model Person
#Html.EditorFor(p => p.AreYouHappy)
#Html.EditorFor(p => p.IsInherently)