dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.37k stars 9.99k forks source link

QuickGrid collection from OnParametersSet not working with static SSR #55915

Closed guardrex closed 4 months ago

guardrex commented 4 months ago

Is there an existing issue for this?

Describe the bug

I don't think that this is the same as Add support to the QuickGrid paginator for static server rendering (dotnet/aspnetcore #51249), but it might have the same cause.

When scaffolding into a BWA that only adopts static SSR, the following code works ✔️ ...

@inject BlazorWebAppMovies.Data.BlazorWebAppMoviesContext DB

...

<QuickGrid Class="table" Items="DB.Movie">

... and the following works, too ✔️ (ignore NRT static analysis, as this is for only for discussion here, and assume a QS is provided e.g., ?movieSearch=XXX) ...

@inject BlazorWebAppMovies.Data.BlazorWebAppMoviesContext DB

...

<QuickGrid Class="table" Items="DB.Movie.Where(s => s.Title!.Contains(TitleSearch))">

...

[SupplyParameterFromQuery]
public string TitleSearch{ get; set; }

... but the following no-ops ❌. The QG doesn't display data, but the collection (movies) does receive the correct DbSet from the dB in OnParametersSet. Why? ... and what's the correct approach that I can use with the new Blazor tutorial (static SSR) for this search/filter scenario?

This ...

<QuickGrid Class="table" Items="@(!string.IsNullOrEmpty(TitleSearch) ? DB.Movie.Where(s => s.Title!.Contains(TitleSearch)) : DB.Movie)">

... is a working approach ✔️ ... or to deal with the nullable Title ...

<QuickGrid Class="table" Items="@(!string.IsNullOrEmpty(TitleSearch) ? DB.Movie.Where(s => !string.IsNullOrEmpty(s.Title) ? s.Title.Contains(TitleSearch) : false) : DB.Movie)">

... but the ❓ stands on the no-op code below.

I'll place the full component code here for inspection ...

@page "/movies"
@using Microsoft.AspNetCore.Components.QuickGrid
@inject BlazorWebAppMovies.Data.BlazorWebAppMoviesContext DB
@using BlazorWebAppMovies.Models
@using Microsoft.EntityFrameworkCore

<PageTitle>Index</PageTitle>

<h1>Index</h1>

<p>
    <a href="movies/create">Create New</a>
</p>

<QuickGrid Class="table" Items="movies">
    <PropertyColumn Property="movie => movie.Title" />
    <PropertyColumn Property="movie => movie.ReleaseDate" Title="Release Date" />
    <PropertyColumn Property="movie => movie.Genre" />
    <PropertyColumn Property="movie => movie.Price" />

    <TemplateColumn Context="movie">
        <a href="@($"movies/edit?id={movie.Id}")">Edit</a> |
        <a href="@($"movies/details?id={movie.Id}")">Details</a> |
        <a href="@($"movies/delete?id={movie.Id}")">Delete</a>
    </TemplateColumn>
</QuickGrid>

@code {
    private DbSet<Movie>? movies;

    [SupplyParameterFromQuery]
    public string? TitleSearch { get; set; }

    protected override void OnParametersSet()
    {
        var movies = from m in DB.Movie
                     select m;

        if (!string.IsNullOrEmpty(TitleSearch))
        {
            movies = movies.Where(s => !string.IsNullOrEmpty(s.Title) ? s.Title.Contains(TitleSearch) : false);
        }
    }
}

It doesn't work with movies as an IQueryable either ❌ ...

private IQueryable<Movie>? movies;

Expected Behavior

The movies collection is valid for the Items param, and the movies are rendered by the QG.

Steps To Reproduce

:point_up: Shown above.

Exceptions (if any)

None ... the QG merely displays no items.

.NET Version

8.0

Anything else?

No response

guardrex commented 4 months ago

Nevermind! The rubber 🦆 resolved this. Working code turned out to be ...

@code {
    private IQueryable<Movie>? movies;

    [SupplyParameterFromQuery]
    public string? TitleSearch { get; set; }

    protected override void OnParametersSet()
    {
        if (!string.IsNullOrEmpty(TitleSearch))
        {
            movies = DB.Movie.Where(s => !string.IsNullOrEmpty(s.Title) ? s.Title.Contains(TitleSearch) : false);
        }
        else
        {
            movies = DB.Movie;
        }
    }
}

... and we'll modify further on review of the PR later.