更改下拉列表值会在剃刀页面中产生重复页面

问题描述 投票:0回答:1

我想用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 时遇到问题。 你有什么建议?

c# ajax asp.net-core .net-core asp.net-ajax
1个回答
0
投票

它将创建从 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);
}

还有我的测试结果。 enter image description here enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.