Blazor generic type cascading feature (#21846)
parent
7da013e169
commit
2b6eba0ec7
|
@ -94,10 +94,86 @@ When using generic-typed components, the type parameter is inferred if possible.
|
|||
|
||||
::: moniker-end
|
||||
|
||||
## Generic type constraints
|
||||
## Infer generic types based on ancestor components
|
||||
|
||||
::: moniker range=">= aspnetcore-6.0"
|
||||
|
||||
An ancestor component can cascade a type parameter by name to descendants using the `CascadingTypeParameter` attribute. This attribute allows a generic type inference to use the specified type parameter automatically with descendants that have a type parameter with the same name.
|
||||
|
||||
For example, the following `Chart` component receives stock price data and cascades a generic type parameter named `TLineData` to its descendent components.
|
||||
|
||||
`Shared/Chart.razor`:
|
||||
|
||||
```razor
|
||||
@typeparam TLineData
|
||||
@attribute [CascadingTypeParameter(nameof(TLineData))]
|
||||
|
||||
...
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public IEnumerable<TLineData> Data { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
`Shared/Line.razor`:
|
||||
|
||||
```razor
|
||||
@typeparam TLineData
|
||||
|
||||
...
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public string Title { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public decimal Value { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public IEnumerable<TLineData> Data { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
When the `Chart` component is used, `TLineData` isn't specified for each `Line` component of the chart.
|
||||
|
||||
`Pages/StockPriceHistory.razor`:
|
||||
|
||||
```razor
|
||||
@page "/stock-price-history"
|
||||
|
||||
<Chart Data="stockPriceHistory.GroupBy(x => x.Date)">
|
||||
<Line Title="Open" Value="day => day.Values.First()" />
|
||||
<Line Title="High" Value="day => day.Values.Max()" />
|
||||
<Line Title="Low" Value="day => day.Values.Min()" />
|
||||
<Line Title="Close" Value="day => day.Values.Last()" />
|
||||
</Chart>
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> Generic type constraints will be supported in a future release. For more information, see [Allow generic type constraints (dotnet/aspnetcore #8433)](https://github.com/dotnet/aspnetcore/issues/8433).
|
||||
> The Razor support in Visual Studio Code hasn't been updated to support this feature, so you may receive incorrect errors even though the project correctly builds. This will be addressed in an upcoming tooling release.
|
||||
|
||||
By adding `@attribute [CascadingTypeParameter(...)]` to a component, the specified generic type argument is automatically used by descendants that:
|
||||
|
||||
* Are nested as child content for the component in the same `.razor` document.
|
||||
* Also declare a [`@typeparam`](xref:mvc/views/razor#typeparam) with the exact same name.
|
||||
* Don't have another value supplied or inferred for the type parameter. If another value is supplied or inferred, it takes precedence over the cascaded generic type.
|
||||
|
||||
When receiving a cascaded type parameter, components obtain the parameter value from the closest ancestor that has a `CascadingTypeParameter` with a matching name. Cascaded generic type parameters are overridden within a particular subtree.
|
||||
|
||||
Matching is only performed by name. Therefore, we recommend avoiding a cascaded generic type parameter with a generic name, for example `T` or `TItem`. If a developer opts into cascading a type parameter, they're implicitly promising that its name is unique enough not to clash with other cascaded type parameters from unrelated components.
|
||||
|
||||
::: moniker-end
|
||||
|
||||
::: moniker range="< aspnetcore-6.0"
|
||||
|
||||
> [!NOTE]
|
||||
> Inferred generic types are supported in ASP.NET Core 6.0 or later. For more information, see a version of this article later than ASP.NET Core 5.0.
|
||||
|
||||
::: moniker-end
|
||||
|
||||
## Additional resources
|
||||
|
||||
|
|
Loading…
Reference in New Issue