Reputation: 145
I have a code like this
public async Task<IActionResult> Index(string[] searchString, string sortOrder)
{
ViewBag.CurrentFilter = searchString;
ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "Name desc" : "";
ViewBag.PriceSortParm = sortOrder == "Price" ? "Price desc" : "Price";
var cosmetics = from s in db.Cosmetics
select s;
//Sorting logic
switch (sortOrder)
{
case "Name desc":
cosmetics = cosmetics.OrderByDescending(s => s.Name);
break;
case "Price":
cosmetics = cosmetics.OrderBy(s => s.Price);
break;
case "Price desc":
cosmetics = cosmetics.OrderByDescending(s => s.Price);
break;
default:
cosmetics = cosmetics.OrderBy(s => s.Name);
break;
}
//Filter data logic
if (searchString.Length != 0)
{
var li = new List<Cosmetic>();
foreach (string ss in searchString)
{
List<Cosmetic> ll = cosmetics.Where(c => c.Name.Contains(ss)).ToList();
li.AddRange(ll);
}
return View(li);
}
return View(await cosmetics.ToListAsync());
}
I want data filtering and sorting to work together. I tried to connect them, but the result was such that all products were displayed regardless of what I passed to "string [] searchString"
Update
Filter data:
<form asp-action="Index" method="get">
<input class="form-control col-md-8 d-inline-block align-middle" type="checkbox" name="searchString" placeholder="Find" value="A" />
<input class="form-control col-md-8 d-inline-block align-middle" type="checkbox" name="searchString" placeholder="Find" value="B" />
<input class="btn btn-info" type="submit" value="Search" />
</form>
Sorting:
<a class="m-1" asp-action="Index" asp-route-sortOrder="@ViewBag.NameSortParm" asp-route-searchString="@ViewBag.CurrentFilter">Name</a>
<a class="m-1" asp-action="Index" asp-route-sortOrder="@ViewBag.PriceSortParm" asp-route-searchString="@ViewBag.CurrentFilter">Price</a>
Upvotes: 0
Views: 950
Reputation: 8459
The searchString
is a string array, which can not be regonized in asp-route-searchString
. I suggest you could receive the two searchString separately.
Filter:
<form id="my_form" asp-action="Index" method="get">
<input class="form-control col-md-8 d-inline-block align-middle" type="checkbox" name="searchString1" placeholder="Find" value="A" />
<input class="form-control col-md-8 d-inline-block align-middle" type="checkbox" name="searchString2" placeholder="Find" value="B" />
<input class="btn btn-info" type="submit" value="Search" />
</form>
Sorting:
<a class="m-1" asp-action="Index" asp-route-sortOrder="@ViewBag.NameSortParm" asp-route-searchString1="@ViewBag.CurrentFilter1" asp-route-searchString2="@ViewBag.CurrentFilter2">Name</a>
<a class="m-1" asp-action="Index" asp-route-sortOrder="@ViewBag.PriceSortParm" asp-route-searchString1="@ViewBag.CurrentFilter1" asp-route-searchString2="@ViewBag.CurrentFilter2">Price</a>
Controller:
public IActionResult Index(string searchString1, string searchString2, string sortOrder)
{
ViewBag.CurrentFilter1 = searchString1;
ViewBag.CurrentFilter2 = searchString2;
ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "Name desc" : "";
ViewBag.PriceSortParm = sortOrder == "Price" ? "Price desc" : "Price";
//filter and sort
}
Update:
If you have different filter conditions, I think javasript can meet it. You could get the filter and sort condition in js then append them as querstring to url manually.
I have made an example based on this, you can refer to below codes:
Model:
public class Car
{
public int Id { get; set; }
public string Name { get; set; }
public string Color { get; set; }
public string Manufacturer { get; set; }
public string Price { get; set; }
}
View:
@model IEnumerable<Car>
@{
ViewData["Title"] = "Home Page";
}
<form id="my_form" asp-action="Index" method="get">
<label>Color:</label>
<input type="checkbox" name="color" value="black" /><span>Black</span>
<input type="checkbox" name="color" value="white" /><span>White</span>
<br />
<label>Manufacturer:</label>
<input type="checkbox" name="manufacturer" value="A" /><span>A</span>
<input type="checkbox" name="manufacturer" value="B" /><span>B</span>
<input type="checkbox" name="manufacturer" value="C" /><span>C</span>
<input type="checkbox" name="manufacturer" value="D" /><span>D</span>
<input class="btn btn-info float-right" type="submit" value="Search" />
</form>
<table class="table">
<thead>
<tr>
<th>
<a class="sort" id="sortname" data-sortorder="@ViewBag.NameSortParm" href="javascript:void(0)" >@Html.DisplayNameFor(model => model.Name)</a>
</th>
<th>
@Html.DisplayNameFor(model => model.Color)
</th>
<th>
@Html.DisplayNameFor(model => model.Manufacturer)
</th>
<th>
<a class="sort" id="sortprice" data-sortorder="@ViewBag.PriceSortParm" href="javascript:void(0)" >@Html.DisplayNameFor(model => model.Price)</a>
</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Color)
</td>
<td>
@Html.DisplayFor(modelItem => item.Manufacturer)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
</tr>
}
</tbody>
</table>
@section scripts{
<script>
var color = @Html.Raw(Json.Serialize(ViewBag.color));
var manufacturer = @Html.Raw(Json.Serialize(ViewBag.manufacturer));
$(function () {
var checkoptions = [];
checkoptions = color.concat(manufacturer);
$('input[type=checkbox]').each(function () {
if (checkoptions.includes(this.value)) {
$(this).prop("checked", true);
}
});
})
$(".sort").click(function () {
var sortorder = $(this).data('sortorder');
var link = "/Home/Index?";
color.forEach(function (value) {
link += "color=" + value + "&";
});
manufacturer.forEach(function (value) {
link += "manufacturer=" + value + "&";
});
link += "sortOrder=" + sortorder;
window.location.href = link;
})
</script>
}
Controller:
public IActionResult Index(string[] color, string[] manufacturer, string sortOrder)
{
ViewBag.color = color;
ViewBag.manufacturer = manufacturer;
ViewBag.NameSortParm = string.IsNullOrEmpty(sortOrder) ? "Name_desc" : "";
ViewBag.PriceSortParm = sortOrder == "Price" ? "Price_desc" : "Price";
var cars = _context.Car.ToList();
var co_cars = new List<Car>();
var ma_cars = new List<Car>();
if (color.Length != 0)
{
foreach (string co in color)
{
var colorfiltercars = _context.Car.Where(c => c.Color.Contains(co)).ToList();
co_cars.AddRange(colorfiltercars);
}
}
else
{
co_cars = cars;
}
if (manufacturer.Length != 0)
{
foreach (string ma in manufacturer)
{
var manufacturerfiltercars = _context.Car.Where(c => c.Manufacturer.Contains(ma)).ToList();
ma_cars.AddRange(manufacturerfiltercars);
}
}
else
{
ma_cars = cars;
}
var filtercars = co_cars.Intersect(ma_cars);
switch (sortOrder)
{
case "Name_desc":
filtercars = filtercars.OrderByDescending(s => s.Name);
break;
case "Price":
filtercars = filtercars.OrderBy(s => int.Parse(s.Price));
break;
case "Price_desc":
filtercars = filtercars.OrderByDescending(s => int.Parse(s.Price));
break;
default:
filtercars = filtercars.OrderBy(s => s.Name);
break;
}
return View(filtercars.ToList());
}
And the Datasource:
Result:
Upvotes: 1
Reputation: 4809
Try to debug it by checking if searchString is passed to your controller. Also, check the updated code to make it easier to read.
public async Task<IActionResult> Index(string[] searchString, string sortOrder)
{
ViewBag.CurrentFilter = searchString;
ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "Name desc" : "";
ViewBag.PriceSortParm = sortOrder == "Price" ? "Price desc" : "Price";
var cosmetics = from s in db.Cosmetics
select s;
//Filter data logic
if (searchString.Length != 0)
{
cosmetics = cometics.Where(c => searchString.Any(s => s.Contains(c.Name)));
}
//Sorting logic
switch (sortOrder)
{
case "Name desc":
cosmetics = cosmetics.OrderByDescending(s => s.Name);
break;
case "Price":
cosmetics = cosmetics.OrderBy(s => s.Price);
break;
case "Price desc":
cosmetics = cosmetics.OrderByDescending(s => s.Price);
break;
default:
cosmetics = cosmetics.OrderBy(s => s.Name);
break;
}
return View(await cosmetics.ToListAsync());
}
Upvotes: 0