Нумерованный список с несколькими полями поиска на бритвенных страницах - PullRequest
0 голосов
/ 22 октября 2019

Я создаю приложение Razor Page, в котором мои клиенты должны искать сразу по нескольким полям, однако, когда я создаю несколько полей поиска, сам поиск работает хорошо, но разбиение на страницы в разбивке на страницы разбивается, теряя поискусловия на второй странице и возвращается к порядку нумерации страниц по умолчанию. Есть ли другой тип списка, который я должен реализовать, или есть способ условно расставить приоритеты, какое поле поиска использует разбитый на страницы список, чтобы сохранить его порядок нумерации страниц и не потерять поиск? Как новичок в разработке, я предоставлю большую часть кода в коде, так как мне все еще неясно, как все части сочетаются друг с другом, когда дело доходит до нумерации страниц, сортировки и фильтрации в Razor Pages.

Всеотлично работал, когда у меня был настроен поиск, который позволял клиенту искать по одному полю за раз, и проблема возникла, когда я внес изменения, чтобы разрешить множественный параллельный поиск.

Это код позади:

 private readonly PFDTrustContext _context;

    public IndexModel(PFDTrustContext context)
    {
        _context = context;
    }

    public PaginatedList<Client> Clients { get; set; }

    // sorting
    public string AcctNumberSort { get; set; }
    public string FirstNameSort { get; set; }
    public string LastNameSort { get; set; }
    public string SSNSort { get; set; }
    public string CurrentSort { get; set; }

    // filtering
    public string FilterLN { get; set; }
    public string FilterFN { get; set; }
    public string FilterSSN { get; set; }
    public string FilterAcctNum { get; set; }
    public string CurrentFilter { get; set; }


    public async Task OnGetAsync(string sortOrder, string searchStringLN, string searchStringFN, string searchStringSSN, string searchStringAcctNum, string filterLN, string filterFN, string filterSSN, string filterAcctNum, string currentFilter, int? pageIndex)
    {
        CurrentSort = sortOrder;

        // Sorting
        LastNameSort = string.IsNullOrEmpty(sortOrder) ? "lastName_desc" : "";
        FirstNameSort = sortOrder == "firstName" ? "firstName_desc" : "firstName";
        AcctNumberSort = sortOrder == "acctNumber" ? "acctNumber_desc" : "acctNumber";
        SSNSort = sortOrder == "SSN" ? "SSN_desc" : "SSN";

        // Paging
        if (searchStringLN != null)
        {
            pageIndex = 1;
        }
        else
        {
            searchStringLN = filterLN;
        }

        if (searchStringFN != null)
        {
            pageIndex = 1;
        }
        else
        {
            searchStringFN = filterFN;
        }

        if (searchStringSSN != null)
        {
            pageIndex = 1;
        }
        else
        {
            searchStringSSN = filterSSN;
        }

        if (searchStringAcctNum != null)
        {
            pageIndex = 1;
        }
        else
        {
            searchStringAcctNum = filterAcctNum;
        }

        // Searching/Filtering
        FilterLN = searchStringLN;
        FilterFN = searchStringFN;
        FilterSSN = searchStringSSN;
        FilterAcctNum = searchStringAcctNum;

        if (!string.IsNullOrEmpty(FilterLN))
        {
            CurrentFilter = FilterLN;
        }
        else if (!string.IsNullOrEmpty(FilterSSN))
        {
            CurrentFilter = FilterSSN;
        }
        else if (!string.IsNullOrEmpty(FilterAcctNum))
        {
            CurrentFilter = FilterAcctNum;
        }
        else
        {
            CurrentFilter = FilterFN;
        }


        // Sorting
        IQueryable<Client> clients = from c in _context.Clients
                                     select c;

        // Searching
        if (!string.IsNullOrEmpty(searchStringLN))
        {
            clients = clients.Where(c => c.LastName.ToUpper().Contains(searchStringLN.ToUpper()));
        }
        if (!string.IsNullOrEmpty(searchStringFN))
        {
            clients = clients.Where(c => c.FirstName.ToUpper().Contains(searchStringFN.ToUpper()));
        }
        if (!string.IsNullOrEmpty(searchStringSSN))
        {
            clients = clients.Where(c => c.SSN.ToString().Contains(searchStringSSN));
        }
        if (!string.IsNullOrEmpty(searchStringAcctNum))
        {
            clients = clients.Where(c => c.AcctNumber.ToString().Contains(searchStringAcctNum));
        }

        // Sorting
        switch (sortOrder)
        {
            case "lastName_desc":
                clients = clients.OrderByDescending(c => c.LastName);
                break;
            case "acctNumber":
                clients = clients.OrderBy(c => c.AcctNumber);
                break;
            case "acctNumber_desc":
                clients = clients.OrderByDescending(c => c.AcctNumber);
                break;
            case "firstName_desc":
                clients = clients.OrderByDescending(c => c.FirstName);
                break;
            case "firstName":
                clients = clients.OrderBy(c => c.FirstName);
                break;
            case "SSN":
                clients = clients.OrderBy(c => c.SSN);
                break;
            case "SSN_desc":
                clients = clients.OrderByDescending(c => c.SSN);
                break;
            default:
                clients = clients.OrderBy(c => c.LastName);
                break;
        }

        // Pagination
        int pageSize = 12;

        Clients = await PaginatedList<Client>.CreateAsync(
            clients.AsNoTracking(), pageIndex ?? 1, pageSize);
    }

Это страница Razor:

 <table class="table">
     <thead>
         <tr>
             <th>
                 @Html.DisplayNameFor(model => model.Clients[0].ClientId)
             </th>
             <th>
                 <a asp-page="./Index" asp-route-sortOrder="@Model.AcctNumberSort"
               asp-route-currentFilter="@Model.FilterAcctNum">
                     @Html.DisplayNameFor(model => model.Clients[0].AcctNumber)
                 </a>
             </th>
             <th>
                 <a asp-page="./Index" asp-route-sortOrder="@Model.FirstNameSort"
               asp-route-currentFilter="@Model.FilterFN">
                     @Html.DisplayNameFor(model => model.Clients[0].FirstName)
                 </a>
             </th>
             <th>
                 <a asp-page="./Index" asp-route-sortOrder="@Model.LastNameSort"
               asp-route-currentFilter="@Model.FilterLN">
                @Html.DisplayNameFor(model => model.Clients[0].LastName)
                 </a>
             </th>
             <th>
                 @Html.DisplayNameFor(model => model.Clients[0].MdlInit)
             </th>
             <th>
                 <a asp-page="./Index" asp-route-sortOrder="@Model.SSNSort"
               asp-route-currentFilter="@Model.FilterSSN">
                     @Html.DisplayNameFor(model => model.Clients[0].SSN)
                 </a>
             </th>
             <th>
                 @Html.DisplayNameFor(model => model.Clients[0].DOB)
             </th>
             <th>
                 @Html.DisplayNameFor(model => model.Clients[0].InitialEntryDate)
             </th>
             <th></th>
         </tr>
     </thead>
     <tbody>
         @foreach (var item in Model.Clients)
         {
         <tr>
             <td>
                 @Html.DisplayFor(modelItem => item.ClientId)
             </td>
             <td>
                 @Html.DisplayFor(modelItem => item.AcctNumber)
             </td>
             <td>
                 @Html.DisplayFor(modelItem => item.FirstName)
             </td>
             <td>
                 @Html.DisplayFor(modelItem => item.LastName)
             </td>
             <td>
                 @Html.DisplayFor(modelItem => item.MdlInit)
             </td>
             <td>
                 @Html.DisplayFor(modelItem => item.SSN, "SSN")
             </td>
             <td>
                 @Html.DisplayFor(modelItem => item.DOB)
             </td>
             <td>
                 @Html.DisplayFor(modelItem => item.InitialEntryDate)
             </td>
             <td>
                 <a asp-page="./Edit" asp-route-id="@item.ClientId">Edit Client</a> |
                 <a asp-page="./Details" asp-route-id="@item.ClientId">Transactions</a>
             </td>
         </tr>
         }
     </tbody>
 </table>

 @{
     var prevDisabled = !Model.Clients.HasPreviousPage ? "disabled" : "";
     var nextDisabled = !Model.Clients.HasNextPage ? "disabled" : "";
 }


     <a asp-page="./Index"
         asp-route-SortOrder="@Model.CurrentSort"
         asp-route-pageIndex="@(Model.Clients.PageIndex - 1)"
         asp-route-currentFilter="@Model.CurrentFilter"

         class="btn btn-default @prevDisabled">
         Previous
     </a>

     <a asp-page="./Index"
         asp-route-sortOrder="@Model.CurrentSort"
         asp-route-pageIndex="@(Model.Clients.PageIndex + 1)"
         asp-route-currentFilter="@Model.CurrentFilter"

         class="btn btn-default @nextDisabled">
         Next
     </a>

В конечном итоге мне нужно разбить на страницы нумерацию, чтобы сохранить условия поиска и порядок сортировки при перемещении по страницам результатов. Если это просто невозможно, то я хотел бы знать, как устранить нумерацию страниц и использовать какой-либо другой вид сбора для достижения результата сохранения возможности одновременного поиска по нескольким полям.

1 Ответ

0 голосов
/ 23 октября 2019

При создании ссылок на пейджинг вам необходимо передать все параметры строки запроса, чтобы сгенерировать URL новой страницы.

Это можно сделать путем жесткого кодирования всех значений строки запроса (включая поисковые фильтры) с помощью asp-route-...="xxx".

Другой способ - получить значение строки запроса текущей страницы (начиная с '?'), Заменить только номер страницы и сгенерировать новый URL:


<a href="@CreateUrl(Model.Clients.PageIndex - 1)">Previous</a>
<a href="@CreateUrl(Model.Clients.PageIndex + 1)">Next</a>

@{
    string CreateUrl(int index)
    {
        // Split the query string to individual parameters
        // e.g. [ "pageIndex=1", "searchString=blablabla", ...]
        var queryStringList = Request.QueryString.Value.Split('&').ToList();

        // Loop throw the parameters and increase the page index
        for (int i = 0; i < queryStringList.Count(); i++)
        {
            var qs = queryStringList[i];
            queryStringList[i] = qs.StartsWith("pageIndex=") ? $"pageIndex={index}" : qs;
        }

        // Reconstrcu the url
        return string.Join("&", queryStringList);
    }
}

Или вы можете просто использовать регулярное выражениечтобы заменить значение без разделения и воссоздания URL-адреса:

<a href="@CreateUrl(Model.Clients.PageIndex - 1)">Previous</a>
<a href="@CreateUrl(Model.Clients.PageIndex + 1)">Next</a>

@{
    string CreateUrl(int index)
    {
        var input = Request.QueryString.Value;
        var replacement = $"pageIndex={index}";
        var pattern = @"pageIndex=\d+";
        return System.Text.RegularExpressions.Regex.Replace(input, pattern, replacement);
    }
}

Или используйте вспомогательный тег для тега нумерации страниц, который может обрабатывать всю сложную логику разбиения на страницы, например LazZiya.TagHelpers , установить из nuget:

Install-Package LazZiya.TagHelpers -Version 3.0.2

Добавить помощник тега подкачки в _ViewImports:

@addTagHelper *, LazZiya.TagHelpers

Затем используйте его там, где вынужен контроль подкачки:

<paging 
    total-records="Model.TotalRecords" 
    page-no="Model.PageNo"
    query-string-key-page-no="pageIndex"
    query-string-value="@(Request.QueryString.Value)">
</paging>

См. учебное пособие , живое демо и документы

...