我想用Ajax在razor页面中实现搜索、分页和排序。我使用视图组件来显示数据库中的数据,因为这些是我的文件代码 在 ViewComponent.cs 中
public async Task<IViewComponentResult> InvokeAsync(int categoryId, string search, string sort, int page, int pageSize)
{
var items = await _equipmentRepository.GetEquipmentActive();
// Filtering by category
if (categoryId > 0)
{
items = items.Where(x => x.HealthProjectUsefilCategoryId == categoryId).ToList();
}
// Searching
if (!string.IsNullOrEmpty(search))
{
items = items.Where(x => x.Name != null && x.Name.Contains(search, StringComparison.OrdinalIgnoreCase)).ToList();
}
// Sorting
items = sort switch
{
"Price" => items.OrderBy(x => x.Price).ToList(),
"Priority" => items.OrderBy(x => x.Priority).ToList(),
_ => items
};
// Pagination
var pagedItems = items.Skip((page - 1) * pageSize).Take(pageSize).ToList();
// JSON response
var result = new
{
Items = pagedItems.Select(x => new
{
x.Id,
x.Name,
x.Price,
x.Priority,
x.Description,
x.ImageUrl,
x.ModifyDate
}),
TotalCount = items.Count,
CurrentPage = page,
TotalPages = (int)Math.Ceiling(items.Count / (double)pageSize)
};
foreach (var item in items)
{
Console.WriteLine($"Equipment: {item.Name}, ID: {item.Id}");
}
var viewModel = new EquipmentViewModel
{
Equipments = pagedItems,
TotalCount = items.Count,
CurrentPage = page,
TotalPages = (int)Math.Ceiling(items.Count / (double)pageSize)
};
return View(viewModel);
}
在 Default.cshtml 中的视图中,这些是我的代码
@using DNTPersianUtils.Core
@using KH.Services;
@model KH.Models.EquipmentViewModel;
@foreach (var card in Model.Equipments)
{
<article class="postcard light blue">
<a class="postcard__img_link" href="#">
<img class="postcard__img" src="@card.ImageUrl" alt="@card.Name" />
</a>
<div class="postcard__text t-dark">
<h1 class="postcard__title"><a href="#">@card.Name</a></h1>
<div class="postcard__subtitle small">
<time datetime="@card.ModifyDate.ToString("yyyy-MM-ddTHH:mm:ss")">
<i class="fas fa-calendar-alt mr-2"></i>
@DNTPersianUtils.Core.PersianDateTimeUtils.ToShortPersianDateString(card.ModifyDate).ToPersianNumbers()
</time>
</div>
<div class="postcard__bar"></div>
<div class="postcard__preview-txt">@card.Description</div>
<ul class="postcard__tagbox">
<li class="tag__item"><i class="fas fa-tag mr-2"></i>تعداد مورد نیاز:
@card.Quantity.ToPersianNumbers()</li>
<li class="tag__item"><i class="fas fa-tag mr-2"></i>
قیمت:@DNTPersianUtils.Core.PersianNumbersUtils.ToPersianNumbers(string.Format("{0:N0}",
(int)@card.Price)) ریال
@* (@card.Price.ToPersianNumbers())*@</li>
<li class="tag__item"><i class="fas fa-clock mr-2"></i>تعداد تهیه شده تاکنون .</li>
<li class="tag__item play blue">
<a asp-page="/ReceiptPages/DefineDonation" asp-route-Amount="@card.Price" asp-area=""><i
class="fas fa-play mr-2"></i>کمک مالی</a>
</li>
</ul>
</div>
</article>
}
这也是我在 View 中使用的 ViewModel
public class EquipmentViewModel
{
public IEnumerable<Equipment>? Equipments { get; set; } // The list of equipment items
public int TotalCount { get; set; } // Total number of filtered items
public int CurrentPage { get; set; } // The current page number
public int TotalPages { get; set; } // Total number of pages
}
这是我视图中的代码,它调用 Index.cshtml 中的视图组件,我也重新挖掘 Ajax 代码
<section class="light mt-4">
<div class="container py-2">
<div class="h1 text-center text-dark" id="pageHeaderTitle">Equipments</div>
<!-- Filters -->
<select id="category-filter" class="form-control">
<option value="0">all category</option>
@foreach (var category in Model.Categories!)
{
<option value="@category.Id">@category.Name</option>
}
</select>
<select id="sort-filter" class="form-control mt-2">
<option value="Price">price</option>
<option value="Priority">priority</option>
</select>
<input id="search-box" type="text" class="form-control mt-2" placeholder="جستجو
(min 3 character)">
<div id="equipment-list">
@await Component.InvokeAsync("EquipmentsList", new
{
categoryId = 0,
search = "",
sort = "Date",
page = 1,
pageSize = 10
})
</div>
<div id="pagination" class="pagination mt-3">
@for (int i = 1; i <= ViewBag.TotalPages; i++)
{
<button class="page-link" data-page="@i">@i</button>
}
</div>
</div>
@section Scripts {
<script>
$(document).ready(function () {
function loadEquipmentData(page = 1) {
const categoryId = $('#category-filter').val();
const sort = $('#sort-filter').val();
const search = $('#search-box').val();
// Make an AJAX request to fetch filtered data
$.ajax({
url: "/Equipment", // Ensure this endpoint handles
filtering/sorting/pagination
data: { categoryId, sort, search, page, pageSize: 10 },
success: function (result) {
// Replace only the equipment list content
$('#equipment-list').html(result);
},
error: function () {
alert("Failed to load data!");
}
});
}
// Attach event handlers (ensure no duplicates using .off())
$('#category-filter').off('change').on('change', function () {
loadEquipmentData(1); // Load data for the first page
});
$('#sort-filter').off('change').on('change', function () {
loadEquipmentData(1); // Load data for the first page
});
$('#search-box').off('input').on('input', function () {
if ($(this).val().length >= 3 || $(this).val().length === 0) {
loadEquipmentData(1); // Load data for the first page
}
});
$(document).off('click', '.page-link').on('click', '.page-link', function (e) {
e.preventDefault(); // Prevent default navigation behavior
const page = $(this).data('page');
loadEquipmentData(page); // Load data for the clicked page
});
});
</script>
}
我在更改下拉列表的任何字段后检查了页面源,它将创建从 HTMl 标记开始到容器的重复页面。我认为加载 Ajax 或 jquery 时遇到问题。 你有什么建议?
它将创建从 HTMl 标签开始到 容器。我想我在加载 Ajax 或 jquery 时遇到问题
我不知道你在这里的意思是什么。在您的代码片段中,您现在尝试通过 ajax 请求更改视图内容。在ajax请求的响应中,它应该具有与您可以获得的格式相同的html内容
@await Component.InvokeAsync("Equipment", new
{
categoryId = 0,
search = "",
sort = "Date",
page = 1,
pageSize = 10
})
然后在你的ajax请求中,你将URL设置为
url: "/Equipment"
,但你没有共享它,所以在我这边,除了硬编码数据库查询结果之外,我还在HomeController中创建了一个POST端点,如下所示。
public IActionResult Equipment() {
return View();
}
[HttpPost]
public IActionResult GetEquipment(int categoryId, string search, string sort, int page, int pageSize)
{
//return View(viewModel);
return ViewComponent("Equipment",
new
{
categoryId = categoryId,
search = search,
sort = sort,
page = page,
pageSize = 10
});
}
我的ajax请求就像
$.ajax({
url: "/home/GetEquipment", // Ensure this endpoint handles filtering/sorting/pagination
type: "post",
data: { categoryId, sort, search, page, pageSize: 10 },
success: function (result) {
// Replace only the equipment list content
$('#equipment-list').html(result);
},
error: function () {
alert("Failed to load data!");
}
});
这是我的调用方法。
public async Task<IViewComponentResult> InvokeAsync(int categoryId, string search, string sort, int page, int pageSize)
{
//var items = await _equipmentRepository.GetEquipmentActive();
var items = new List<Equipment>();
if (sort == "Price")
{
items = new List<Equipment>{
new Equipment { Id = "11", Name = "Equ11", Price = "1001", Description="descp11"} ,
new Equipment { Id = "22", Name = "Equ22", Price = "1012", Description="descp22"} ,
new Equipment { Id = "33", Name = "Equ33", Price = "1023", Description="descp33"} ,
new Equipment { Id = "44", Name = "Equ44", Price = "1034", Description="descp44"} ,
new Equipment { Id = "55", Name = "Equ55", Price = "1045", Description="descp55"} ,
new Equipment { Id = "66", Name = "Equ66", Price = "1056", Description="descp66"} ,
new Equipment { Id = "77", Name = "Equ77", Price = "1067", Description="descp77"} ,
new Equipment { Id = "88", Name = "Equ88", Price = "1078", Description="descp88"} ,
};
}
else {
items = new List<Equipment>() {
new Equipment { Id = "1", Name = "Equ1", Price = "100", Description="descp1"} ,
new Equipment { Id = "2", Name = "Equ2", Price = "101", Description="descp2"} ,
new Equipment { Id = "3", Name = "Equ3", Price = "102", Description="descp3"} ,
new Equipment { Id = "4", Name = "Equ4", Price = "103", Description="descp4"} ,
new Equipment { Id = "5", Name = "Equ5", Price = "104", Description="descp5"} ,
new Equipment { Id = "6", Name = "Equ5", Price = "105", Description="descp6"} ,
new Equipment { Id = "7", Name = "Equ6", Price = "106", Description="descp7"} ,
new Equipment { Id = "8", Name = "Equ7", Price = "107", Description="descp8"} ,
};
}
var pagedItems = items.Skip((page - 1) * pageSize).Take(pageSize).ToList();
var result = new
{
Items = pagedItems.Select(x => new
{
x.Id,
x.Name,
x.Price,
//x.Priority,
x.Description
//x.ImageUrl,
//x.ModifyDate
}),
TotalCount = items.Count,
CurrentPage = page,
TotalPages = (int)Math.Ceiling(items.Count / (double)pageSize)
};
foreach (var item in items)
{
Console.WriteLine($"Equipment: {item.Name}, ID: {item.Id}");
}
var viewModel = new EquipmentViewModel
{
Equipments = pagedItems,
TotalCount = items.Count,
CurrentPage = page,
TotalPages = (int)Math.Ceiling(items.Count / (double)pageSize)
};
return View(viewModel);
}