Component overview updates (#29283)

pull/29284/head
Luke Latham 2023-05-16 08:33:37 -04:00 committed by GitHub
parent 46441ae690
commit f705bcb4c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 198 additions and 183 deletions

View File

@ -971,188 +971,6 @@ You can factor out child components purely as a way of reusing rendering logic.
For more information, see [Reuse rendering logic](xref:blazor/performance#define-reusable-renderfragments-in-code).
## Attribute splatting and arbitrary parameters
Components can capture and render additional attributes in addition to the component's declared parameters. Additional attributes can be captured in a dictionary and then *splatted* onto an element when the component is rendered using the [`@attributes`][3] Razor directive attribute. This scenario is useful for defining a component that produces a markup element that supports a variety of customizations. For example, it can be tedious to define attributes separately for an `<input>` that supports many parameters.
In the following `Splat` component:
* The first `<input>` element (`id="useIndividualParams"`) uses individual component parameters.
* The second `<input>` element (`id="useAttributesDict"`) uses attribute splatting.
`Pages/Splat.razor`:
:::moniker range=">= aspnetcore-7.0"
:::code language="razor" source="~/../blazor-samples/7.0/BlazorSample_WebAssembly/Pages/index/Splat.razor":::
:::moniker-end
:::moniker range=">= aspnetcore-6.0 < aspnetcore-7.0"
:::code language="razor" source="~/../blazor-samples/6.0/BlazorSample_WebAssembly/Pages/index/Splat.razor":::
:::moniker-end
:::moniker range=">= aspnetcore-5.0 < aspnetcore-6.0"
:::code language="razor" source="~/../blazor-samples/5.0/BlazorSample_WebAssembly/Pages/index/Splat.razor":::
:::moniker-end
:::moniker range="< aspnetcore-5.0"
:::code language="razor" source="~/../blazor-samples/3.1/BlazorSample_WebAssembly/Pages/index/Splat.razor":::
:::moniker-end
The rendered `<input>` elements in the webpage are identical:
```html
<input id="useIndividualParams"
maxlength="10"
placeholder="Input placeholder text"
required="required"
size="50">
<input id="useAttributesDict"
maxlength="10"
placeholder="Input placeholder text"
required="required"
size="50">
```
To accept arbitrary attributes, define a [component parameter](#component-parameters) with the <xref:Microsoft.AspNetCore.Components.ParameterAttribute.CaptureUnmatchedValues> property set to `true`:
```razor
@code {
[Parameter(CaptureUnmatchedValues = true)]
public Dictionary<string, object>? InputAttributes { get; set; }
}
```
The <xref:Microsoft.AspNetCore.Components.ParameterAttribute.CaptureUnmatchedValues> property on [`[Parameter]`](xref:Microsoft.AspNetCore.Components.ParameterAttribute) allows the parameter to match all attributes that don't match any other parameter. A component can only define a single parameter with <xref:Microsoft.AspNetCore.Components.ParameterAttribute.CaptureUnmatchedValues>. The property type used with <xref:Microsoft.AspNetCore.Components.ParameterAttribute.CaptureUnmatchedValues> must be assignable from [`Dictionary<string, object>`](xref:System.Collections.Generic.Dictionary%602) with string keys. Use of [`IEnumerable<KeyValuePair<string, object>>`](xref:System.Collections.Generic.IEnumerable%601) or [`IReadOnlyDictionary<string, object>`](xref:System.Collections.Generic.IReadOnlyDictionary%602) are also options in this scenario.
The position of [`@attributes`][3] relative to the position of element attributes is important. When [`@attributes`][3] are splatted on the element, the attributes are processed from right to left (last to first). Consider the following example of a parent component that consumes a child component:
`Shared/AttributeOrderChild1.razor`:
:::moniker range=">= aspnetcore-7.0"
:::code language="razor" source="~/../blazor-samples/7.0/BlazorSample_WebAssembly/Shared/index/AttributeOrderChild1.razor":::
:::moniker-end
:::moniker range=">= aspnetcore-6.0 < aspnetcore-7.0"
:::code language="razor" source="~/../blazor-samples/6.0/BlazorSample_WebAssembly/Shared/index/AttributeOrderChild1.razor":::
:::moniker-end
:::moniker range=">= aspnetcore-5.0 < aspnetcore-6.0"
:::code language="razor" source="~/../blazor-samples/5.0/BlazorSample_WebAssembly/Shared/index/AttributeOrderChild1.razor":::
:::moniker-end
:::moniker range="< aspnetcore-5.0"
:::code language="razor" source="~/../blazor-samples/3.1/BlazorSample_WebAssembly/Shared/index/AttributeOrderChild1.razor":::
:::moniker-end
`Pages/AttributeOrderParent1.razor`:
:::moniker range=">= aspnetcore-7.0"
:::code language="razor" source="~/../blazor-samples/7.0/BlazorSample_WebAssembly/Pages/index/AttributeOrderParent1.razor":::
:::moniker-end
:::moniker range=">= aspnetcore-6.0 < aspnetcore-7.0"
:::code language="razor" source="~/../blazor-samples/6.0/BlazorSample_WebAssembly/Pages/index/AttributeOrderParent1.razor":::
:::moniker-end
:::moniker range=">= aspnetcore-5.0 < aspnetcore-6.0"
:::code language="razor" source="~/../blazor-samples/5.0/BlazorSample_WebAssembly/Pages/index/AttributeOrderParent1.razor":::
:::moniker-end
:::moniker range="< aspnetcore-5.0"
:::code language="razor" source="~/../blazor-samples/3.1/BlazorSample_WebAssembly/Pages/index/AttributeOrderParent1.razor":::
:::moniker-end
The `AttributeOrderChild1` component's `extra` attribute is set to the right of [`@attributes`][3]. The `AttributeOrderParent1` component's rendered `<div>` contains `extra="5"` when passed through the additional attribute because the attributes are processed right to left (last to first):
```html
<div extra="5" />
```
In the following example, the order of `extra` and [`@attributes`][3] is reversed in the child component's `<div>`:
`Shared/AttributeOrderChild2.razor`:
:::moniker range=">= aspnetcore-7.0"
:::code language="razor" source="~/../blazor-samples/7.0/BlazorSample_WebAssembly/Shared/index/AttributeOrderChild2.razor":::
:::moniker-end
:::moniker range=">= aspnetcore-6.0 < aspnetcore-7.0"
:::code language="razor" source="~/../blazor-samples/6.0/BlazorSample_WebAssembly/Shared/index/AttributeOrderChild2.razor":::
:::moniker-end
:::moniker range=">= aspnetcore-5.0 < aspnetcore-6.0"
:::code language="razor" source="~/../blazor-samples/5.0/BlazorSample_WebAssembly/Shared/index/AttributeOrderChild2.razor":::
:::moniker-end
:::moniker range="< aspnetcore-5.0"
:::code language="razor" source="~/../blazor-samples/3.1/BlazorSample_WebAssembly/Shared/index/AttributeOrderChild2.razor":::
:::moniker-end
`Pages/AttributeOrderParent2.razor`:
:::moniker range=">= aspnetcore-7.0"
:::code language="razor" source="~/../blazor-samples/7.0/BlazorSample_WebAssembly/Pages/index/AttributeOrderParent2.razor":::
:::moniker-end
:::moniker range=">= aspnetcore-6.0 < aspnetcore-7.0"
:::code language="razor" source="~/../blazor-samples/6.0/BlazorSample_WebAssembly/Pages/index/AttributeOrderParent2.razor":::
:::moniker-end
:::moniker range=">= aspnetcore-5.0 < aspnetcore-6.0"
:::code language="razor" source="~/../blazor-samples/5.0/BlazorSample_WebAssembly/Pages/index/AttributeOrderParent2.razor":::
:::moniker-end
:::moniker range="< aspnetcore-5.0"
:::code language="razor" source="~/../blazor-samples/3.1/BlazorSample_WebAssembly/Pages/index/AttributeOrderParent2.razor":::
:::moniker-end
The `<div>` in the parent component's rendered webpage contains `extra="10"` when passed through the additional attribute:
```html
<div extra="10" />
```
## Capture references to components
Component references provide a way to reference a component instance for issuing commands. To capture a component reference:

View File

@ -0,0 +1,195 @@
---
title: ASP.NET Core Blazor attribute splatting and arbitrary parameters
author: guardrex
description: Learn how components can capture and render additional attributes in addition to the component's declared parameters.
monikerRange: '>= aspnetcore-3.1'
ms.author: riande
ms.custom: mvc
ms.date: 05/16/2023
uid: blazor/components/attribute-splatting
---
# ASP.NET Core Blazor attribute splatting and arbitrary parameters
Components can capture and render additional attributes in addition to the component's declared parameters. Additional attributes can be captured in a dictionary and then *splatted* onto an element when the component is rendered using the <xref:mvc/views/razor#attributes> Razor directive attribute. This scenario is useful for defining a component that produces a markup element that supports a variety of customizations. For example, it can be tedious to define attributes separately for an `<input>` that supports many parameters.
## Attribute splatting
In the following `Splat` component:
* The first `<input>` element (`id="useIndividualParams"`) uses individual component parameters.
* The second `<input>` element (`id="useAttributesDict"`) uses attribute splatting.
`Pages/Splat.razor`:
:::moniker range=">= aspnetcore-7.0"
:::code language="razor" source="~/../blazor-samples/7.0/BlazorSample_WebAssembly/Pages/index/Splat.razor":::
:::moniker-end
:::moniker range=">= aspnetcore-6.0 < aspnetcore-7.0"
:::code language="razor" source="~/../blazor-samples/6.0/BlazorSample_WebAssembly/Pages/index/Splat.razor":::
:::moniker-end
:::moniker range=">= aspnetcore-5.0 < aspnetcore-6.0"
:::code language="razor" source="~/../blazor-samples/5.0/BlazorSample_WebAssembly/Pages/index/Splat.razor":::
:::moniker-end
:::moniker range="< aspnetcore-5.0"
:::code language="razor" source="~/../blazor-samples/3.1/BlazorSample_WebAssembly/Pages/index/Splat.razor":::
:::moniker-end
The rendered `<input>` elements in the webpage are identical:
```html
<input id="useIndividualParams"
maxlength="10"
placeholder="Input placeholder text"
required="required"
size="50">
<input id="useAttributesDict"
maxlength="10"
placeholder="Input placeholder text"
required="required"
size="50">
```
## Arbitrary attributes
To accept arbitrary attributes, define a [component parameter](xref:blazor/components/index#component-parameters) with the <xref:Microsoft.AspNetCore.Components.ParameterAttribute.CaptureUnmatchedValues> property set to `true`:
```razor
@code {
[Parameter(CaptureUnmatchedValues = true)]
public Dictionary<string, object>? InputAttributes { get; set; }
}
```
The <xref:Microsoft.AspNetCore.Components.ParameterAttribute.CaptureUnmatchedValues> property on [`[Parameter]`](xref:Microsoft.AspNetCore.Components.ParameterAttribute) allows the parameter to match all attributes that don't match any other parameter. A component can only define a single parameter with <xref:Microsoft.AspNetCore.Components.ParameterAttribute.CaptureUnmatchedValues>. The property type used with <xref:Microsoft.AspNetCore.Components.ParameterAttribute.CaptureUnmatchedValues> must be assignable from [`Dictionary<string, object>`](xref:System.Collections.Generic.Dictionary%602) with string keys. Use of [`IEnumerable<KeyValuePair<string, object>>`](xref:System.Collections.Generic.IEnumerable%601) or [`IReadOnlyDictionary<string, object>`](xref:System.Collections.Generic.IReadOnlyDictionary%602) are also options in this scenario.
The position of <xref:mvc/views/razor#attributes> relative to the position of element attributes is important. When <xref:mvc/views/razor#attributes> are splatted on the element, the attributes are processed from right to left (last to first). Consider the following example of a parent component that consumes a child component:
`Shared/AttributeOrderChild1.razor`:
:::moniker range=">= aspnetcore-7.0"
:::code language="razor" source="~/../blazor-samples/7.0/BlazorSample_WebAssembly/Shared/index/AttributeOrderChild1.razor":::
:::moniker-end
:::moniker range=">= aspnetcore-6.0 < aspnetcore-7.0"
:::code language="razor" source="~/../blazor-samples/6.0/BlazorSample_WebAssembly/Shared/index/AttributeOrderChild1.razor":::
:::moniker-end
:::moniker range=">= aspnetcore-5.0 < aspnetcore-6.0"
:::code language="razor" source="~/../blazor-samples/5.0/BlazorSample_WebAssembly/Shared/index/AttributeOrderChild1.razor":::
:::moniker-end
:::moniker range="< aspnetcore-5.0"
:::code language="razor" source="~/../blazor-samples/3.1/BlazorSample_WebAssembly/Shared/index/AttributeOrderChild1.razor":::
:::moniker-end
`Pages/AttributeOrderParent1.razor`:
:::moniker range=">= aspnetcore-7.0"
:::code language="razor" source="~/../blazor-samples/7.0/BlazorSample_WebAssembly/Pages/index/AttributeOrderParent1.razor":::
:::moniker-end
:::moniker range=">= aspnetcore-6.0 < aspnetcore-7.0"
:::code language="razor" source="~/../blazor-samples/6.0/BlazorSample_WebAssembly/Pages/index/AttributeOrderParent1.razor":::
:::moniker-end
:::moniker range=">= aspnetcore-5.0 < aspnetcore-6.0"
:::code language="razor" source="~/../blazor-samples/5.0/BlazorSample_WebAssembly/Pages/index/AttributeOrderParent1.razor":::
:::moniker-end
:::moniker range="< aspnetcore-5.0"
:::code language="razor" source="~/../blazor-samples/3.1/BlazorSample_WebAssembly/Pages/index/AttributeOrderParent1.razor":::
:::moniker-end
The `AttributeOrderChild1` component's `extra` attribute is set to the right of <xref:mvc/views/razor#attributes>. The `AttributeOrderParent1` component's rendered `<div>` contains `extra="5"` when passed through the additional attribute because the attributes are processed right to left (last to first):
```html
<div extra="5" />
```
In the following example, the order of `extra` and <xref:mvc/views/razor#attributes> is reversed in the child component's `<div>`:
`Shared/AttributeOrderChild2.razor`:
:::moniker range=">= aspnetcore-7.0"
:::code language="razor" source="~/../blazor-samples/7.0/BlazorSample_WebAssembly/Shared/index/AttributeOrderChild2.razor":::
:::moniker-end
:::moniker range=">= aspnetcore-6.0 < aspnetcore-7.0"
:::code language="razor" source="~/../blazor-samples/6.0/BlazorSample_WebAssembly/Shared/index/AttributeOrderChild2.razor":::
:::moniker-end
:::moniker range=">= aspnetcore-5.0 < aspnetcore-6.0"
:::code language="razor" source="~/../blazor-samples/5.0/BlazorSample_WebAssembly/Shared/index/AttributeOrderChild2.razor":::
:::moniker-end
:::moniker range="< aspnetcore-5.0"
:::code language="razor" source="~/../blazor-samples/3.1/BlazorSample_WebAssembly/Shared/index/AttributeOrderChild2.razor":::
:::moniker-end
`Pages/AttributeOrderParent2.razor`:
:::moniker range=">= aspnetcore-7.0"
:::code language="razor" source="~/../blazor-samples/7.0/BlazorSample_WebAssembly/Pages/index/AttributeOrderParent2.razor":::
:::moniker-end
:::moniker range=">= aspnetcore-6.0 < aspnetcore-7.0"
:::code language="razor" source="~/../blazor-samples/6.0/BlazorSample_WebAssembly/Pages/index/AttributeOrderParent2.razor":::
:::moniker-end
:::moniker range=">= aspnetcore-5.0 < aspnetcore-6.0"
:::code language="razor" source="~/../blazor-samples/5.0/BlazorSample_WebAssembly/Pages/index/AttributeOrderParent2.razor":::
:::moniker-end
:::moniker range="< aspnetcore-5.0"
:::code language="razor" source="~/../blazor-samples/3.1/BlazorSample_WebAssembly/Pages/index/AttributeOrderParent2.razor":::
:::moniker-end
The `<div>` in the parent component's rendered webpage contains `extra="10"` when passed through the additional attribute:
```html
<div extra="10" />
```

View File

@ -420,7 +420,7 @@ This approach allows passing arbitrary additional attributes to the element. How
Use <xref:Microsoft.AspNetCore.Components.ParameterAttribute.CaptureUnmatchedValues> where component rendering performance isn't critical, such as components that aren't repeated frequently. For components that render at scale, such as each item in a large list or in the cells of a grid, try to avoid attribute splatting.
For more information, see <xref:blazor/components/index#attribute-splatting-and-arbitrary-parameters>.
For more information, see <xref:blazor/components/attribute-splatting>.
#### Implement `SetParametersAsync` manually

View File

@ -439,6 +439,8 @@ items:
uid: blazor/components/key
- name: Overwriting parameters
uid: blazor/components/overwriting-parameters
- name: Attribute splatting and arbitrary parameters
uid: blazor/components/attribute-splatting
- name: Layouts
uid: blazor/components/layouts
- name: Sections