Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Pagination state is not updating in the UI when filtering returns less pages of results than the current page index using a FluentDataGrid with ItemsProvider in FluentPaginator #1596

Closed
NickHirras opened this issue Feb 27, 2024 · 4 comments · Fixed by #1606

Comments

@NickHirras
Copy link
Contributor

NickHirras commented Feb 27, 2024

🐛 Bug Report

I have a data table using pagination, and remote data retrieved through ItemsProvider.

If I page ahead (for example, to page 3 of the current results), and then I adjust a filter to return less than 3 pages of results, the paginator UI does not update correctly. I can see it results in two data retrievals. First one includes the new items count that is less than the currently selected page index, which in the FluentPaginator component triggers a re-retrieval for whatever the calculated last page of results would be.

My DataGrid is refreshing correctly, but my Paginator is still showing the wrong page number and page count. Until I press one of the pagination buttons, which seems to trigger the UI refresh and then it's correct.

I'm hoping I've just made some fundamental mistake in my code, and maybe you can point me towards the solution, if this is not in fact a bug.

💻 Repro or Code Sample

Here's a complete working sample page.

@page "/RemoteDataPaginationBug"

<h3>RemoteDataPaginationBug</h3>

<FluentDataGrid Loading="true" ItemsProvider="DisputeCasesProvider" TGridItem="string" Pagination="@_pagination" ResizableColumns="false" GridTemplateColumns="1fr">

    <TemplateColumn Title="Word">
      <ColumnOptions>
        <div class="search-box">
          <FluentTextField @bind-Value="RequestModel.WordFilter" Label="Word contains:"/>
        </div>
      </ColumnOptions>
      <ChildContent>
        @context
      </ChildContent>
    </TemplateColumn>
</FluentDataGrid>

<FluentPaginator State="@_pagination"/>


@code {

  public class MyRequestModel
  {
    public string WordFilter { get; set; } = String.Empty;
  }

  private MyRequestModel RequestModel { get; set; } = new();

  readonly List<string> _wordlist = [
    "a", "about", "all", "also", "and", "as", "at", "be", "because", "but", "by", "can", "come", "could", "day", "do",
    "even", "find", "first", "for", "from", "get", "give", "go", "have", "he", "her", "here", "him", "his", "how",
    "I", "if", "in", "into", "it", "its", "just", "know", "like", "look", "make", "man", "many", "me", "more", "my",
    "new", "no", "not", "now", "of", "on", "one", "only", "or", "other", "our", "out", "people", "say", "see", "she",
    "so", "some", "take", "tell", "than", "that", "the", "their", "them", "then", "there", "these", "they", "thing",
    "think", "this", "those", "time", "to", "two", "up", "use", "very", "want", "way", "we", "well", "what", "when",
    "which", "who", "will", "with", "would", "year", "you", "your"
  ];

  private readonly PaginationState _pagination = new() { ItemsPerPage = 7 };

  private async ValueTask<GridItemsProviderResult<string>> DisputeCasesProvider(
    GridItemsProviderRequest<string> req)
  {
    Console.WriteLine($"FETCH filter='{RequestModel.WordFilter}', currentPage={_pagination.CurrentPageIndex}, itemsPerPage={_pagination.ItemsPerPage}");

    var filteredList = _wordlist.ToList();
    filteredList = filteredList.Where(w => w.Contains(RequestModel.WordFilter, StringComparison.OrdinalIgnoreCase)).ToList();

    var itemsPerPage = _pagination.ItemsPerPage;
    var currentPageIndex = _pagination.CurrentPageIndex;

    int totalItemCount = filteredList.Count();

    var startIndex = currentPageIndex * itemsPerPage;
    if (startIndex > totalItemCount)
    {
      startIndex = 0;
    }

    var endIndex = startIndex + itemsPerPage;
    if (endIndex > totalItemCount)
    {
      endIndex = totalItemCount;
    }

    filteredList = filteredList[new Range(startIndex, endIndex)];

    Console.WriteLine($"   totalItemCount = {totalItemCount}\n=========================================");

    await Task.Delay(500);

    return GridItemsProviderResult.From(
      items: filteredList,
      totalItemCount: totalItemCount);  }

}

🤔 Expected Behavior

When filtering results in the paginator needing to jump back to a valid page, I expect the paginator UI to update showing the correct current page and page count.

😯 Current Behavior

You can reproduce by running the page, and following these steps.

  1. Open dev console so you can see the output messages about data retrieval, you can see the request filters and pagination values, and the returned item count.
  2. Use paginator to move ahead to page 4 of results.
  3. Click the filter control on the Word column, and type "ou" and press [TAB] or [ENTER]. This will trigger data retrieval using the filter.
  4. Notice that a single page of results is returned, and updated in the data grid. However the Paginator still shows you're on "Page 4 of 15" even though the results being displayed are page 1 of 1.
  5. Pressing the next page button on the paginator will take you to "Page 2 of 1" and show no results in the table.
  6. Pressing the prev button on the paginator now shows again the only page of results, paginator correctly shows "Page 1 of 1" with the prev/next buttons correctly disabled.

see screen recording:

Screen.Recording.2024-02-27.at.1.35.54.PM.mov

💁 Possible Solution

🔦 Context

🌍 Your Environment

  • OS & Device: MacOS arm64 on Macbook
  • Chrome latest MacOS arm64
  • .NET 8.0.101 arm64
  • Fluent UI Blazor library Version 4.x.x (latest release)
@vnbaaij
Copy link
Collaborator

vnbaaij commented Feb 28, 2024

You just need to change your _pagination variable to not be readonly
issue-#1596

@vnbaaij vnbaaij closed this as completed Feb 28, 2024
@NickHirras
Copy link
Contributor Author

NickHirras commented Feb 28, 2024

@vnbaaij I changed it to not be readonly, but still seeing the same behavior.

Here's test code with the readonly attribute removed.

@page "/RemoteDataPaginationBug"

<h3>RemoteDataPaginationBug</h3>

<FluentDataGrid Loading="true" ItemsProvider="DisputeCasesProvider" TGridItem="string" Pagination="@_pagination" ResizableColumns="false" GridTemplateColumns="1fr">
    <TemplateColumn Title="Word">
      <ColumnOptions>
        <div class="search-box">
          <FluentTextField @bind-Value="RequestModel.WordFilter" Label="Word contains:"/>
        </div>
      </ColumnOptions>
      <ChildContent>
        @context
      </ChildContent>
    </TemplateColumn>
</FluentDataGrid>

<FluentPaginator State="@_pagination"/>


@code {

  public class MyRequestModel
  {
    public string WordFilter { get; set; } = String.Empty;
  }

  private MyRequestModel RequestModel { get; set; } = new();

  List<string> _wordlist = [
    "a", "about", "all", "also", "and", "as", "at", "be", "because", "but", "by", "can", "come", "could", "day", "do",
    "even", "find", "first", "for", "from", "get", "give", "go", "have", "he", "her", "here", "him", "his", "how",
    "I", "if", "in", "into", "it", "its", "just", "know", "like", "look", "make", "man", "many", "me", "more", "my",
    "new", "no", "not", "now", "of", "on", "one", "only", "or", "other", "our", "out", "people", "say", "see", "she",
    "so", "some", "take", "tell", "than", "that", "the", "their", "them", "then", "there", "these", "they", "thing",
    "think", "this", "those", "time", "to", "two", "up", "use", "very", "want", "way", "we", "well", "what", "when",
    "which", "who", "will", "with", "would", "year", "you", "your"
  ];

  private PaginationState _pagination = new() { ItemsPerPage = 7 };

  private async ValueTask<GridItemsProviderResult<string>> DisputeCasesProvider(
    GridItemsProviderRequest<string> req)
  {
    Console.WriteLine($"FETCH filter='{RequestModel.WordFilter}', currentPage={_pagination.CurrentPageIndex}, itemsPerPage={_pagination.ItemsPerPage}");

    var filteredList = _wordlist.ToList();
    filteredList = filteredList.Where(w => w.Contains(RequestModel.WordFilter, StringComparison.OrdinalIgnoreCase)).ToList();

    var itemsPerPage = _pagination.ItemsPerPage;
    var currentPageIndex = _pagination.CurrentPageIndex;

    int totalItemCount = filteredList.Count();

    var startIndex = currentPageIndex * itemsPerPage;
    if (startIndex > totalItemCount)
    {
      startIndex = 0;
    }

    var endIndex = startIndex + itemsPerPage;
    if (endIndex > totalItemCount)
    {
      endIndex = totalItemCount;
    }

    filteredList = filteredList[new Range(startIndex, endIndex)];

    Console.WriteLine($"   totalItemCount = {totalItemCount}\n=========================================");

    await Task.Delay(500);

    return GridItemsProviderResult.From(
      items: filteredList,
      totalItemCount: totalItemCount);  }

}

@marciolordelo
Copy link

marciolordelo commented Feb 28, 2024

@vnbaaij I think your simulation is not correct. Before filtering by a column, you need to go to a page that will not exist after filtering (@NickHirras changed to the 4th page before filtering by the column, and the filtered data has only one page of results).

@vnbaaij
Copy link
Collaborator

vnbaaij commented Feb 28, 2024

I closed it too early but will be fixed with PR mentioned above and will be in next release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants