मेरे पास एक ब्लेज़र ऐप है जहां मेरे पास सूची में वस्तुओं की एक सूची है। मैंने एक पेजर घटक स्थापित किया (नीचे दिखाया गया है) और यह बहुत अच्छा काम करता है। फिर मैंने सूची से फ़ील्ड के एक सेट पर खोज बॉक्स कार्यक्षमता स्थापित की। अगर पेजर पहले पेज पर है तो यह सब बहुत अच्छा काम करता है। कोई अन्य पृष्ठ और खोजें अप्रत्याशित परिणाम दिखाती हैं। कभी-कभी उस पृष्ठ पर आइटम के लिए सही ढंग से फ़िल्टर भी नहीं किया जाता है। कोई भी सलाह सहायक होगी। धन्यवाद।

पेजर.रेजर

@typeparam TItem

<div class="row d-flex col-9">
<div class="justify-content-center">
    @if (PageCount > 1 && List.Count > PageSize)
    {
        <ul class="pagination justify-content-center">
            <li><button @onclick="@(() => ChangePage(1))" class="btn">&laquo;</button></li>

                @for (var i = StartIndex; i <= FinishIndex; i++)
                {
                    var currentIndex = i;
                    @if (i == CurrentPage)
                    {
                        <li class="page-item active"><span class="btn">@i</span></li>
                    }
                    else
                    {
                        <li class="page-item"><button class="btn page-link" @onclick="@(() => ChangePage(currentIndex))">@i</button></li>
                    }
                }

            <li><button @onclick="@(() => ChangePage(PageCount))" class="btn">&raquo;</button></li>
        </ul>
    }   
</div>
<select class="custom-select offset-1 col-1 ml-auto" bind="@PageSize" @onchange="@(e => ChangePageSize(e))">
    <option value="10">10</option>
    <option value="25">25</option>
    <option value="50">50</option>
</select>
</div>

@code {
    [Parameter]
    public List<TItem> List { get; set; }

    public List<TItem> Display { get; set; }

    [Parameter]
    public Action<List<TItem>> DisplayChanged { get; set; }

    [Parameter]
    public Action<bool> Rendered { get; set; }

    private int PageSize { get; set; } = 10;
    private int CurrentPage { get; set; } = 1;
    private int StartIndex { get; set; }
    private int FinishIndex { get; set; }
    private int PageCount { get; set; }

    protected override void OnAfterRender(bool firstRender)
    {
        base.OnAfterRender(firstRender);
        Rendered?.Invoke(true);
    }

    private void ChangePageSize(ChangeEventArgs e)
    {
        PageSize = int.Parse(e.Value.ToString());
        ChangePage(1);
    }

    private void ChangeDisplay()
    {
        DisplayChanged?.Invoke(
            List
                .Skip((CurrentPage - 1) * PageSize)
                .Take(PageSize)
                .ToList()
        );
    }

    protected override void OnParametersSet()
    {
        ResetIndex();

        ChangeDisplay();
        base.OnParametersSet();
    }

    protected void ChangePage(int page)
    {
        CurrentPage = page;
        ResetIndex();
        ChangeDisplay();
    }

    private void ResetIndex()
    {
        PageCount = List.Count / PageSize;

        if (List.Count % PageSize > 0)
        {
            PageCount++;
        }

        StartIndex = Math.Max(CurrentPage - 5, 1);
        FinishIndex = Math.Min(CurrentPage + 5, PageCount);
    }
}

पेजर उपयोग <Pager List="@FilteredUsers" DisplayChanged="@DisplayChanged" Rendered="@PagerRendered" />

खोज फ़ंक्शन

<input class="form-control" type="text" @bind-value="@SearchTerm" @bind-value:event="oninput" />
<select class="form-control" @bind-value="@Property" @bind-value:event="onchange">
    <option value="FirstName">First Name</option>
    <option value="LastName">Last Name</option>
    <option value="Role">Role</option>
    <option value="Property">Property</option>
</select>

private string searchTerm;

private string SearchTerm
{
    get => searchTerm;
    set
    {
        searchTerm = value;
        Filter();
    }
}

फ़िल्टर करें

private void Filter()
{
    switch (Property)
    {
        case "FirstName":
            FilteredUsers = Users.Where(u => u.FirstName.ToLower().Contains(SearchTerm.ToLower())).ToList();
            break;
        case "LastName":
            FilteredUsers = Users.Where(u => u.LastName.ToLower().Contains(SearchTerm.ToLower())).ToList();
            break;
        case "Role":
            FilteredUsers = Users.Where(u => u.Role.ToString().ToLower().Contains(SearchTerm.ToLower())).ToList();
            break;
        case "Property":
            if (string.IsNullOrEmpty(SearchTerm))
            {
                FilteredUsers = Users;
            }
            else
            {
                FilteredUsers = Users.Where(u => TicketingRosters.Any(t => t.Property.PropertyName.ToLower().Contains(SearchTerm.ToLower()) && u.UserId == t.SellerId)).ToList();
            }
            break;
    }
    StateHasChanged();
}

संपादित करें

यहां अन्य कार्य और गुण हैं जिनकी आप तलाश कर रहे हैं:

private List<UserDto> Users { get; set; }
private List<UserDto> FilteredUsers { get; set; }
private List<UserDto> Display { get; set; }

private bool IsPagerRendered { get; set; }
private void DisplayChanged(List<UserDto> display)
{
    Display = display;
}

private void PagerRendered(bool rendered)
{
    IsPagerRendered = rendered;
    StateHasChanged();
}

2 संपादित करें private List<TicketingRoster> TicketingRosters { get; set; } = new List<TicketingRoster>();

UserDto

#nullable enable
using System;
using System.ComponentModel.DataAnnotations;

namespace TicketingSolutions.Models.DTOs
{
    public class UserDto
    {
        public long UserId { get; set; }
        [Required(AllowEmptyStrings = false, ErrorMessage = "First name cannot be empty.")]
        [StringLength(75, ErrorMessage = "First Name too long.  (75 characters)")]
        public string? FirstName { get; set; }
        [Required(AllowEmptyStrings = false, ErrorMessage = "Last Name cannot be empty.")]
        [StringLength(75, ErrorMessage = "Last Name too long. (75 characters)")]
        public string? LastName { get; set; }
        [StringLength(75, ErrorMessage = "Middle Name too long. (75 characters)")]
        public string? MiddleName { get; set; }
        [StringLength(150, ErrorMessage = "Title too long. (150 characters)")]
        public string? Title { get; set; }
        [DataType(DataType.EmailAddress)]
        [StringLength(150, ErrorMessage = "Email Address too long. (150 characters)")]
        public string? EmailAddress { get; set; }
        [RegularExpression(@"((\(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4}", ErrorMessage = "Not a valid phone number format: (xxx) xxx-xxxx")]
        [StringLength(50, ErrorMessage = "Phone Number too long. (50 characters)")]
        public string? OfficePhone { get; set; }
        [RegularExpression(@"((\(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4}", ErrorMessage = "Not a valid phone number format: (xxx) xxx-xxxx")]
        [StringLength(50, ErrorMessage = "Phone Number too long. (50 characters)")]
        public string? OtherPhone { get; set; }
        public Guid? AdUserId { get; set; }
        public bool IsActive { get; set; }
        public int? RegionId { get; set; }
        public Region? Region { get; set; }
        public DateTime CreatedOn { get; set; }
        public long CreatedBy { get; set; }
        public DateTime ModifiedOn { get; set; }
        public long ModifiedBy { get; set; }

        public Roles Role { get; set; }

        public int? RoleId { get; set; }
        public CommissionRole? CommissionRole { get; set; }
    }
}

टिकटिंग रोस्टर

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;

namespace TicketingSolutions.Models
{
    [Table("TicketingRosters")]
    public class TicketingRoster : IValidatableObject
    {
        [Key]
        public long TicketingRosterId { get; set; }
        public int PropertyId { get; set; }
        public Property Property { get; set; }
        public long SellerId { get; set; }
        public User Seller { get; set; }
        public bool IsActive { get; set; }
        public DateTime ValidFrom { get; set; }
        public DateTime? ValidTo { get; set; }
        public DateTime CreatedOn { get; set; }
        public long CreatedBy { get; set; }
        public DateTime ModifiedOn { get; set; }
        public long ModifiedBy { get; set; }

        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
            if (ValidTo <= ValidFrom)
            {
                yield return new ValidationResult("ValidTo cannot be set to a date before or equal to ValidFrom", new[] { nameof(ValidTo) });
            }
        }
    }
}
2
Aaron Rumford 29 अप्रैल 2020, 19:03

1 उत्तर

सबसे बढ़िया उत्तर

इसका पालन करना थोड़ा कठिन है क्योंकि कुछ बाहरी तरीके हैं जो आपने इस उदाहरण में नहीं दिखाए हैं (स्पष्टता के लिए संपादित करें?) आपका पेजिंग कैसे काम करता है। सस्ता DisplayChanged इवेंट कॉलबैक है। मैं सुझाव दे सकता हूं कि आप चिंताओं को तोड़कर इससे निपटें, और आप सब कुछ काम कर सकते हैं। (मैं आपके पास जो कुछ भी है उससे काम करते हुए इसे काफी तेज़ी से चलाने में सक्षम था)

सबसे पहले, आइए पेजर को सेट अप करें ताकि यह केवल जानकारी पेजिंग को संभाल सके, और इसमें स्वयं निहित, पुन: प्रयोज्य घटक में ऐसा करने के लिए अपने स्वयं के तर्क शामिल हैं। इसे TItem और एक RenderFragment<TItem> की सूची दें और यह जानता है कि क्या करना है।

@typeparam TItem

<div class="row d-flex col-9">
    <div class="justify-content-center">

        @if (List != null)
        {
            @foreach (var item in DisplayList)
            {
                @ChildContent(item)
            }
        }

        @if (PageCount > 1 && List.Count > PageSize)
        {

            ...Nothing here was changed, eliminated for brevity...


        }
    </div>
    <select class="custom-select offset-1 col-1 ml-auto" bind="@PageSize" @onchange="@(e => ChangePageSize(e))">
        <option value="10">10</option>
        <option value="25">25</option>
        <option value="50">50</option>
    </select>
</div>

@code {
    [Parameter]
    public List<TItem> List { get; set; }

    public List<TItem> DisplayList { get; set; } = new List<TItem>();

    [Parameter]
    public RenderFragment<TItem> ChildContent { get; set; }

    //[Parameter]
    //public Action<List<TItem>> DisplayChanged { get; set; }

    //[Parameter]
    //public Action<bool> Rendered { get; set; }

    private int PageSize { get; set; } = 10;
    private int CurrentPage { get; set; } = 1;
    private int StartIndex { get; set; }
    private int FinishIndex { get; set; }
    private int PageCount { get; set; }

    //protected override void OnAfterRender(bool firstRender)
    //{
    //  base.OnAfterRender(firstRender);
    //  Rendered?.Invoke(true);
    //}

    private void ChangePageSize(ChangeEventArgs e)
    {
        PageSize = int.Parse(e.Value.ToString());
        ChangePage(1);
    }

    private void ChangeDisplay()
    {
        DisplayList = List
                .Skip((CurrentPage -1) * PageSize)
                .Take(PageSize)
                .ToList();
    }

    protected override void OnParametersSet()
    {
        // Edited
        ChangePage(1);
    }

    protected void ChangePage(int page)
    {
        CurrentPage = page;
        ResetIndex();
        ChangeDisplay();
    }

    private void ResetIndex()
    {
        PageCount = List.Count / PageSize;

        if (List.Count % PageSize > 0)
        {
            PageCount++;
        }

        StartIndex = Math.Max(CurrentPage - 5, 1);
        FinishIndex = Math.Min(CurrentPage + 5, PageCount);
    }
}

आप देखेंगे कि @code ब्लॉक में कुछ चीजों पर टिप्पणी की गई है। इसे काम करने के लिए आपको इनकी आवश्यकता नहीं होगी। हम पेरेंट कंपोनेंट में एक मिनट में शुरुआती सूची के मानों को हैंडल करेंगे। आपको एक RenderFragment<TItem> पैरामीटर और DisplayList के लिए एक नई प्रॉपर्टी दिखाई देगी, जो एक पैरामीटर नहीं है। आप मार्कअप में यह भी देखेंगे कि हमारे पास @foreach ब्लॉक है जो DisplayList प्रॉपर्टी में प्रत्येक आइटम के लिए हमारे RenderFragment का एक उदाहरण प्रस्तुत करता है। यदि आप पृष्ठ संख्याओं और तीरों पर क्लिक करने के लिए OnParametersSet विधि और अपने हैंडलर के तर्क का पालन करते हैं, तो आप देखेंगे कि हम पृष्ठ संख्या के आधार पर हमारे List पैरामीटर की एक उप-सूची बना रहे हैं और प्रस्तुत कर रहे हैं और पृष्ठ संख्या, और वह सब जो प्रस्तुत किया गया है। यह घटक अब दी गई सूची से आइटम को पेजिंग करने के लिए ज़िम्मेदार है, और इसमें प्रस्तुत करने के लिए सूची के अलावा अन्य कोई बाहरी निर्भरता नहीं है, और प्रत्येक आइटम को RenderFragment<TItem> के रूप में कैसे प्रस्तुत किया जाए, इस पर निर्देश हैं।

इसके बाद, अभिभावक घटक में, हम पेजर पर कॉल को इस प्रकार सेट करते हैं:

<Pager TItem="User" List="FilteredUsers">
    <h6>@context.FirstName @context.LastName is in @context.Role </h6>
</Pager>

आप जैसे चाहें इसे सेट कर सकते हैं, मैंने उदाहरण के लिए <h6> टैग का उपयोग किया है, लेकिन निर्देशों का पालन करें यहां अगर आपको अधिक गहराई की जरूरत है, तो टेबल, सूचियां, आदि बनाना। यह घटक अब <Pager> के बीच चाइल्ड कंटेंट को स्वीकार करता है। टैग और प्रत्येक आइटम के लिए 1 प्रत्येक को अपनी पृष्ठांकित सूची में प्रस्तुत करता है।

अब तक, हमने पेजर के तर्क को शेष पृष्ठ से अलग कर दिया है, इसलिए अब यह केवल एक प्रतिपादन उपकरण है और पेजिंग तर्क आंतरिक है। अब हम फ़िल्टरिंग पर ध्यान केंद्रित कर सकते हैं और पेजिंग के बारे में भूल सकते हैं।

खोज फ़िल्टरिंग: सबसे पहले, मैंने "संपत्ति" खोज के लिए प्रारंभिक मान निर्धारित किया है और बैकिंग फ़ील्ड को इस तरह सेट किया है:

private string property = "FirstName";

private string Property
{
    get => property;
    set
    {
        property = value;
        Filter();
    }
}

यह अब ड्रॉप डाउन प्रारंभिक मान के साथ संरेखित हो जाता है, क्योंकि <select> ने इसे केवल परिवर्तन पर अपडेट किया है, और जब आप ड्रॉपडाउन बदलते हैं तो खोज परिणामों को भी अपडेट करता है।

मैंने आपकी SearchTerm संपत्ति को वैसे ही छोड़ दिया जैसे आपके पास थी।

अब फ़िल्टर विधि में:

private void Filter()
{
    if (string.IsNullOrEmpty(SearchTerm))
    {
        FilteredUsers = Users;
    }
    else
    {
        switch (Property)
        {
            case "FirstName":
                FilteredUsers = Users.Where(u => u.FirstName.ToLower().Contains(SearchTerm.ToLower())).ToList();
                break;
            case "LastName":
                FilteredUsers = Users.Where(u => u.LastName.ToLower().Contains(SearchTerm.ToLower())).ToList();
                break;
            case "Role":
                FilteredUsers = Users.Where(u => u.Role.ToString().ToLower().Contains(SearchTerm.ToLower())).ToList();
                break;
            case "Property":
                FilteredUsers = Users.Where(u => u.Role.ToString().ToLower().Contains(SearchTerm.ToLower())).ToList();
                //FilteredUsers = Users.Where(u => TicketingRosters.Any(t => t.Property.PropertyName.ToLower().Contains(SearchTerm.ToLower()) && u.UserId == t.SellerId)).ToList();
                break;
            default:
                FilteredUsers = Users;
                break;
        }
    }
    StateHasChanged();
}

यह अब पहले खोज मान की जांच करता है, और अगर यह खाली है तो पूरी Users सूची लौटाता है। यदि नहीं, तो आप स्विच दर्ज करें। सभी मामले वैसे ही काम करते हैं जैसे मेरे पास हैं, हालाँकि आप देखेंगे कि मैंने Where तर्क पर टिप्पणी की थी जो आपके पास मूल रूप से था। ईमानदारी से, टिकटिंगरोस्टर्स मुझसे परिचित नहीं हैं और मैं बता सकता हूं कि आपका तर्क एक ऐसे डोमेन में है जिसके बारे में मुझे कुछ नहीं पता है, इसलिए आपको उस अंतिम मामले के बारे में स्वयं तर्क करना होगा। लेकिन, अगर बाकी सब कुछ काम करता है, तो अब आपके पास अपनी बग को खोजने के लिए एक केंद्रित दृष्टिकोण है।

तो अब फ़िल्टर विधि एक फ़िल्टर की गई सूची सेट करती है, पेजर उस पूरी सूची को लेता है और पेजिंग को अपने आप संभालता है, और आपके पास अच्छी तरह से अलग-अलग चिंताएं हैं, इसलिए यदि आपको कोई समस्या है तो आप जानते हैं कि कहां देखना है। सही ढंग से पेजिंग नहीं करना -> यह पेजर में है। सही ढंग से फ़िल्टर नहीं करना -> यह फ़िल्टर तर्क में है।

संपादित करें

ओपी द्वारा TicketingRoster और UserDto वर्ग परिभाषाओं को जोड़ने के बाद, मैंने यह सोचने की गलती की कि मुझे क्वेरी में समस्या मिली है। हालाँकि, कुछ आगे और पीछे ओपी ने स्पष्ट किया कि Pager जो मैंने ऊपर उल्लिखित किया था वह अभी भी बिल्कुल सही काम नहीं कर रहा था और प्रश्न थे, और एक और नज़र के बाद मैंने OnParametersSet को कॉल करने की विधि को साफ़ कर दिया ChnagePage(1), जो दोनों वर्तमान पृष्ठ को 1 पर रीसेट कर देगा और पृष्ठ संख्या को रीसेट कर देगा। मेरी ओर से एक परीक्षण ने पुष्टि की कि मेरी मूल प्रतिक्रिया के साथ ओपी का मुद्दा साफ हो गया था।

मेरे पहले संपादन में क्वेरी संरचना और सिद्धांत के बारे में काफी कुछ था, और मैंने उस अनुभाग को हटा दिया क्योंकि a) यह अब इस चर्चा के लिए प्रासंगिक नहीं है, और b) पीछे मुड़कर देखने पर, यह कृपालु के रूप में सामने आ सकता है, हालांकि यह कभी भी मेरा नहीं था किसी भी बिंदु पर इरादा।

2
Nik P 30 अप्रैल 2020, 20:26
विस्तृत उत्तर के लिए धन्यवाद। यदि आप मुझे बताएं कि आप क्या देखना चाहते हैं, तो मैं प्रश्न संपादित कर सकता हूं। सुनिश्चित नहीं है कि आप किस पहलू पर अस्पष्ट हैं।
 – 
Aaron Rumford
29 अप्रैल 2020, 23:05
विशेष रूप से अगर मैं देख सकता था कि TicketingRosters कहाँ रहता है, और यह मानते हुए कि यह एक संग्रह है, प्रकार की परिभाषा (वर्ग, संरचना, आदिम) जो संग्रह में भी है। उन गुणों को देखकर जिनके खिलाफ आप पूछताछ कर रहे हैं और फ़िल्टर विधि में आखिरी मामला कैसे इंटरैक्ट करता है, इस पर कुछ और प्रकाश डालेगा। मैं यह भी मानता हूं कि मूल घटक में एक DisplayChanged विधि थी जिसे आपने रेखांकित नहीं किया था, हालांकि मुझे नहीं पता कि इसकी आवश्यकता है या नहीं।
 – 
Nik P
29 अप्रैल 2020, 23:42
संपादन किए गए। मदद के लिए धन्यवाद, वैसे। :)
 – 
Aaron Rumford
30 अप्रैल 2020, 02:27
मेरी पोस्ट के नीचे एक संपादन जोड़ा गया, एक नज़र डालें और मुझे बताएं कि क्या यह चीजों को स्पष्ट करता है।
 – 
Nik P
30 अप्रैल 2020, 19:11
तो शायद मैं चीजों को थोड़ा स्पष्ट कर सकूं। 4 'फ़ील्ड' हैं जिन्हें मैं खोजना चाहता हूं। पहले तीन (प्रथम नाम, अंतिम नाम और भूमिका) सभी UserDto ऑब्जेक्ट्स पर उपलब्ध हैं। आखिरी संपत्ति का नाम है जो टिकटिंगरोस्टर से जुड़ा हुआ है जो एक मिश्रित तालिका है जो उपयोगकर्ताओं और गुणों को जोड़ती है। फिर से, ये चारों खोजें सफलतापूर्वक और अपेक्षित रूप से काम कर रही हैं यदि पेजर पहले पृष्ठ पर है। पेजर का कोई अन्य पेज और यह ठीक से काम नहीं करता है। अप्रत्याशित परिणाम।
 – 
Aaron Rumford
30 अप्रैल 2020, 19:51