--- title: Dynamically-rendered ASP.NET Core Razor components author: guardrex description: Learn how to use dynamically-rendered Razor components in Blazor apps. monikerRange: '>= aspnetcore-6.0' ms.author: riande ms.custom: mvc ms.date: 11/08/2022 uid: blazor/components/dynamiccomponent --- # Dynamically-rendered ASP.NET Core Razor components By [Dave Brock](https://twitter.com/daveabrock) Use the built-in component to render components by type. :::moniker range=">= aspnetcore-7.0" A is useful for rendering components without iterating through possible types or using conditional logic. For example, can render a component based on a user selection from a dropdown list. In the following example: * `componentType` specifies the type. * `parameters` specifies component parameters to pass to the `componentType` component. ```razor @code { private Type componentType = ...; private IDictionary parameters = ...; } ``` For more information on passing parameter values, see the [Pass parameters](#pass-parameters) section later in this article. Use the property to access the dynamically-created component instance: ```razor @code { private DynamicComponent? dc; private Task Refresh() { return (dc?.Instance as IRefreshable)?.Refresh(); } } ``` In the preceding example: * The `{COMPONENT}` placeholder is the dynamically-created component type. * `IRefreshable` is an example interface provided by the developer for the dynamic component instance. ## Example In the following example, a Razor component renders a component based on the user's selection from a dropdown list of four possible values. | User spaceflight carrier selection | Shared Razor component to render | | ---------------------------------- | ----------------------------------- | | Rocket Lab® | `Shared/RocketLab.razor` | | SpaceX® | `Shared/SpaceX.razor` | | ULA® | `Shared/UnitedLaunchAlliance.razor` | | Virgin Galactic® | `Shared/VirginGalactic.razor` | `Shared/RocketLab.razor`: :::code language="razor" source="~/../blazor-samples/7.0/BlazorSample_WebAssembly/Shared/dynamiccomponent/RocketLab.razor"::: `Shared/SpaceX.razor`: :::code language="razor" source="~/../blazor-samples/7.0/BlazorSample_WebAssembly/Shared/dynamiccomponent/SpaceX.razor"::: `Shared/UnitedLaunchAlliance.razor`: :::code language="razor" source="~/../blazor-samples/7.0/BlazorSample_WebAssembly/Shared/dynamiccomponent/UnitedLaunchAlliance.razor"::: `Shared/VirginGalactic.razor`: :::code language="razor" source="~/../blazor-samples/7.0/BlazorSample_WebAssembly/Shared/dynamiccomponent/VirginGalactic.razor"::: `Pages/DynamicComponentExample1.razor`: :::code language="razor" source="~/../blazor-samples/7.0/BlazorSample_WebAssembly/Pages/dynamiccomponent/DynamicComponentExample1.razor"::: In the preceding example: * Component names are used as the option values using the [`nameof` operator](/dotnet/csharp/language-reference/operators/nameof), which returns component names as constant strings. * The namespace of the app is `BlazorSample`. Change the namespace to match your app's namespace. ## Pass parameters If dynamically-rendered components have [component parameters](xref:blazor/components/index#component-parameters), pass them into the as an `IDictionary`. The `string` is the name of the parameter, and the `object` is the parameter's value. The following example configures a component metadata object (`ComponentMetadata`) to supply parameter values to dynamically-rendered components based on the type name. The example is just one of several approaches that you can adopt. Parameter data can also be provided from a web API, a database, or a method. The only requirement is that the approach returns an `IDictionary`. `ComponentMetadata.cs`: ```csharp public class ComponentMetadata { public string? Name { get; set; } public Dictionary Parameters { get; set; } = new Dictionary(); } ``` The following `RocketLabWithWindowSeat` component (`Shared/RocketLabWithWindowSeat.razor`) has been updated from the preceding example to include a component parameter named `WindowSeat` to specify if the passenger prefers a window seat on their flight: `Shared/RocketLabWithWindowSeat.razor`: :::code language="razor" source="~/../blazor-samples/7.0/BlazorSample_WebAssembly/Shared/dynamiccomponent/RocketLabWithWindowSeat.razor" highlight="13-14"::: In the following example: * Only the `RocketLabWithWindowSeat` component's parameter for a window seat (`WindowSeat`) receives the value of the **`Window Seat`** checkbox. * The namespace of the app is `BlazorSample`. Change the namespace to match your app's namespace. * The dynamically-rendered components are shared components in the app's `Shared` folder: * Shown in this article section: `RocketLabWithWindowSeat` (`Shared/RocketLabWithWindowSeat.razor`) * Components shown in the [Example](#example) section earlier in this article: * `SpaceX` (`Shared/SpaceX.razor`) * `UnitedLaunchAlliance` (`Shared/UnitedLaunchAlliance.razor`) * `VirginGalactic` (`Shared/VirginGalactic.razor`) `Pages/DynamicComponentExample2.razor`: :::code language="razor" source="~/../blazor-samples/7.0/BlazorSample_WebAssembly/Pages/dynamiccomponent/DynamicComponentExample2.razor"::: ## Event callbacks (`EventCallback`) Event callbacks () can be passed to a in its parameter dictionary. `ComponentMetadata.cs`: ```csharp public class ComponentMetadata { public string? Name { get; set; } public Dictionary Parameters { get; set; } = new Dictionary(); } ``` Implement an event callback parameter () within each dynamically-rendered component. `Shared/RocketLab2.razor`: ```razor

Rocket Lab®

Rocket Lab is a registered trademark of Rocket Lab USA Inc.

@code { [Parameter] public EventCallback OnClickCallback { get; set; } } ``` `Shared/SpaceX2.razor`: ```razor

SpaceX®

SpaceX is a registered trademark of Space Exploration Technologies Corp.

@code { [Parameter] public EventCallback OnClickCallback { get; set; } } ``` `Shared/UnitedLaunchAlliance2.razor`: ```razor

United Launch Alliance®

United Launch Alliance and ULA are registered trademarks of United Launch Alliance, LLC.

@code { [Parameter] public EventCallback OnClickCallback { get; set; } } ``` `Shared/VirginGalactic2.razor`: ```razor

Virgin Galactic®

Virgin Galactic is a registered trademark of Galactic Enterprises, LLC.

@code { [Parameter] public EventCallback OnClickCallback { get; set; } } ``` In the following parent component example, the `ShowDTMessage` method assigns a string with the current time to `message`, and the value of `message` is rendered. The parent component passes the callback method, `ShowDTMessage` in the parameter dictionary: * The `string` key is the callback method's name, `OnClickCallback`. * The `object` value is created by for the parent callback method, `ShowDTMessage`. Note that the [`this` keyword](/dotnet/csharp/language-reference/keywords/this) isn't supported in C# fields, so a C# property is used for the parameter dictionary. **For the following component, change the namespace name of `BlazorSample` in the `OnDropdownChange` method to match your app's namespace.** `Pages/DynamicComponentExample3.razor`: ```razor @page "/dynamiccomponent-example-3"

DynamicComponent Component Example 3

@if (selectedType is not null) {
}

@message

@code { private Type? selectedType; private string? message; private Dictionary Components { get { return new Dictionary() { { "RocketLab2", new ComponentMetadata { Name = "Rocket Lab", Parameters = new() { { "OnClickCallback", EventCallback.Factory.Create( this, ShowDTMessage) } } } }, { "VirginGalactic2", new ComponentMetadata { Name = "Virgin Galactic", Parameters = new() { { "OnClickCallback", EventCallback.Factory.Create( this, ShowDTMessage) } } } }, { "UnitedLaunchAlliance2", new ComponentMetadata { Name = "ULA", Parameters = new() { { "OnClickCallback", EventCallback.Factory.Create( this, ShowDTMessage) } } } }, { "SpaceX2", new ComponentMetadata { Name = "SpaceX", Parameters = new() { { "OnClickCallback", EventCallback.Factory.Create( this, ShowDTMessage) } } } } }; } } private void OnDropdownChange(ChangeEventArgs e) { selectedType = e.Value?.ToString()?.Length > 0 ? Type.GetType($"BlazorSample.Shared.{e.Value}") : null; } private void ShowDTMessage(MouseEventArgs e) => message = $"The current DT is: {DateTime.Now}."; } ``` ## Avoid catch-all parameters Avoid the use of [catch-all parameters](xref:blazor/fundamentals/routing#catch-all-route-parameters). If catch-all parameters are used, every explicit parameter on effectively is a reserved word that you can't pass to a dynamic child. Any new parameters passed to are a breaking change, as they start shadowing child component parameters that happen to have the same name. It's unlikely that the caller always knows a fixed set of parameter names to pass to all possible dynamic children. ## Trademarks Rocket Lab is a registered trademark of [Rocket Lab USA Inc.](https://www.rocketlabusa.com/) SpaceX is a registered trademark of [Space Exploration Technologies Corp.](https://www.spacex.com/) United Launch Alliance and ULA are registered trademarks of [United Launch Alliance, LLC](https://www.ulalaunch.com/). Virgin Galactic is a registered trademark of [Galactic Enterprises, LLC](https://www.virgingalactic.com/). ## Additional resources * :::moniker-end :::moniker range="< aspnetcore-7.0" A is useful for rendering components without iterating through possible types or using conditional logic. For example, can render a component based on a user selection from a dropdown list. In the following example: * `componentType` specifies the type. * `parameters` specifies component parameters to pass to the `componentType` component. ```razor @code { private Type componentType = ...; private IDictionary parameters = ...; } ``` For more information on passing parameter values, see the [Pass parameters](#pass-parameters) section later in this article. Use the property to access the dynamically-created component instance: ```razor @code { private DynamicComponent? dc; private Task Refresh() { return (dc?.Instance as IRefreshable)?.Refresh(); } } ``` In the preceding example: * The `{COMPONENT}` placeholder is the dynamically-created component type. * `IRefreshable` is an example interface provided by the developer for the dynamic component instance. ## Example In the following example, a Razor component renders a component based on the user's selection from a dropdown list of four possible values. | User spaceflight carrier selection | Shared Razor component to render | | ---------------------------------- | ----------------------------------- | | Rocket Lab® | `Shared/RocketLab.razor` | | SpaceX® | `Shared/SpaceX.razor` | | ULA® | `Shared/UnitedLaunchAlliance.razor` | | Virgin Galactic® | `Shared/VirginGalactic.razor` | `Shared/RocketLab.razor`: :::code language="razor" source="~/../blazor-samples/6.0/BlazorSample_WebAssembly/Shared/dynamiccomponent/RocketLab.razor"::: `Shared/SpaceX.razor`: :::code language="razor" source="~/../blazor-samples/6.0/BlazorSample_WebAssembly/Shared/dynamiccomponent/SpaceX.razor"::: `Shared/UnitedLaunchAlliance.razor`: :::code language="razor" source="~/../blazor-samples/6.0/BlazorSample_WebAssembly/Shared/dynamiccomponent/UnitedLaunchAlliance.razor"::: `Shared/VirginGalactic.razor`: :::code language="razor" source="~/../blazor-samples/6.0/BlazorSample_WebAssembly/Shared/dynamiccomponent/VirginGalactic.razor"::: `Pages/DynamicComponentExample1.razor`: :::code language="razor" source="~/../blazor-samples/6.0/BlazorSample_WebAssembly/Pages/dynamiccomponent/DynamicComponentExample1.razor"::: In the preceding example: * Component names are used as the option values using the [`nameof` operator](/dotnet/csharp/language-reference/operators/nameof), which returns component names as constant strings. * The namespace of the app is `BlazorSample`. Change the namespace to match your app's namespace. ## Pass parameters If dynamically-rendered components have [component parameters](xref:blazor/components/index#component-parameters), pass them into the as an `IDictionary`. The `string` is the name of the parameter, and the `object` is the parameter's value. The following example configures a component metadata object (`ComponentMetadata`) to supply parameter values to dynamically-rendered components based on the type name. The example is just one of several approaches that you can adopt. Parameter data can also be provided from a web API, a database, or a method. The only requirement is that the approach returns an `IDictionary`. `ComponentMetadata.cs`: ```csharp public class ComponentMetadata { public string? Name { get; set; } public Dictionary Parameters { get; set; } = new Dictionary(); } ``` The following `RocketLabWithWindowSeat` component (`Shared/RocketLabWithWindowSeat.razor`) has been updated from the preceding example to include a component parameter named `WindowSeat` to specify if the passenger prefers a window seat on their flight: `Shared/RocketLabWithWindowSeat.razor`: :::code language="razor" source="~/../blazor-samples/6.0/BlazorSample_WebAssembly/Shared/dynamiccomponent/RocketLabWithWindowSeat.razor" highlight="13-14"::: In the following example: * Only the `RocketLabWithWindowSeat` component's parameter for a window seat (`WindowSeat`) receives the value of the **`Window Seat`** checkbox. * The namespace of the app is `BlazorSample`. Change the namespace to match your app's namespace. * The dynamically-rendered components are shared components in the app's `Shared` folder: * Shown in this article section: `RocketLabWithWindowSeat` (`Shared/RocketLabWithWindowSeat.razor`) * Components shown in the [Example](#example) section earlier in this article: * `SpaceX` (`Shared/SpaceX.razor`) * `UnitedLaunchAlliance` (`Shared/UnitedLaunchAlliance.razor`) * `VirginGalactic` (`Shared/VirginGalactic.razor`) `Pages/DynamicComponentExample2.razor`: :::code language="razor" source="~/../blazor-samples/6.0/BlazorSample_WebAssembly/Pages/dynamiccomponent/DynamicComponentExample2.razor"::: ## Event callbacks (`EventCallback`) Event callbacks () can be passed to a in its parameter dictionary. `ComponentMetadata.cs`: ```csharp public class ComponentMetadata { public string? Name { get; set; } public Dictionary Parameters { get; set; } = new Dictionary(); } ``` Implement an event callback parameter () within each dynamically-rendered component. `Shared/RocketLab2.razor`: ```razor

Rocket Lab®

Rocket Lab is a registered trademark of Rocket Lab USA Inc.

@code { [Parameter] public EventCallback OnClickCallback { get; set; } } ``` `Shared/SpaceX2.razor`: ```razor

SpaceX®

SpaceX is a registered trademark of Space Exploration Technologies Corp.

@code { [Parameter] public EventCallback OnClickCallback { get; set; } } ``` `Shared/UnitedLaunchAlliance2.razor`: ```razor

United Launch Alliance®

United Launch Alliance and ULA are registered trademarks of United Launch Alliance, LLC.

@code { [Parameter] public EventCallback OnClickCallback { get; set; } } ``` `Shared/VirginGalactic2.razor`: ```razor

Virgin Galactic®

Virgin Galactic is a registered trademark of Galactic Enterprises, LLC.

@code { [Parameter] public EventCallback OnClickCallback { get; set; } } ``` In the following parent component example, the `ShowDTMessage` method assigns a string with the current time to `message`, and the value of `message` is rendered. The parent component passes the callback method, `ShowDTMessage` in the parameter dictionary: * The `string` key is the callback method's name, `OnClickCallback`. * The `object` value is created by for the parent callback method, `ShowDTMessage`. Note that the [`this` keyword](/dotnet/csharp/language-reference/keywords/this) isn't supported in C# fields, so a C# property is used for the parameter dictionary. **For the following component, change the namespace name of `BlazorSample` in the `OnDropdownChange` method to match your app's namespace.** `Pages/DynamicComponentExample3.razor`: ```razor @page "/dynamiccomponent-example-3"

DynamicComponent Component Example 3

@if (selectedType is not null) {
}

@message

@code { private Type? selectedType; private string? message; private Dictionary Components { get { return new Dictionary() { { "RocketLab2", new ComponentMetadata { Name = "Rocket Lab", Parameters = new() { { "OnClickCallback", EventCallback.Factory.Create( this, ShowDTMessage) } } } }, { "VirginGalactic2", new ComponentMetadata { Name = "Virgin Galactic", Parameters = new() { { "OnClickCallback", EventCallback.Factory.Create( this, ShowDTMessage) } } } }, { "UnitedLaunchAlliance2", new ComponentMetadata { Name = "ULA", Parameters = new() { { "OnClickCallback", EventCallback.Factory.Create( this, ShowDTMessage) } } } }, { "SpaceX2", new ComponentMetadata { Name = "SpaceX", Parameters = new() { { "OnClickCallback", EventCallback.Factory.Create( this, ShowDTMessage) } } } } }; } } private void OnDropdownChange(ChangeEventArgs e) { selectedType = e.Value?.ToString()?.Length > 0 ? Type.GetType($"BlazorSample.Shared.{e.Value}") : null; } private void ShowDTMessage(MouseEventArgs e) => message = $"The current DT is: {DateTime.Now}."; } ``` ## Avoid catch-all parameters Avoid the use of [catch-all parameters](xref:blazor/fundamentals/routing#catch-all-route-parameters). If catch-all parameters are used, every explicit parameter on effectively is a reserved word that you can't pass to a dynamic child. Any new parameters passed to are a breaking change, as they start shadowing child component parameters that happen to have the same name. It's unlikely that the caller always knows a fixed set of parameter names to pass to all possible dynamic children. ## Trademarks Rocket Lab is a registered trademark of [Rocket Lab USA Inc.](https://www.rocketlabusa.com/) SpaceX is a registered trademark of [Space Exploration Technologies Corp.](https://www.spacex.com/) United Launch Alliance and ULA are registered trademarks of [United Launch Alliance, LLC](https://www.ulalaunch.com/). Virgin Galactic is a registered trademark of [Galactic Enterprises, LLC](https://www.virgingalactic.com/). ## Additional resources * :::moniker-end