From 2e39213c97e9716904eeadf77ee7d38781a3d243 Mon Sep 17 00:00:00 2001 From: Julien Riboulet Date: Mon, 23 Jan 2023 16:38:23 +0100 Subject: [PATCH] :globe_with_meridians: Fix --- .../docs/edit-item/create-edit-page.md | 730 +++++------ .../razor-component/generic-component.md | 1138 ++++++++--------- 2 files changed, 934 insertions(+), 934 deletions(-) diff --git a/Documentation/docusaurus/docs/edit-item/create-edit-page.md b/Documentation/docusaurus/docs/edit-item/create-edit-page.md index 9bfc8f8..d553ab5 100644 --- a/Documentation/docusaurus/docs/edit-item/create-edit-page.md +++ b/Documentation/docusaurus/docs/edit-item/create-edit-page.md @@ -1,365 +1,365 @@ ---- -sidebar_position: 4 -title: Creation of page editor ---- - -## Creation of the page - -As before, create a new page which will be named `Edit.razor` and the partial class `Edit.razor.cs`. - -## Final source code - -```cshtml title="Pages/Edit.razor" -

Edit

- -``` - -```csharp title="Pages/Edit.razor.cs" -public partial class Edit -{ -} -``` - -## Set page url - -We are going to define the url of our page by specifying that we want our identifier. - -Open the `Pages/Edit.razor` file and add the highlighted edits as follows: - -```cshtml title="Pages/Edit.razor" -// highlight-next-line -@page "/edit/{Id:int}" - -

Edit

- -``` - -## Pass a parameter - -We passed in the url the id of our item to edit, now we are going to retrieve it in a `Parameter` in order to be able to use it in our code. - -Open the `Pages/Edit.razor.cs` file and add the highlighted edits as follows: - -```cshtml title="Pages/Edit.razor.cs" -public partial class Edit -{ - [Parameter] - public int Id { get; set; } - -} -``` - -## View Parameter - -In order to verify the passage of our identifier we will display it. - -Open the `Pages/Edit.razor` file and add the highlighted edits as follows: - -```cshtml title="Pages/Edit.razor" -@page "/edit/{Id:int}" - -

Edit

- -// highlight-next-line -
My paremeter: @Id
- -``` - -## Concept: URL parameters - -### Route settings - -The router uses routing parameters to populate corresponding component parameters with the same name. -Route parameter names are case insensitive. In the following example, the `text` parameter assigns the value of the road segment to the component's `Text` property. -When a request is made for `/RouteParameter/amazing`, the `

` tag content is rendered as `Blazor is amazing!`. - -```cshtml title="Pages/RouteParameter.razor" -@page "/RouteParameter/{text}" - -

Blazor is @Text!

- -@code { - [Parameter] - public string? Text { get; set; } -} -``` - -Optional parameters are supported. -In the following example, the optional `text` parameter assigns the value of the route segment to the component's `Text` property. If the segment is not present, the value of `Text` is set to `fantastic`. - -```cshtml title="Pages/RouteParameter.razor" -@page "/RouteParameter/{text?}" - -

Blazor is @Text!

- -@code { - [Parameter] - public string? Text { get; set; } - - protected override void OnInitialized() - { - Text = Text ?? "fantastic"; - } -} -``` - -Use `OnParametersSet OnInitialized{Async}` instead to allow navigation to the same component with a different optional parameter value. -Based on the previous example, use `OnParametersSet` when the user needs to navigate from `/RouteParameter` to `/RouteParameter/amazing` or from `/RouteParameter/amazing` to `/RouteParameter`: - -```html -protected override void OnParametersSet() -{ - Text = Text ?? "fantastic"; -} -``` - -### Route Constraints - -A route constraint applies type matching on a route segment to a component. - -In the following example, the route to the `User` component matches only if: -* A routing `Id` segment is present in the request URL. -* The `Id` segment is an integer type ( `int` ). - -```cshtml title="Pages/User.razor" -@page "/user/{Id:int}" - -

User Id: @Id

- -@code { - [Parameter] - public int Id { get; set; } -} -``` - -The route constraints shown in the following table are available. -For more information about route constraints that correspond to the indifferent culture, see the disclaimer below the table. - -| Constraint | Example | Matching examples | Invariant culture correspondence -| ---- | ---- | ---- | ---- -| `bool` | `{active:bool}` | `true`, FALSE | No -| `datetime` | `{dob:datetime}` | `2016-12-31`, `2016-12-31 7:32pm` | Yes -| `decimal` | `{price:decimal}` | `49.99`, `-1,000.01` | Yes -| `double` | `{weight:double}` | `1.234`, `-1,001.01e8` | Yes -| `float` | `{weight:float}` | `1.234, -1`,`001.01e8` | Yes -| `guid` | `{id:guid}` | `CD2C1638-1638-72D5-1638-DEADBEEF1638`, `{CD2C1638-1638-72D5-1638-DEADBEEF1638}` | No -| `int` | `{id:int}` | `123456789`, `-123456789` | Yes -| `long` | `{ticks:long}` | `123456789`, `-123456789` | Yes - -:::caution -Routing constraints that check that the URL can be converted to a CLR type (like `int` or `DateTime`) always use the invariant culture. these constraints assume that the URL is not localizable. -::: - -Route constraints also work with optional parameters. In the following example, `Id` is required, but `Option` is an optional boolean route parameter. - -```cshtml title="Pages/User.razor" -@page "/user/{Id:int}/{Option:bool?}" - -

- Id: @Id -

- -

- Option: @Option -

- -@code { - [Parameter] - public int Id { get; set; } - - [Parameter] - public bool Option { get; set; } -} -``` - -## Concept: Component Parameters - -Component parameters pass data to components and are set using Public C# Properties on the component class with the `[Parameter]` attribute. - -In the following example, a built-in reference type ( `System.String` ) and a user-defined reference type ( `PanelBody` ) are passed as component parameters. - -```csharp title="PanelBody.cs" -public class PanelBody -{ - public string? Text { get; set; } - public string? Style { get; set; } -} -``` - -```cshtml title="Shared/ParameterChild.razor" -
-
@Title
-
- @Body.Text -
-
- -@code { - [Parameter] - public string Title { get; set; } = "Set By Child"; - - [Parameter] - public PanelBody Body { get; set; } = - new() - { - Text = "Set by child.", - Style = "normal" - }; -} -``` - -:::caution -Providing initial values for component parameters is supported, but does not create a component that writes to its own parameters after the component is first rendered. -::: - - -The `Title` & `Body` component and `ParameterChild` component parameters are defined by arguments in the HTML tag that renders the component instance. -The following `ParameterParent` component renders two `ParameterChild` components: -* The first `ParameterChild` component is rendered without providing any parameter arguments. -* The second `ParameterChild` component receives values for `Title` and `Body` from the `ParameterParent` component, which uses an explicit C# expression to set the values for the properties of `PanelBody`. - -```cshtml title="Pages/ParameterParent.razor" -@page "/parameter-parent" - -

Child component (without attribute values)

- - - -

Child component (with attribute values)

- - -``` - -The following rendered HTML markup of the `ParameterParent` component shows default `ParameterChild` values for components when the `ParameterParent` component does not provide component parameter values. -When the `ParameterParent` component provides component parameter values, they override the component's default `ParameterChild` values. - -:::note -For clarity, rendered CSS style classes are not shown in the following rendered HTML markup. -::: - -```html -

Child component (without attribute values)

- -
-
Set By Child
-
Set by child.
-
- -

Child component (with attribute values)

- -
-
Set by Parent
-
Set by parent.
-
-``` - -Assign a C# field, property, or result of a method to a component parameter as an HTML attribute value using the `@` symbol. -The following `ParameterParent2` component displays four instances of the preceding `ParameterChild` component and sets their parameter `Title` values to: -* Value of the `title` field. -* Result of C# `GetTitle` method. -* Current local date in long format with `ToLongDateString`, which uses an implicit C# expression. -* `panelData` Property of the `Title` object. - -```cshtml title="Pages/ParameterParent2.razor" -@page "/parameter-parent-2" - - - - - - - - - -@code { - private string title = "From Parent field"; - private PanelData panelData = new(); - - private string GetTitle() - { - return "From Parent method"; - } - - private class PanelData - { - public string Title { get; set; } = "From Parent object"; - } -} -``` - -:::info - -When assigning a C# member to a component parameter, prefix the member with the `@` symbol and never prefix the parameter's HTML attribute. - -Correct use: -```html - -``` - -Wrong: -```html - -``` - -::: - -Using an explicit Razor expression to concatenate text with an expression result for assignment to a parameter is not supported. - -The following example attempts to concatenate the text "Set by" with the property value of an object. The following Razor syntax is not supported: - -```html - -``` - -The code in the previous example generates a Compiler Error when building the application: - -``` -Les attributs de composant ne prennent pas en charge le contenu complexe (mixte C# et balisage). -``` - -To support assigning a compound value, use a method, field, or property. The following example performs the concatenation of "`Set by`" and the property value of an object in the C# `GetTitle` method: - -```cshtml title="Pages/ParameterParent3.razor" -@page "/parameter-parent-3" - - - -@code { - private PanelData panelData = new(); - - private string GetTitle() => $"Set by {panelData.Title}"; - - private class PanelData - { - public string Title { get; set; } = "Parent"; - } -} -``` - -Component parameters must be declared as Automatic Properties, which means they must not contain custom logic in their `get` or `set` accessors. -For example, the following `StartData` property is an automatic property: - -```csharp -[Parameter] -public DateTime StartData { get; set; } -``` - -Do not put custom logic in the `get` or `set` accessor, as component parameters are purely for use as a channel from a parent component to pass information to a child component. -If a `set` accessor of a child component property contains logic that causes the parent component to be re-rendered, the results of an infinite render loop. - -To transform a received parameter value: - -* Leave the parameter property as auto property to represent the raw data provided. -* Create another property or method to provide the transformed data based on the parameter property. - -Override `OnParametersSetAsync` to transform a received parameter each time new data is received. - -Writing an initial value to a component parameter is supported because initial value assignments don't interfere with automatic component Blazor rendering. -The following assignment of the current locale `DateTime` with `DateTime.Now` to `StartData` is valid syntax in a component: - -```csharp -[Parameter] -public DateTime StartData { get; set; } = DateTime.Now; -``` - -After the initial assignment of `DateTime.Now`, do not assign a value to `StartData` in code. +--- +sidebar_position: 4 +title: Creation of page editor +--- + +## Creation of the page + +As before, create a new page which will be named `Edit.razor` and the partial class `Edit.razor.cs`. + +## Final source code + +```cshtml title="Pages/Edit.razor" +

Edit

+ +``` + +```csharp title="Pages/Edit.razor.cs" +public partial class Edit +{ +} +``` + +## Set page url + +We are going to define the url of our page by specifying that we want our identifier. + +Open the `Pages/Edit.razor` file and add the highlighted edits as follows: + +```cshtml title="Pages/Edit.razor" +// highlight-next-line +@page "/edit/{Id:int}" + +

Edit

+ +``` + +## Pass a parameter + +We passed in the url the id of our item to edit, now we are going to retrieve it in a `Parameter` in order to be able to use it in our code. + +Open the `Pages/Edit.razor.cs` file and add the highlighted edits as follows: + +```cshtml title="Pages/Edit.razor.cs" +public partial class Edit +{ + [Parameter] + public int Id { get; set; } + +} +``` + +## View Parameter + +In order to verify the passage of our identifier we will display it. + +Open the `Pages/Edit.razor` file and add the highlighted edits as follows: + +```cshtml title="Pages/Edit.razor" +@page "/edit/{Id:int}" + +

Edit

+ +// highlight-next-line +
My parameter: @Id
+ +``` + +## Concept: URL parameters + +### Route settings + +The router uses routing parameters to populate corresponding component parameters with the same name. +Route parameter names are case insensitive. In the following example, the `text` parameter assigns the value of the road segment to the component's `Text` property. +When a request is made for `/RouteParameter/amazing`, the `

` tag content is rendered as `Blazor is amazing!`. + +```cshtml title="Pages/RouteParameter.razor" +@page "/RouteParameter/{text}" + +

Blazor is @Text!

+ +@code { + [Parameter] + public string? Text { get; set; } +} +``` + +Optional parameters are supported. +In the following example, the optional `text` parameter assigns the value of the route segment to the component's `Text` property. If the segment is not present, the value of `Text` is set to `fantastic`. + +```cshtml title="Pages/RouteParameter.razor" +@page "/RouteParameter/{text?}" + +

Blazor is @Text!

+ +@code { + [Parameter] + public string? Text { get; set; } + + protected override void OnInitialized() + { + Text = Text ?? "fantastic"; + } +} +``` + +Use `OnParametersSet OnInitialized{Async}` instead to allow navigation to the same component with a different optional parameter value. +Based on the previous example, use `OnParametersSet` when the user needs to navigate from `/RouteParameter` to `/RouteParameter/amazing` or from `/RouteParameter/amazing` to `/RouteParameter`: + +```html +protected override void OnParametersSet() +{ + Text = Text ?? "fantastic"; +} +``` + +### Route Constraints + +A route constraint applies type matching on a route segment to a component. + +In the following example, the route to the `User` component matches only if: +* A routing `Id` segment is present in the request URL. +* The `Id` segment is an integer type ( `int` ). + +```cshtml title="Pages/User.razor" +@page "/user/{Id:int}" + +

User Id: @Id

+ +@code { + [Parameter] + public int Id { get; set; } +} +``` + +The route constraints shown in the following table are available. +For more information about route constraints that correspond to the indifferent culture, see the disclaimer below the table. + +| Constraint | Example | Matching examples | Invariant culture correspondence +| ---- | ---- | ---- | ---- +| `bool` | `{active:bool}` | `true`, FALSE | No +| `datetime` | `{dob:datetime}` | `2016-12-31`, `2016-12-31 7:32pm` | Yes +| `decimal` | `{price:decimal}` | `49.99`, `-1,000.01` | Yes +| `double` | `{weight:double}` | `1.234`, `-1,001.01e8` | Yes +| `float` | `{weight:float}` | `1.234, -1`,`001.01e8` | Yes +| `guid` | `{id:guid}` | `CD2C1638-1638-72D5-1638-DEADBEEF1638`, `{CD2C1638-1638-72D5-1638-DEADBEEF1638}` | No +| `int` | `{id:int}` | `123456789`, `-123456789` | Yes +| `long` | `{ticks:long}` | `123456789`, `-123456789` | Yes + +:::caution +Routing constraints that check that the URL can be converted to a CLR type (like `int` or `DateTime`) always use the invariant culture. these constraints assume that the URL is not localizable. +::: + +Route constraints also work with optional parameters. In the following example, `Id` is required, but `Option` is an optional boolean route parameter. + +```cshtml title="Pages/User.razor" +@page "/user/{Id:int}/{Option:bool?}" + +

+ Id: @Id +

+ +

+ Option: @Option +

+ +@code { + [Parameter] + public int Id { get; set; } + + [Parameter] + public bool Option { get; set; } +} +``` + +## Concept: Component Parameters + +Component parameters pass data to components and are set using Public C# Properties on the component class with the `[Parameter]` attribute. + +In the following example, a built-in reference type ( `System.String` ) and a user-defined reference type ( `PanelBody` ) are passed as component parameters. + +```csharp title="PanelBody.cs" +public class PanelBody +{ + public string? Text { get; set; } + public string? Style { get; set; } +} +``` + +```cshtml title="Shared/ParameterChild.razor" +
+
@Title
+
+ @Body.Text +
+
+ +@code { + [Parameter] + public string Title { get; set; } = "Set By Child"; + + [Parameter] + public PanelBody Body { get; set; } = + new() + { + Text = "Set by child.", + Style = "normal" + }; +} +``` + +:::caution +Providing initial values for component parameters is supported, but does not create a component that writes to its own parameters after the component is first rendered. +::: + + +The `Title` & `Body` component and `ParameterChild` component parameters are defined by arguments in the HTML tag that renders the component instance. +The following `ParameterParent` component renders two `ParameterChild` components: +* The first `ParameterChild` component is rendered without providing any parameter arguments. +* The second `ParameterChild` component receives values for `Title` and `Body` from the `ParameterParent` component, which uses an explicit C# expression to set the values for the properties of `PanelBody`. + +```cshtml title="Pages/ParameterParent.razor" +@page "/parameter-parent" + +

Child component (without attribute values)

+ + + +

Child component (with attribute values)

+ + +``` + +The following rendered HTML markup of the `ParameterParent` component shows default `ParameterChild` values for components when the `ParameterParent` component does not provide component parameter values. +When the `ParameterParent` component provides component parameter values, they override the component's default `ParameterChild` values. + +:::note +For clarity, rendered CSS style classes are not shown in the following rendered HTML markup. +::: + +```html +

Child component (without attribute values)

+ +
+
Set By Child
+
Set by child.
+
+ +

Child component (with attribute values)

+ +
+
Set by Parent
+
Set by parent.
+
+``` + +Assign a C# field, property, or result of a method to a component parameter as an HTML attribute value using the `@` symbol. +The following `ParameterParent2` component displays four instances of the preceding `ParameterChild` component and sets their parameter `Title` values to: +* Value of the `title` field. +* Result of C# `GetTitle` method. +* Current local date in long format with `ToLongDateString`, which uses an implicit C# expression. +* `panelData` Property of the `Title` object. + +```cshtml title="Pages/ParameterParent2.razor" +@page "/parameter-parent-2" + + + + + + + + + +@code { + private string title = "From Parent field"; + private PanelData panelData = new(); + + private string GetTitle() + { + return "From Parent method"; + } + + private class PanelData + { + public string Title { get; set; } = "From Parent object"; + } +} +``` + +:::info + +When assigning a C# member to a component parameter, prefix the member with the `@` symbol and never prefix the parameter's HTML attribute. + +Correct use: +```html + +``` + +Wrong: +```html + +``` + +::: + +Using an explicit Razor expression to concatenate text with an expression result for assignment to a parameter is not supported. + +The following example attempts to concatenate the text "Set by" with the property value of an object. The following Razor syntax is not supported: + +```html + +``` + +The code in the previous example generates a Compiler Error when building the application: + +``` +Les attributs de composant ne prennent pas en charge le contenu complexe (mixte C# et balisage). +``` + +To support assigning a compound value, use a method, field, or property. The following example performs the concatenation of "`Set by`" and the property value of an object in the C# `GetTitle` method: + +```cshtml title="Pages/ParameterParent3.razor" +@page "/parameter-parent-3" + + + +@code { + private PanelData panelData = new(); + + private string GetTitle() => $"Set by {panelData.Title}"; + + private class PanelData + { + public string Title { get; set; } = "Parent"; + } +} +``` + +Component parameters must be declared as Automatic Properties, which means they must not contain custom logic in their `get` or `set` accessors. +For example, the following `StartData` property is an automatic property: + +```csharp +[Parameter] +public DateTime StartData { get; set; } +``` + +Do not put custom logic in the `get` or `set` accessor, as component parameters are purely for use as a channel from a parent component to pass information to a child component. +If a `set` accessor of a child component property contains logic that causes the parent component to be re-rendered, the results of an infinite render loop. + +To transform a received parameter value: + +* Leave the parameter property as auto property to represent the raw data provided. +* Create another property or method to provide the transformed data based on the parameter property. + +Override `OnParametersSetAsync` to transform a received parameter each time new data is received. + +Writing an initial value to a component parameter is supported because initial value assignments don't interfere with automatic component Blazor rendering. +The following assignment of the current locale `DateTime` with `DateTime.Now` to `StartData` is valid syntax in a component: + +```csharp +[Parameter] +public DateTime StartData { get; set; } = DateTime.Now; +``` + +After the initial assignment of `DateTime.Now`, do not assign a value to `StartData` in code. diff --git a/Documentation/docusaurus/i18n/fr/docusaurus-plugin-content-docs/current/razor-component/generic-component.md b/Documentation/docusaurus/i18n/fr/docusaurus-plugin-content-docs/current/razor-component/generic-component.md index 4b02691..323b315 100644 --- a/Documentation/docusaurus/i18n/fr/docusaurus-plugin-content-docs/current/razor-component/generic-component.md +++ b/Documentation/docusaurus/i18n/fr/docusaurus-plugin-content-docs/current/razor-component/generic-component.md @@ -1,569 +1,569 @@ ---- -sidebar_position: 2 -title: Composant générique ---- - -Les composants génériques sont des composants qui acceptent un ou plusieurs modèles d’interface utilisateur en tant que paramètres, qui peuvent ensuite être utilisés dans le cadre de la logique de rendu du composant. -Les composants génériques vous permettent de créer des composants de niveau supérieur qui sont plus réutilisables que les composants standard. Voici quelques exemples : -* Composant de table qui permet à un utilisateur de spécifier des modèles pour l’en-tête, les lignes et le pied de page de la table. -* Composant de liste qui permet à un utilisateur de spécifier un modèle pour le rendu d’éléments dans une liste. - -## Création du composant - -Créer un nouveau composant qui servira de base au composant générique : - -```cshtml title="Components/Card.razor" -

Card

-
- @CardHeader - @CardBody - @CardFooter -
-``` - -```csharp title="Components/Card.razor.cs" -public partial class Card -{ - [Parameter] - public RenderFragment CardBody { get; set; } - - [Parameter] - public RenderFragment CardFooter { get; set; } - - [Parameter] - public RenderFragment CardHeader { get; set; } -} -``` - -`@CardHeader`, `@CardBody` et `@CardFooter` sont des composants Templates en paramètre de type `RenderFragment`. - -```cshtml title="Pages/Index.razor" -... - - - -
- My Templated Component -
-
- -
-
Welcome To Template Component
-
-
- - - -
- -... -``` - -Chaque paramètre de Template de type `RenderFragment` aura une balise Html correspondant. La balise HTML doit correspondre au nom du paramètre. - -**Rendu:** - -![Render](/img/blazor-component/RenderFragmentCard.png) - -## Duplication de balise Html - -La balise Html qui représente le paramètre du composant Template, la dupliquer entraînera le rendu de la dernière balise Html ou celle du bas en priorité. - -```cshtml title="Pages/Index.razor" -... - - - -
- Templated Component -
-
- -
- Hi I'm duplicated header -
-
-
- -... -``` - -**Rendu:** - -![Render](/img/blazor-component/duplicate.png) - - -## Parameter typé `RenderFragment` - -* `RenderFragmetnt` est un paramètre typé qui réprésente une partie du rendu UI avec du contenu dynamique du type qu'il implémente. -* Déclarez le paramètre de type générique en haut du composant en utilisant `@typeparam`. Cela représente le type de composant au moment de l'exécution. -* Ce type de paramètre de composant typé qui est passé comme élément aura un paramètre implicite appelé `context`. -* Le paramètre implicite de contexte aide à la liaison dynamique des données. Il a accès au type de propriété implémenté par `RenderFragment`. - -```cshtml title="Components/Card.razor" -@typeparam TItem -
- @CardHeader(Item) - @CardBody(Item) - @CardFooter -
-``` - -```csharp title="Components/Card.razor.cs" -public partial class Card -{ - [Parameter] - public RenderFragment CardBody { get; set; } - - [Parameter] - public RenderFragment CardFooter { get; set; } - - [Parameter] - public RenderFragment CardHeader { get; set; } - - [Parameter] - public TItem Item { get; set; } -} -``` - -`CardHeader`, `CardBody` sont des paramètres de type `RenderFragment`. Ces propriétés modélisées Html ont accès au paramètre implicite `context` pour les données de liaison dynamiques. - -```csharp title="Models/Cake.cs" -public class Cake -{ - public int Id { get; set; } - public string Name { get; set; } - public decimal Cost { get; set; } -} -``` - -```cshtml title="Pages/Index.razor" -... - - - -
- Cake Token Number - @context.Id -
-
- -
-
@context.Name
-
$ @context.Cost
-
-
- - - -
- -... -``` - -```csharp title="Pages/Index.razor.cs" -public partial class Index -{ - private Cake CakeItem = new Cake - { - Id = 1, - Name = "Black Forest", - Cost = 50 - }; -} -``` - -**Rendu:** - -![Render](/img/blazor-component/typeRenderFragment.png) - - -## Attribut de contexte sur l'élément Template HTML - -Dans le composant, le contexte peut être déclaré explicitement en tant qu'attribut Html. -La valeur affectée au contexte (attribut Html) sera utilisée pour la liaison dynamique dans tous les templates du composant. - -Déclaration de l'attribut Context au niveau du composant. - -```cshtml title="Pages/Index.razor" -... - - - -
- Cake Token Number - @cakeContext.Id -
-
- -
-
@cakeContext.Name
-
$ @cakeContext.Cost
-
-
-
- -... -``` - -Attribut de contexte de déclaration au niveau de chaque template. - -```cshtml title="Pages/Index.razor" -... - - - -
- Cake Token Number - @headContext.Id -
-
- -
-
@bodyContext.Name
-
$ @bodyContext.Cost
-
-
-
- -... -``` - -## Composant générique - -Le composant template est lui même un composant générique. `@typeparam` définie le type du composant générique. -Le composant template générique sera défini par notre propre implémentation et il peut être réutilisé pour différents types. - -Le meilleur choix de son implémentation est comme le composant avec seulement deux propriétés. -La première propriété est de type `RenderFragment` pour restituer le contenu. -La deuxième propriété est de type `List` une collection de données à lier au rendu. - -Les scénarios les plus largement utilisés pour le composant générique sont des éléments d'affichage, -cela aidera à éviter de créer de nouveaux composants pour afficher des éléments dans une application. -Un composant unique pour tous les éléments d'affichage. - -```cshtml title="Components/ShowItems.razor" -@typeparam TItem - -
- @if ((Items?.Count ?? 0) != 0) - { - @foreach (var item in Items) - { - @ShowTemplate(item); - } - } -
-``` - -```cshtml title="Components/ShowItems.razor.cs" -public partial class ShowItems -{ - [Parameter] - public List Items { get; set; } - - [Parameter] - public RenderFragment ShowTemplate { get; set; } -} -``` - -`ShowTemplate` et `Items` sont deux paramètres de notre composant de type générique. -`ShowTemplate` est une propriété de type `RenderFragment` qui rendra le Html à afficher (ce Html peut être un tableau, une liste, un contenu, etc.). -`Items` est une collection dont le type correspond à notre type de composant, ces données seront utilisées dans la liaison de données à l'intérieur de notre Html rendu. - -```cshtml title="Pages/Index.razor" -... - - - -
-
- Cake Token Id - @CakeContext.Id -
-
-
@CakeContext.Name
-

Price $@CakeContext.Cost

-
- -
-
-
- -... -``` - -Le template `ShowItems` représente notre composant de type générique. `ShowTemplate` représente la propriété de rendu HTML du composant. - -```csharp title="Pages/Index.razor.cs" -public partial class Index -{ - ... - - public List Cakes { get; set; } - - protected override Task OnAfterRenderAsync(bool firstRender) - { - LoadCakes(); - StateHasChanged(); - return base.OnAfterRenderAsync(firstRender); - } - - public void LoadCakes() - { - Cakes = new List - { - // items hidden for display purpose - new Cake - { - Id = 1, - Name = "Red Velvet", - Cost = 60 - }, - }; - } - - ... -} -``` - -À l'intérieur de la méthode `OnAfterRenderAsync` on appele la méthode `StageHasChanged()` pour refléter les modifications de données dans le composant. -Vous pouvez essayer de supprimer la méthode `StateHasChanged()` et vous pouvez observer une page vide sans afficher de données car nous remplissons des données avant de rendre Html. - -**Rendu:** - -![Render](/img/blazor-component/genericStatic.png) - - - -## Notion : RenderFragment - -Les composants template sont des composants qui acceptent un ou plusieurs modèles d’interface utilisateur en tant que paramètres, qui peuvent ensuite être utilisés dans le cadre de la logique de rendu du composant. -Les composants template vous permettent de créer des composants de niveau supérieur qui sont plus réutilisables que les composants normaux. - -Voici quelques exemples : -* Composant de table qui permet à un utilisateur de spécifier des template pour l’en-tête, les lignes et le pied de page de la table. -* Composant de liste qui permet à un utilisateur de spécifier un template pour afficher des éléments dans une liste. - -Un composant template est défini en spécifiant un ou plusieurs paramètres de composant de type `RenderFragment` ou `RenderFragment`. -Un fragment de rendu représente un segment de l’interface utilisateur à restituer. `RenderFragment` prend un paramètre de type qui peut être spécifié lors de l’appel du fragment de rendu. - -Souvent, les composants template sont typés de façon générique, comme le montre le composant suivant `TableTemplate`. -Le type générique `` dans cet exemple est utilisé pour restituer des valeurs `IReadOnlyList`, qui dans ce cas est une série de lignes PET dans un composant qui affiche une table d’animaux familiers. - -```cshtml title="Shared/TableTemplate.razor" -@typeparam TItem -@using System.Diagnostics.CodeAnalysis - - - - @TableHeader - - - @foreach (var item in Items) - { - if (RowTemplate is not null) - { - @RowTemplate(item) - } - } - -
- -@code { - [Parameter] - public RenderFragment? TableHeader { get; set; } - - [Parameter] - public RenderFragment? RowTemplate { get; set; } - - [Parameter, AllowNull] - public IReadOnlyList Items { get; set; } -} -``` - -Lorsque vous utilisez un composant template, les paramètres de modèle peuvent être spécifiés à l’aide d’éléments enfants qui correspondent aux noms des paramètres. -Dans l’exemple suivant, `...` et `...` fournissent des template `RenderFragment` pour `TableHeader` et `RowTemplate` du composant `TableTemplate`. - -Spécifiez l'attribut `Context` sur l’élément composant lorsque vous souhaitez spécifier le nom du paramètre de contenu pour le contenu enfant implicite (sans élément enfant d’encapsulation). -Dans l’exemple suivant, l'attribut `Context` apparaît sur l'élément `TableTemplate` et s’applique à tous les paramètres de template `RenderFragment`. - -```cshtml title="Pages/Pets1.razor" -@page "/pets1" - -

Pets

- - - - ID - Name - - - @pet.PetId - @pet.Name - - - -@code { - private List pets = new() - { - new Pet { PetId = 2, Name = "Mr. Bigglesworth" }, - new Pet { PetId = 4, Name = "Salem Saberhagen" }, - new Pet { PetId = 7, Name = "K-9" } - }; - - private class Pet - { - public int PetId { get; set; } - public string? Name { get; set; } - } -} -``` - -Vous pouvez également modifier le nom du paramètre à l’aide de l’attribut `Context` sur l'élément enfant `RenderFragment`. -Dans l’exemple suivant, le `Context` est défini sur `RowTemplate` au lieu de `TableTemplate` : - -```cshtml title="Pages/Pets2.razor" -@page "/pets2" - -

Pets

- - - - ID - Name - - - @pet.PetId - @pet.Name - - - -@code { - private List pets = new() - { - new Pet { PetId = 2, Name = "Mr. Bigglesworth" }, - new Pet { PetId = 4, Name = "Salem Saberhagen" }, - new Pet { PetId = 7, Name = "K-9" } - }; - - private class Pet - { - public int PetId { get; set; } - public string? Name { get; set; } - } -} -``` - -Les arguments de composant de type `RenderFragment` ont un paramètre implicite nommé `context`, qui peut être utilisé. -Dans l’exemple suivant, `Context` n’est pas défini. `@context.{PROPERTY}` fournit des valeurs de `PET` au modèle, où `{PROPERTY}` est une propriété `Pet` : - -```cshtml title="Pages/Pets3.razor" -@page "/pets3" - -

Pets

- - - - ID - Name - - - @context.PetId - @context.Name - - - -@code { - private List pets = new() - { - new Pet { PetId = 2, Name = "Mr. Bigglesworth" }, - new Pet { PetId = 4, Name = "Salem Saberhagen" }, - new Pet { PetId = 7, Name = "K-9" } - }; - - private class Pet - { - public int PetId { get; set; } - public string? Name { get; set; } - } -} -``` - -Lorsque vous utilisez des composants génériques, le paramètre de type est déduit si possible. -Toutefois, vous pouvez spécifier explicitement le type avec un attribut dont le nom correspond au paramètre de type, qui est `TItem` dans l’exemple précédent : - -```cshtml title="Pages/Pets4.razor" -@page "/pets4" - -

Pets

- - - - ID - Name - - - @context.PetId - @context.Name - - - -@code { - private List pets = new() - { - new Pet { PetId = 2, Name = "Mr. Bigglesworth" }, - new Pet { PetId = 4, Name = "Salem Saberhagen" }, - new Pet { PetId = 7, Name = "K-9" } - }; - - private class Pet - { - public int PetId { get; set; } - public string? Name { get; set; } - } -} -``` - -Par défaut un nouveau composant blazor n'accepte pas contenu si vous ne déclarer pas un `RenderFragment` nommé `ChildContent`. - -```cshtml title="Components/TestRenderFragment.razor" -

TestRenderFragment

- -@code { - -} -``` - -```cshtml title="Pages/Index.razor" -... - - -
Content of my TestRenderFragment
-
- -... -``` - -Ce code ne génére pas d'erreur de compilation mais déclenchera l'erreur suivante lors de l'éxécution : - -``` -Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100] - Unhandled exception rendering component: Object of type 'MyBeautifulAdmin.Components.TestRenderFragment' does not have a property matching the name 'ChildContent'. -System.InvalidOperationException: Object of type 'MyBeautifulAdmin.Components.TestRenderFragment' does not have a property matching the name 'ChildContent'. -``` - -Afin de rendre le code enfant, utiliser le code suivant : - -```cshtml title="Components/TestRenderFragment.razor" -

TestRenderFragment

- -@code { - [Parameter] - public RenderFragment ChildContent { get; set; } -} - -@ChildContent -``` +--- +sidebar_position: 2 +title: Composant générique +--- + +Les composants génériques sont des composants qui acceptent un ou plusieurs modèles d’interface utilisateur en tant que paramètres, qui peuvent ensuite être utilisés dans le cadre de la logique de rendu du composant. +Les composants génériques vous permettent de créer des composants de niveau supérieur qui sont plus réutilisables que les composants standard. Voici quelques exemples : +* Composant de table qui permet à un utilisateur de spécifier des modèles pour l’en-tête, les lignes et le pied de page de la table. +* Composant de liste qui permet à un utilisateur de spécifier un modèle pour le rendu d’éléments dans une liste. + +## Création du composant + +Créer un nouveau composant qui servira de base au composant générique : + +```cshtml title="Components/Card.razor" +

Card

+
+ @CardHeader + @CardBody + @CardFooter +
+``` + +```csharp title="Components/Card.razor.cs" +public partial class Card +{ + [Parameter] + public RenderFragment CardBody { get; set; } + + [Parameter] + public RenderFragment CardFooter { get; set; } + + [Parameter] + public RenderFragment CardHeader { get; set; } +} +``` + +`@CardHeader`, `@CardBody` et `@CardFooter` sont des composants Templates en paramètre de type `RenderFragment`. + +```cshtml title="Pages/Index.razor" +... + + + +
+ My Templated Component +
+
+ +
+
Welcome To Template Component
+
+
+ + + +
+ +... +``` + +Chaque paramètre de Template de type `RenderFragment` aura une balise Html correspondant. La balise HTML doit correspondre au nom du paramètre. + +**Rendu:** + +![Render](/img/blazor-component/RenderFragmentCard.png) + +## Duplication de balise Html + +La balise Html qui représente le paramètre du composant Template, la dupliquer entraînera le rendu de la dernière balise Html ou celle du bas en priorité. + +```cshtml title="Pages/Index.razor" +... + + + +
+ Templated Component +
+
+ +
+ Hi I'm duplicated header +
+
+
+ +... +``` + +**Rendu:** + +![Render](/img/blazor-component/duplicate.png) + + +## Parameter typé `RenderFragment` + +* `RenderFragment` est un paramètre typé qui réprésente une partie du rendu UI avec du contenu dynamique du type qu'il implémente. +* Déclarez le paramètre de type générique en haut du composant en utilisant `@typeparam`. Cela représente le type de composant au moment de l'exécution. +* Ce type de paramètre de composant typé qui est passé comme élément aura un paramètre implicite appelé `context`. +* Le paramètre implicite de contexte aide à la liaison dynamique des données. Il a accès au type de propriété implémenté par `RenderFragment`. + +```cshtml title="Components/Card.razor" +@typeparam TItem +
+ @CardHeader(Item) + @CardBody(Item) + @CardFooter +
+``` + +```csharp title="Components/Card.razor.cs" +public partial class Card +{ + [Parameter] + public RenderFragment CardBody { get; set; } + + [Parameter] + public RenderFragment CardFooter { get; set; } + + [Parameter] + public RenderFragment CardHeader { get; set; } + + [Parameter] + public TItem Item { get; set; } +} +``` + +`CardHeader`, `CardBody` sont des paramètres de type `RenderFragment`. Ces propriétés modélisées Html ont accès au paramètre implicite `context` pour les données de liaison dynamiques. + +```csharp title="Models/Cake.cs" +public class Cake +{ + public int Id { get; set; } + public string Name { get; set; } + public decimal Cost { get; set; } +} +``` + +```cshtml title="Pages/Index.razor" +... + + + +
+ Cake Token Number - @context.Id +
+
+ +
+
@context.Name
+
$ @context.Cost
+
+
+ + + +
+ +... +``` + +```csharp title="Pages/Index.razor.cs" +public partial class Index +{ + private Cake CakeItem = new Cake + { + Id = 1, + Name = "Black Forest", + Cost = 50 + }; +} +``` + +**Rendu:** + +![Render](/img/blazor-component/typeRenderFragment.png) + + +## Attribut de contexte sur l'élément Template HTML + +Dans le composant, le contexte peut être déclaré explicitement en tant qu'attribut Html. +La valeur affectée au contexte (attribut Html) sera utilisée pour la liaison dynamique dans tous les templates du composant. + +Déclaration de l'attribut Context au niveau du composant. + +```cshtml title="Pages/Index.razor" +... + + + +
+ Cake Token Number - @cakeContext.Id +
+
+ +
+
@cakeContext.Name
+
$ @cakeContext.Cost
+
+
+
+ +... +``` + +Attribut de contexte de déclaration au niveau de chaque template. + +```cshtml title="Pages/Index.razor" +... + + + +
+ Cake Token Number - @headContext.Id +
+
+ +
+
@bodyContext.Name
+
$ @bodyContext.Cost
+
+
+
+ +... +``` + +## Composant générique + +Le composant template est lui même un composant générique. `@typeparam` définie le type du composant générique. +Le composant template générique sera défini par notre propre implémentation et il peut être réutilisé pour différents types. + +Le meilleur choix de son implémentation est comme le composant avec seulement deux propriétés. +La première propriété est de type `RenderFragment` pour restituer le contenu. +La deuxième propriété est de type `List` une collection de données à lier au rendu. + +Les scénarios les plus largement utilisés pour le composant générique sont des éléments d'affichage, +cela aidera à éviter de créer de nouveaux composants pour afficher des éléments dans une application. +Un composant unique pour tous les éléments d'affichage. + +```cshtml title="Components/ShowItems.razor" +@typeparam TItem + +
+ @if ((Items?.Count ?? 0) != 0) + { + @foreach (var item in Items) + { + @ShowTemplate(item); + } + } +
+``` + +```cshtml title="Components/ShowItems.razor.cs" +public partial class ShowItems +{ + [Parameter] + public List Items { get; set; } + + [Parameter] + public RenderFragment ShowTemplate { get; set; } +} +``` + +`ShowTemplate` et `Items` sont deux paramètres de notre composant de type générique. +`ShowTemplate` est une propriété de type `RenderFragment` qui rendra le Html à afficher (ce Html peut être un tableau, une liste, un contenu, etc.). +`Items` est une collection dont le type correspond à notre type de composant, ces données seront utilisées dans la liaison de données à l'intérieur de notre Html rendu. + +```cshtml title="Pages/Index.razor" +... + + + +
+
+ Cake Token Id - @CakeContext.Id +
+
+
@CakeContext.Name
+

Price $@CakeContext.Cost

+
+ +
+
+
+ +... +``` + +Le template `ShowItems` représente notre composant de type générique. `ShowTemplate` représente la propriété de rendu HTML du composant. + +```csharp title="Pages/Index.razor.cs" +public partial class Index +{ + ... + + public List Cakes { get; set; } + + protected override Task OnAfterRenderAsync(bool firstRender) + { + LoadCakes(); + StateHasChanged(); + return base.OnAfterRenderAsync(firstRender); + } + + public void LoadCakes() + { + Cakes = new List + { + // items hidden for display purpose + new Cake + { + Id = 1, + Name = "Red Velvet", + Cost = 60 + }, + }; + } + + ... +} +``` + +À l'intérieur de la méthode `OnAfterRenderAsync` on appele la méthode `StageHasChanged()` pour refléter les modifications de données dans le composant. +Vous pouvez essayer de supprimer la méthode `StateHasChanged()` et vous pouvez observer une page vide sans afficher de données car nous remplissons des données avant de rendre Html. + +**Rendu:** + +![Render](/img/blazor-component/genericStatic.png) + + + +## Notion : RenderFragment + +Les composants template sont des composants qui acceptent un ou plusieurs modèles d’interface utilisateur en tant que paramètres, qui peuvent ensuite être utilisés dans le cadre de la logique de rendu du composant. +Les composants template vous permettent de créer des composants de niveau supérieur qui sont plus réutilisables que les composants normaux. + +Voici quelques exemples : +* Composant de table qui permet à un utilisateur de spécifier des template pour l’en-tête, les lignes et le pied de page de la table. +* Composant de liste qui permet à un utilisateur de spécifier un template pour afficher des éléments dans une liste. + +Un composant template est défini en spécifiant un ou plusieurs paramètres de composant de type `RenderFragment` ou `RenderFragment`. +Un fragment de rendu représente un segment de l’interface utilisateur à restituer. `RenderFragment` prend un paramètre de type qui peut être spécifié lors de l’appel du fragment de rendu. + +Souvent, les composants template sont typés de façon générique, comme le montre le composant suivant `TableTemplate`. +Le type générique `` dans cet exemple est utilisé pour restituer des valeurs `IReadOnlyList`, qui dans ce cas est une série de lignes PET dans un composant qui affiche une table d’animaux familiers. + +```cshtml title="Shared/TableTemplate.razor" +@typeparam TItem +@using System.Diagnostics.CodeAnalysis + + + + @TableHeader + + + @foreach (var item in Items) + { + if (RowTemplate is not null) + { + @RowTemplate(item) + } + } + +
+ +@code { + [Parameter] + public RenderFragment? TableHeader { get; set; } + + [Parameter] + public RenderFragment? RowTemplate { get; set; } + + [Parameter, AllowNull] + public IReadOnlyList Items { get; set; } +} +``` + +Lorsque vous utilisez un composant template, les paramètres de modèle peuvent être spécifiés à l’aide d’éléments enfants qui correspondent aux noms des paramètres. +Dans l’exemple suivant, `...` et `...` fournissent des template `RenderFragment` pour `TableHeader` et `RowTemplate` du composant `TableTemplate`. + +Spécifiez l'attribut `Context` sur l’élément composant lorsque vous souhaitez spécifier le nom du paramètre de contenu pour le contenu enfant implicite (sans élément enfant d’encapsulation). +Dans l’exemple suivant, l'attribut `Context` apparaît sur l'élément `TableTemplate` et s’applique à tous les paramètres de template `RenderFragment`. + +```cshtml title="Pages/Pets1.razor" +@page "/pets1" + +

Pets

+ + + + ID + Name + + + @pet.PetId + @pet.Name + + + +@code { + private List pets = new() + { + new Pet { PetId = 2, Name = "Mr. Bigglesworth" }, + new Pet { PetId = 4, Name = "Salem Saberhagen" }, + new Pet { PetId = 7, Name = "K-9" } + }; + + private class Pet + { + public int PetId { get; set; } + public string? Name { get; set; } + } +} +``` + +Vous pouvez également modifier le nom du paramètre à l’aide de l’attribut `Context` sur l'élément enfant `RenderFragment`. +Dans l’exemple suivant, le `Context` est défini sur `RowTemplate` au lieu de `TableTemplate` : + +```cshtml title="Pages/Pets2.razor" +@page "/pets2" + +

Pets

+ + + + ID + Name + + + @pet.PetId + @pet.Name + + + +@code { + private List pets = new() + { + new Pet { PetId = 2, Name = "Mr. Bigglesworth" }, + new Pet { PetId = 4, Name = "Salem Saberhagen" }, + new Pet { PetId = 7, Name = "K-9" } + }; + + private class Pet + { + public int PetId { get; set; } + public string? Name { get; set; } + } +} +``` + +Les arguments de composant de type `RenderFragment` ont un paramètre implicite nommé `context`, qui peut être utilisé. +Dans l’exemple suivant, `Context` n’est pas défini. `@context.{PROPERTY}` fournit des valeurs de `PET` au modèle, où `{PROPERTY}` est une propriété `Pet` : + +```cshtml title="Pages/Pets3.razor" +@page "/pets3" + +

Pets

+ + + + ID + Name + + + @context.PetId + @context.Name + + + +@code { + private List pets = new() + { + new Pet { PetId = 2, Name = "Mr. Bigglesworth" }, + new Pet { PetId = 4, Name = "Salem Saberhagen" }, + new Pet { PetId = 7, Name = "K-9" } + }; + + private class Pet + { + public int PetId { get; set; } + public string? Name { get; set; } + } +} +``` + +Lorsque vous utilisez des composants génériques, le paramètre de type est déduit si possible. +Toutefois, vous pouvez spécifier explicitement le type avec un attribut dont le nom correspond au paramètre de type, qui est `TItem` dans l’exemple précédent : + +```cshtml title="Pages/Pets4.razor" +@page "/pets4" + +

Pets

+ + + + ID + Name + + + @context.PetId + @context.Name + + + +@code { + private List pets = new() + { + new Pet { PetId = 2, Name = "Mr. Bigglesworth" }, + new Pet { PetId = 4, Name = "Salem Saberhagen" }, + new Pet { PetId = 7, Name = "K-9" } + }; + + private class Pet + { + public int PetId { get; set; } + public string? Name { get; set; } + } +} +``` + +Par défaut un nouveau composant blazor n'accepte pas contenu si vous ne déclarer pas un `RenderFragment` nommé `ChildContent`. + +```cshtml title="Components/TestRenderFragment.razor" +

TestRenderFragment

+ +@code { + +} +``` + +```cshtml title="Pages/Index.razor" +... + + +
Content of my TestRenderFragment
+
+ +... +``` + +Ce code ne génére pas d'erreur de compilation mais déclenchera l'erreur suivante lors de l'éxécution : + +``` +Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100] + Unhandled exception rendering component: Object of type 'MyBeautifulAdmin.Components.TestRenderFragment' does not have a property matching the name 'ChildContent'. +System.InvalidOperationException: Object of type 'MyBeautifulAdmin.Components.TestRenderFragment' does not have a property matching the name 'ChildContent'. +``` + +Afin de rendre le code enfant, utiliser le code suivant : + +```cshtml title="Components/TestRenderFragment.razor" +

TestRenderFragment

+ +@code { + [Parameter] + public RenderFragment ChildContent { get; set; } +} + +@ChildContent +```