Basic example link - following link is what I am trying to build. But this is only for single value.
Issue Detail After I select multi colors
in <select>
, Then i click <a>
tag, I want to pass the value of what i select in <select>
. Currently after clicking on <a>
tag, it wont keep values selcted inside <select>
Step#1 Here I am creating Form with 2 filters. 1 search text box and 2 selectlist
<form asp-page="./index" method="get">
<input type="text" asp-for="SearchString" />
<select asp-for="Colors" asp-items="@Model.Colors_SELECT" class="MultiSelect" multiple>...</select>
...
</form>
Step#2 Display data in table grid. <a>
is passing filters to url
<table>
....
<a asp-page="./My_Training"
asp-route-SearchString="@Model.SearchString"
asp-route-Colors="@Model.Colors"
asp-route-SortOrder="@Model.Colors_Sort">
@Html.DisplayNameFor(model => model.MyListData[0].Colors)
</a>
.. // more `<a>` tags. 1 for each column
</table>
Step#3 Back-end code: - mainly bind filter values
[BindProperty(SupportsGet = true)]
public string? SearchString { get; set; }
[BindProperty(SupportsGet = true)]
public List<string>? Colors { get; set; }
public SelectList? Colors_SELECT { get; set; }
public async Task OnGetAsync()
{
// everything is auto bind to properties
}
What I tried: according to google, they recommended using asp-all-route-data
with Dictionary
. I have tried this code and it doesnt work for multi values. Dictionary
doesnt allow same key. for example: if I use asp-all-route-data
and pass URL like Colors[0]=Red&Colors[1]=Green
than it wont keep values selected inside <select>
I also Tried to do this. This works but the code is a mess and hard to maintain if you have too many filters & columns in data grid
<input type="hidden" asp-for="URL_String" />
...
<a href="/Index? @Model.URL_String&[email protected]_Sort">
@Html.DisplayNameFor(model => model.CourseTakenList[0].Colors)
</a>
public string? URL_String { get; set; } = "";
public async Task<IActionResult> OnPostAsync()
{
string? createURL = "?";
createURL += $"SearchString={SearchString}&";
foreach (var p in Colors)
{
createURL += $"Colors={p}&";
}
if (createURL.EndsWith("?") || createURL.EndsWith("&"))
{
createURL = createURL.TrimEnd(createURL[createURL.Length - 1]); //remove last '&'
}
string url = $"{HttpContext.Request.Path}{createURL}";
return Redirect(url);
}
public async Task OnGetAsync()
{
URL_String = Request.QueryString.ToString().Replace("??", "?");
CurrentSort = Request.Query["SortOrder"];
}
Because asp-all-route-data
can't pass value with the same key, So you need to add index by yourself, Please refer to this simple demo:
@{
var colors = new Dictionary<string, string>();
var i = 0;
foreach (var item in Model.colors)
{
colors.Add($"colors[{i}]", item);
i++;
}
}
<a asp-page="index" asp-all-route-data="colors">Test</a>
It will pass data like:
?colors[0]=red&colors[1]=green&colors[2]=black
Demo:
=========================Update================
<select multiple id="selectone">
<option value="red">red</option>
<option value="black">black</option>
<option value="white">white</option>
<option value="yellow">yellow</option>
</select>
<button onclick="MySelect()">Select color</button>
<a asp-page="index" asp-route-SearchString="Test" id="color">Test</a>
<script>
function MySelect(){
var result = document.getElementById("selectone").selectedOptions;
var arr=[];
for(let i=0,len = result.length;i<len;i++){
if(result[i].selected){
arr.push("colors["+i+"]=" + result[i].value)
}
}
var str=arr.join("&");
var a = document.getElementById("color").getAttribute('href');
var url = a+ "&" + str;
document.getElementById("color").href = url;
}
</script>
Demo: