Dynamically-rendered ASP.NET Core Razor components
Note
This isn't the latest version of this article. For the current release, see the .NET 8 version of this article.
Warning
This version of ASP.NET Core is no longer supported. For more information, see .NET and .NET Core Support Policy. For the current release, see the .NET 8 version of this article.
Important
This information relates to a pre-release product that may be substantially modified before it's commercially released. Microsoft makes no warranties, express or implied, with respect to the information provided here.
For the current release, see the .NET 8 version of this article.
By Dave Brock
Use the built-in DynamicComponent component to render components by type.
Dynamic components
A DynamicComponent is useful for rendering components without iterating through possible types or using conditional logic. For example, DynamicComponent 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 thecomponentType
component.
<DynamicComponent Type="componentType" Parameters="parameters" />
@code {
private Type componentType = ...;
private IDictionary<string, object> parameters = ...;
}
For more information on passing parameter values, see the Pass parameters section later in this article.
Use the Instance property to access the dynamically-created component instance:
<DynamicComponent Type="typeof({COMPONENT})" @ref="dc" />
<button @onclick="Refresh">Refresh</button>
@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® | RocketLab.razor |
SpaceX® | SpaceX.razor |
ULA® | UnitedLaunchAlliance.razor |
Virgin Galactic® | VirginGalactic.razor |
RocketLab.razor
:
<h2>Rocket Lab®</h2>
<p>
Rocket Lab is a registered trademark of
<a href="https://www.rocketlabusa.com/">Rocket Lab USA Inc.</a>
</p>
SpaceX.razor
:
<h2>SpaceX®</h2>
<p>
SpaceX is a registered trademark of
<a href="https://www.spacex.com/">Space Exploration Technologies Corp.</a>
</p>
UnitedLaunchAlliance.razor
:
<h2>United Launch Alliance®</h2>
<p>
United Launch Alliance and ULA are registered trademarks of
<a href="https://www.ulalaunch.com/">United Launch Alliance, LLC</a>.
</p>
VirginGalactic.razor
:
<h2>Virgin Galactic®</h2>
<p>
Virgin Galactic is a registered trademark of
<a href="https://www.virgingalactic.com/">Galactic Enterprises, LLC</a>.
</p>
DynamicComponent1.razor
:
@page "/dynamic-component-1"
<PageTitle>Dynamic Component 1</PageTitle>
<h1>Dynamic Component Example 1</h1>
<p>
<label>
Select your transport:
<select @onchange="OnDropdownChange">
<option value="">Select a value</option>
@foreach (var entry in components.Keys)
{
<option value="@entry">@entry</option>
}
</select>
</label>
</p>
@if (selectedType is not null)
{
<div class="border border-primary my-1 p-1">
<DynamicComponent Type="selectedType" />
</div>
}
@code {
private readonly Dictionary<string, Type> components = new()
{
["Rocket Lab"] = typeof(RocketLab),
["SpaceX"] = typeof(SpaceX),
["ULA"] = typeof(UnitedLaunchAlliance),
["Virgin Galactic"] = typeof(VirginGalactic)
};
private Type? selectedType;
private void OnDropdownChange(ChangeEventArgs e)
{
if ((e.Value is string dropdownValue) && !String.IsNullOrWhiteSpace(dropdownValue))
{
selectedType = components[dropdownValue];
}
else
{
selectedType = null;
}
}
}
RocketLab.razor
:
<h2>Rocket Lab®</h2>
<p>
Rocket Lab is a registered trademark of
<a href="https://www.rocketlabusa.com/">Rocket Lab USA Inc.</a>
</p>
SpaceX.razor
:
<h2>SpaceX®</h2>
<p>
SpaceX is a registered trademark of
<a href="https://www.spacex.com/">Space Exploration Technologies Corp.</a>
</p>
UnitedLaunchAlliance.razor
:
<h2>United Launch Alliance®</h2>
<p>
United Launch Alliance and ULA are registered trademarks of
<a href="https://www.ulalaunch.com/">United Launch Alliance, LLC</a>.
</p>
VirginGalactic.razor
:
<h2>Virgin Galactic®</h2>
<p>
Virgin Galactic is a registered trademark of
<a href="https://www.virgingalactic.com/">Galactic Enterprises, LLC</a>.
</p>
DynamicComponentExample1.razor
:
@page "/dynamiccomponent-example-1"
<h1><code>DynamicComponent</code> Component Example 1</h1>
<p>
<label>
Select your transport:
<select @onchange="OnDropdownChange">
<option value="">Select a value</option>
@foreach (var entry in components.Keys)
{
<option value="@entry">@entry</option>
}
</select>
</label>
</p>
@if (selectedType is not null)
{
<div class="border border-primary my-1 p-1">
<DynamicComponent Type="selectedType" />
</div>
}
@code {
private readonly Dictionary<string, Type> components = new()
{
["Rocket Lab"] = typeof(RocketLab),
["SpaceX"] = typeof(SpaceX),
["ULA"] = typeof(UnitedLaunchAlliance),
["Virgin Galactic"] = typeof(VirginGalactic)
};
private Type? selectedType;
private void OnDropdownChange(ChangeEventArgs e)
{
if ((e.Value is string dropdownValue) && !String.IsNullOrWhiteSpace(dropdownValue))
{
selectedType = components[dropdownValue];
}
else
{
selectedType = null;
}
}
}
RocketLab.razor
:
<h2>Rocket Lab®</h2>
<p>
Rocket Lab is a registered trademark of
<a href="https://www.rocketlabusa.com/">Rocket Lab USA Inc.</a>
</p>
SpaceX.razor
:
<h2>SpaceX®</h2>
<p>
SpaceX is a registered trademark of
<a href="https://www.spacex.com/">Space Exploration Technologies Corp.</a>
</p>
UnitedLaunchAlliance.razor
:
<h2>United Launch Alliance®</h2>
<p>
United Launch Alliance and ULA are registered trademarks of
<a href="https://www.ulalaunch.com/">United Launch Alliance, LLC</a>.
</p>
VirginGalactic.razor
:
<h2>Virgin Galactic®</h2>
<p>
Virgin Galactic is a registered trademark of
<a href="https://www.virgingalactic.com/">Galactic Enterprises, LLC</a>.
</p>
DynamicComponentExample1.razor
:
@page "/dynamiccomponent-example-1"
<h1><code>DynamicComponent</code> Component Example 1</h1>
<p>
<label>
Select your transport:
<select @onchange="OnDropdownChange">
<option value="">Select a value</option>
@foreach (var entry in components.Keys)
{
<option value="@entry">@entry</option>
}
</select>
</label>
</p>
@if (selectedType is not null)
{
<div class="border border-primary my-1 p-1">
<DynamicComponent Type="selectedType" />
</div>
}
@code {
private readonly Dictionary<string, Type> components = new()
{
["Rocket Lab"] = typeof(RocketLab),
["SpaceX"] = typeof(SpaceX),
["ULA"] = typeof(UnitedLaunchAlliance),
["Virgin Galactic"] = typeof(VirginGalactic)
};
private Type? selectedType;
private void OnDropdownChange(ChangeEventArgs e)
{
if ((e.Value is string dropdownValue) && !String.IsNullOrWhiteSpace(dropdownValue))
{
selectedType = components[dropdownValue];
}
else
{
selectedType = null;
}
}
}
In the preceding example:
- An Dictionary<TKey,TValue> is used to manage components to be displayed.
- Names serve as the dictionary keys and are provided as selection options.
- Component types are stored as dictionary values using the
typeof
operator.
Pass parameters
If dynamically-rendered components have component parameters, pass them into the DynamicComponent as an IDictionary<string, object>
. 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<string, object>
.
ComponentMetadata.cs
:
namespace BlazorSample;
public class ComponentMetadata
{
public required Type Type { get; init; }
public required string Name { get; init; }
public Dictionary<string, object> Parameters { get; } = [];
}
public class ComponentMetadata
{
public required Type Type { get; init; }
public required string Name { get; init; }
public Dictionary<string, object> Parameters { get; } = new();
}
public class ComponentMetadata
{
public Type? Type { get; init; }
public string? Name { get; init; }
public Dictionary<string, object> Parameters { get; } = new();
}
The following RocketLabWithWindowSeat
component (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:
RocketLabWithWindowSeat.razor
:
<h2>Rocket Lab®</h2>
<p>
User selected a window seat: @WindowSeat
</p>
<p>
Rocket Lab is a trademark of
<a href="https://www.rocketlabusa.com/">Rocket Lab USA Inc.</a>
</p>
@code {
[Parameter]
public bool WindowSeat { get; set; }
}
<h2>Rocket Lab®</h2>
<p>
User selected a window seat: @WindowSeat
</p>
<p>
Rocket Lab is a trademark of
<a href="https://www.rocketlabusa.com/">Rocket Lab USA Inc.</a>
</p>
@code {
[Parameter]
public bool WindowSeat { get; set; }
}
<h2>Rocket Lab®</h2>
<p>
User selected a window seat: @WindowSeat
</p>
<p>
Rocket Lab is a trademark of
<a href="https://www.rocketlabusa.com/">Rocket Lab USA Inc.</a>
</p>
@code {
[Parameter]
public bool WindowSeat { get; set; }
}
In the following example:
- Only the
RocketLabWithWindowSeat
component's parameter for a window seat (WindowSeat
) receives the value of theWindow Seat
checkbox. - Component names are used as dictionary keys using the
nameof
operator, which returns component names as constant strings. - The dynamically-rendered components are shared components:
- Shown in this article section:
RocketLabWithWindowSeat
(RocketLabWithWindowSeat.razor
) - Components shown in the Example section earlier in this article:
SpaceX
(SpaceX.razor
)UnitedLaunchAlliance
(UnitedLaunchAlliance.razor
)VirginGalactic
(VirginGalactic.razor
)
- Shown in this article section:
DynamicComponent2.razor
:
@page "/dynamic-component-2"
<PageTitle>Dynamic Component 2</PageTitle>
<h1>Dynamic Component Example 2</h1>
<p>
<label>
<input type="checkbox" @bind="windowSeat" @bind:after="HandleWindowSeatChanged" />
Window Seat (Rocket Lab only)
</label>
</p>
<p>
<label>
Select your transport:
<select @onchange="OnDropdownChange">
<option value="">Select a value</option>
@foreach (var c in components)
{
<option value="@c.Key">@c.Value.Name</option>
}
</select>
</label>
</p>
@if (selectedComponent is not null)
{
<div class="border border-primary my-1 p-1">
<DynamicComponent Type="selectedComponent.Type"
Parameters="selectedComponent.Parameters" />
</div>
}
@code {
private Dictionary<string, ComponentMetadata> components =
new()
{
[nameof(RocketLabWithWindowSeat)] = new ComponentMetadata()
{
Type = typeof(RocketLabWithWindowSeat),
Name = "Rocket Lab with Window Seat",
Parameters = { [nameof(RocketLabWithWindowSeat.WindowSeat)] = false }
},
[nameof(VirginGalactic)] = new ComponentMetadata()
{
Type = typeof(VirginGalactic),
Name = "Virgin Galactic"
},
[nameof(UnitedLaunchAlliance)] = new ComponentMetadata()
{
Type = typeof(UnitedLaunchAlliance),
Name = "ULA"
},
[nameof(SpaceX)] = new ComponentMetadata()
{
Type = typeof(SpaceX),
Name = "SpaceX"
}
};
private ComponentMetadata? selectedComponent;
private bool windowSeat;
private void HandleWindowSeatChanged()
{
components[nameof(RocketLabWithWindowSeat)]
.Parameters[nameof(RocketLabWithWindowSeat.WindowSeat)] = windowSeat;
}
private void OnDropdownChange(ChangeEventArgs e)
{
if ((e.Value is string dropdownValue) && !String.IsNullOrWhiteSpace(dropdownValue))
{
selectedComponent = components[dropdownValue];
}
else
{
selectedComponent = null;
}
}
}
DynamicComponentExample2.razor
:
@page "/dynamiccomponent-example-2"
<h1><code>DynamicComponent</code> Component Example 2</h1>
<p>
<label>
<input type="checkbox" @bind="windowSeat" @bind:after="HandleWindowSeatChanged" />
Window Seat (Rocket Lab only)
</label>
</p>
<p>
<label>
Select your transport:
<select @onchange="OnDropdownChange">
<option value="">Select a value</option>
@foreach (var c in components)
{
<option value="@c.Key">@c.Value.Name</option>
}
</select>
</label>
</p>
@if (selectedComponent is not null)
{
<div class="border border-primary my-1 p-1">
<DynamicComponent Type="selectedComponent.Type"
Parameters="selectedComponent.Parameters" />
</div>
}
@code {
private Dictionary<string, ComponentMetadata> components =
new()
{
[nameof(RocketLabWithWindowSeat)] = new ComponentMetadata()
{
Type = typeof(RocketLabWithWindowSeat),
Name = "Rocket Lab with Window Seat",
Parameters = { [nameof(RocketLabWithWindowSeat.WindowSeat)] = false }
},
[nameof(VirginGalactic)] = new ComponentMetadata()
{
Type = typeof(VirginGalactic),
Name = "Virgin Galactic"
},
[nameof(UnitedLaunchAlliance)] = new ComponentMetadata()
{
Type = typeof(UnitedLaunchAlliance),
Name = "ULA"
},
[nameof(SpaceX)] = new ComponentMetadata()
{
Type = typeof(SpaceX),
Name = "SpaceX"
}
};
private ComponentMetadata? selectedComponent;
private bool windowSeat;
private void HandleWindowSeatChanged()
{
components[nameof(RocketLabWithWindowSeat)]
.Parameters[nameof(RocketLabWithWindowSeat.WindowSeat)] = windowSeat;
}
private void OnDropdownChange(ChangeEventArgs e)
{
if ((e.Value is string dropdownValue) && !String.IsNullOrWhiteSpace(dropdownValue))
{
selectedComponent = components[dropdownValue];
}
else
{
selectedComponent = null;
}
}
}
DynamicComponentExample2.razor
:
@page "/dynamiccomponent-example-2"
<h1><code>DynamicComponent</code> Component Example 2</h1>
<p>
<label>
<input type="checkbox" @bind="WindowSeat" />
Window Seat (Rocket Lab only)
</label>
</p>
<p>
<label>
Select your transport:
<select @onchange="OnDropdownChange">
<option value="">Select a value</option>
@foreach (var c in components)
{
<option value="@c.Key">@c.Value.Name</option>
}
</select>
</label>
</p>
@if (selectedComponent is not null)
{
<div class="border border-primary my-1 p-1">
<DynamicComponent Type="selectedComponent.Type"
Parameters="selectedComponent.Parameters" />
</div>
}
@code {
private Dictionary<string, ComponentMetadata> components =
new()
{
[nameof(RocketLabWithWindowSeat)] = new ComponentMetadata()
{
Type = typeof(RocketLabWithWindowSeat),
Name = "Rocket Lab with Window Seat",
Parameters = { [nameof(RocketLabWithWindowSeat.WindowSeat)] = false }
},
[nameof(VirginGalactic)] = new ComponentMetadata()
{
Type = typeof(VirginGalactic),
Name = "Virgin Galactic"
},
[nameof(UnitedLaunchAlliance)] = new ComponentMetadata()
{
Type = typeof(UnitedLaunchAlliance),
Name = "ULA"
},
[nameof(SpaceX)] = new ComponentMetadata()
{
Type = typeof(SpaceX),
Name = "SpaceX"
}
};
private ComponentMetadata? selectedComponent;
private bool windowSeat;
private bool WindowSeat
{
get { return windowSeat; }
set
{
windowSeat = value;
components[nameof(RocketLabWithWindowSeat)]
.Parameters[nameof(RocketLabWithWindowSeat.WindowSeat)] = windowSeat;
}
}
private void OnDropdownChange(ChangeEventArgs e)
{
if ((e.Value is string dropdownValue) && !String.IsNullOrWhiteSpace(dropdownValue))
{
selectedComponent = components[dropdownValue];
}
else
{
selectedComponent = null;
}
}
}
Event callbacks (EventCallback
)
Event callbacks (EventCallback) can be passed to a DynamicComponent in its parameter dictionary.
ComponentMetadata.cs
:
namespace BlazorSample;
public class ComponentMetadata
{
public required Type Type { get; init; }
public required string Name { get; init; }
public Dictionary<string, object> Parameters { get; } = [];
}
public class ComponentMetadata
{
public required Type Type { get; init; }
public required string Name { get; init; }
public Dictionary<string, object> Parameters { get; } = new();
}
public class ComponentMetadata
{
public Type? Type { get; init; }
public string? Name { get; init; }
public Dictionary<string, object> Parameters { get; } = new();
}
Implement an event callback parameter (EventCallback) within each dynamically-rendered component.
RocketLab2.razor
:
<h2>Rocket Lab®</h2>
<p>
Rocket Lab is a registered trademark of
<a href="https://www.rocketlabusa.com/">Rocket Lab USA Inc.</a>
</p>
<button @onclick="OnClickCallback">
Trigger a Parent component method
</button>
@code {
[Parameter]
public EventCallback<MouseEventArgs> OnClickCallback { get; set; }
}
<h2>Rocket Lab®</h2>
<p>
Rocket Lab is a registered trademark of
<a href="https://www.rocketlabusa.com/">Rocket Lab USA Inc.</a>
</p>
<button @onclick="OnClickCallback">
Trigger a Parent component method
</button>
@code {
[Parameter]
public EventCallback<MouseEventArgs> OnClickCallback { get; set; }
}
<h2>Rocket Lab®</h2>
<p>
Rocket Lab is a registered trademark of
<a href="https://www.rocketlabusa.com/">Rocket Lab USA Inc.</a>
</p>
<button @onclick="OnClickCallback">
Trigger a Parent component method
</button>
@code {
[Parameter]
public EventCallback<MouseEventArgs> OnClickCallback { get; set; }
}
SpaceX2.razor
:
<h2>SpaceX®</h2>
<p>
SpaceX is a registered trademark of
<a href="https://www.spacex.com/">Space Exploration Technologies Corp.</a>
</p>
<button @onclick="OnClickCallback">
Trigger a Parent component method
</button>
@code {
[Parameter]
public EventCallback<MouseEventArgs> OnClickCallback { get; set; }
}
<h2>SpaceX®</h2>
<p>
SpaceX is a registered trademark of
<a href="https://www.spacex.com/">Space Exploration Technologies Corp.</a>
</p>
<button @onclick="OnClickCallback">
Trigger a Parent component method
</button>
@code {
[Parameter]
public EventCallback<MouseEventArgs> OnClickCallback { get; set; }
}
<h2>SpaceX®</h2>
<p>
SpaceX is a registered trademark of
<a href="https://www.spacex.com/">Space Exploration Technologies Corp.</a>
</p>
<button @onclick="OnClickCallback">
Trigger a Parent component method
</button>
@code {
[Parameter]
public EventCallback<MouseEventArgs> OnClickCallback { get; set; }
}
UnitedLaunchAlliance2.razor
:
<h2>United Launch Alliance®</h2>
<p>
United Launch Alliance and ULA are registered trademarks of
<a href="https://www.ulalaunch.com/">United Launch Alliance, LLC</a>.
</p>
<button @onclick="OnClickCallback">
Trigger a Parent component method
</button>
@code {
[Parameter]
public EventCallback<MouseEventArgs> OnClickCallback { get; set; }
}
<h2>United Launch Alliance®</h2>
<p>
United Launch Alliance and ULA are registered trademarks of
<a href="https://www.ulalaunch.com/">United Launch Alliance, LLC</a>.
</p>
<button @onclick="OnClickCallback">
Trigger a Parent component method
</button>
@code {
[Parameter]
public EventCallback<MouseEventArgs> OnClickCallback { get; set; }
}
<h2>United Launch Alliance®</h2>
<p>
United Launch Alliance and ULA are registered trademarks of
<a href="https://www.ulalaunch.com/">United Launch Alliance, LLC</a>.
</p>
<button @onclick="OnClickCallback">
Trigger a Parent component method
</button>
@code {
[Parameter]
public EventCallback<MouseEventArgs> OnClickCallback { get; set; }
}
VirginGalactic2.razor
:
<h2>Virgin Galactic®</h2>
<p>
Virgin Galactic is a registered trademark of
<a href="https://www.virgingalactic.com/">Galactic Enterprises, LLC</a>.
</p>
<button @onclick="OnClickCallback">
Trigger a Parent component method
</button>
@code {
[Parameter]
public EventCallback<MouseEventArgs> OnClickCallback { get; set; }
}
<h2>Virgin Galactic®</h2>
<p>
Virgin Galactic is a registered trademark of
<a href="https://www.virgingalactic.com/">Galactic Enterprises, LLC</a>.
</p>
<button @onclick="OnClickCallback">
Trigger a Parent component method
</button>
@code {
[Parameter]
public EventCallback<MouseEventArgs> OnClickCallback { get; set; }
}
<h2>Virgin Galactic®</h2>
<p>
Virgin Galactic is a registered trademark of
<a href="https://www.virgingalactic.com/">Galactic Enterprises, LLC</a>.
</p>
<button @onclick="OnClickCallback">
Trigger a Parent component method
</button>
@code {
[Parameter]
public EventCallback<MouseEventArgs> 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 EventCallbackFactory.Create for the parent callback method,ShowDTMessage
. Note that thethis
keyword isn't supported in C# field initialization, so a C# property is used for the parameter dictionary.
DynamicComponent3.razor
:
@page "/dynamic-component-3"
<PageTitle>Dynamic Component 3</PageTitle>
<h1>Dynamic Component Example 3</h1>
<p>
<label>
Select your transport:
<select @onchange="OnDropdownChange">
<option value="">Select a value</option>
@foreach (var c in Components)
{
<option value="@c.Key">@c.Value.Name</option>
}
</select>
</label>
</p>
@if (selectedComponent is not null)
{
<div class="border border-primary my-1 p-1">
<DynamicComponent Type="selectedComponent.Type"
Parameters="selectedComponent.Parameters" />
</div>
}
<p>
@message
</p>
@code {
private ComponentMetadata? selectedComponent;
private string? message;
private Dictionary<string, ComponentMetadata> Components =>
new()
{
[nameof(RocketLab2)] = new ComponentMetadata()
{
Type = typeof(RocketLab2),
Name = "Rocket Lab",
Parameters = { [nameof(RocketLab2.OnClickCallback)] =
EventCallback.Factory.Create<MouseEventArgs>(this, ShowDTMessage) }
},
[nameof(VirginGalactic2)] = new ComponentMetadata()
{
Type = typeof(VirginGalactic2),
Name = "Virgin Galactic",
Parameters = { [nameof(VirginGalactic2.OnClickCallback)] =
EventCallback.Factory.Create<MouseEventArgs>(this, ShowDTMessage) }
},
[nameof(UnitedLaunchAlliance2)] = new ComponentMetadata()
{
Type = typeof(UnitedLaunchAlliance2),
Name = "ULA",
Parameters = { [nameof(UnitedLaunchAlliance2.OnClickCallback)] =
EventCallback.Factory.Create<MouseEventArgs>(this, ShowDTMessage) }
},
[nameof(SpaceX2)] = new ComponentMetadata()
{
Type = typeof(SpaceX2),
Name = "SpaceX",
Parameters = { [nameof(SpaceX2.OnClickCallback)] =
EventCallback.Factory.Create<MouseEventArgs>(this, ShowDTMessage) }
}
};
private void OnDropdownChange(ChangeEventArgs e)
{
if ((e.Value is string dropdownValue) && !String.IsNullOrWhiteSpace(dropdownValue))
{
selectedComponent = Components[dropdownValue];
}
else
{
selectedComponent = null;
}
}
private void ShowDTMessage(MouseEventArgs e) =>
message = $"The current DT is: {DateTime.Now}.";
}
DynamicComponentExample3.razor
:
@page "/dynamiccomponent-example-3"
<h1><code>DynamicComponent</code> Component Example 3</h1>
<p>
<label>
Select your transport:
<select @onchange="OnDropdownChange">
<option value="">Select a value</option>
@foreach (var c in Components)
{
<option value="@c.Key">@c.Value.Name</option>
}
</select>
</label>
</p>
@if (selectedComponent is not null)
{
<div class="border border-primary my-1 p-1">
<DynamicComponent Type="selectedComponent.Type"
Parameters="selectedComponent.Parameters" />
</div>
}
<p>
@message
</p>
@code {
private ComponentMetadata? selectedComponent;
private string? message;
private Dictionary<string, ComponentMetadata> Components =>
new()
{
[nameof(RocketLab2)] = new ComponentMetadata()
{
Type = typeof(RocketLab2),
Name = "Rocket Lab",
Parameters = { [nameof(RocketLab2.OnClickCallback)] =
EventCallback.Factory.Create<MouseEventArgs>(this, ShowDTMessage) }
},
[nameof(VirginGalactic2)] = new ComponentMetadata()
{
Type = typeof(VirginGalactic2),
Name = "Virgin Galactic",
Parameters = { [nameof(VirginGalactic2.OnClickCallback)] =
EventCallback.Factory.Create<MouseEventArgs>(this, ShowDTMessage) }
},
[nameof(UnitedLaunchAlliance2)] = new ComponentMetadata()
{
Type = typeof(UnitedLaunchAlliance2),
Name = "ULA",
Parameters = { [nameof(UnitedLaunchAlliance2.OnClickCallback)] =
EventCallback.Factory.Create<MouseEventArgs>(this, ShowDTMessage) }
},
[nameof(SpaceX2)] = new ComponentMetadata()
{
Type = typeof(SpaceX2),
Name = "SpaceX",
Parameters = { [nameof(SpaceX2.OnClickCallback)] =
EventCallback.Factory.Create<MouseEventArgs>(this, ShowDTMessage) }
}
};
private void OnDropdownChange(ChangeEventArgs e)
{
if ((e.Value is string dropdownValue) && !String.IsNullOrWhiteSpace(dropdownValue))
{
selectedComponent = Components[dropdownValue];
}
else
{
selectedComponent = null;
}
}
private void ShowDTMessage(MouseEventArgs e) =>
message = $"The current DT is: {DateTime.Now}.";
}
DynamicComponentExample3.razor
:
@page "/dynamiccomponent-example-3"
<h1><code>DynamicComponent</code> Component Example 3</h1>
<p>
<label>
Select your transport:
<select @onchange="OnDropdownChange">
<option value="">Select a value</option>
@foreach (var c in Components)
{
<option value="@c.Key">@c.Value.Name</option>
}
</select>
</label>
</p>
@if (selectedComponent is not null)
{
<div class="border border-primary my-1 p-1">
<DynamicComponent Type="selectedComponent.Type"
Parameters="selectedComponent.Parameters" />
</div>
}
<p>
@message
</p>
@code {
private ComponentMetadata? selectedComponent;
private string? message;
private Dictionary<string, ComponentMetadata> Components =>
new()
{
[nameof(RocketLab2)] = new ComponentMetadata()
{
Type = typeof(RocketLab2),
Name = "Rocket Lab",
Parameters = { [nameof(RocketLab2.OnClickCallback)] =
EventCallback.Factory.Create<MouseEventArgs>(this, ShowDTMessage) }
},
[nameof(VirginGalactic2)] = new ComponentMetadata()
{
Type = typeof(VirginGalactic2),
Name = "Virgin Galactic",
Parameters = { [nameof(VirginGalactic2.OnClickCallback)] =
EventCallback.Factory.Create<MouseEventArgs>(this, ShowDTMessage) }
},
[nameof(UnitedLaunchAlliance2)] = new ComponentMetadata()
{
Type = typeof(UnitedLaunchAlliance2),
Name = "ULA",
Parameters = { [nameof(UnitedLaunchAlliance2.OnClickCallback)] =
EventCallback.Factory.Create<MouseEventArgs>(this, ShowDTMessage) }
},
[nameof(SpaceX2)] = new ComponentMetadata()
{
Type = typeof(SpaceX2),
Name = "SpaceX",
Parameters = { [nameof(SpaceX2.OnClickCallback)] =
EventCallback.Factory.Create<MouseEventArgs>(this, ShowDTMessage) }
}
};
private void OnDropdownChange(ChangeEventArgs e)
{
if ((e.Value is string dropdownValue) && !String.IsNullOrWhiteSpace(dropdownValue))
{
selectedComponent = Components[dropdownValue];
}
else
{
selectedComponent = null;
}
}
private void ShowDTMessage(MouseEventArgs e) =>
message = $"The current DT is: {DateTime.Now}.";
}
Avoid catch-all parameters
Avoid the use of catch-all parameters. If catch-all parameters are used, every explicit parameter on DynamicComponent effectively is a reserved word that you can't pass to a dynamic child. Any new parameters passed to DynamicComponent 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. SpaceX is a registered trademark of Space Exploration Technologies Corp. United Launch Alliance and ULA are registered trademarks of United Launch Alliance, LLC. Virgin Galactic is a registered trademark of Galactic Enterprises, LLC.
Additional resources
ASP.NET Core
Feedback
https://aka.ms/ContentUserFeedback.
Coming soon: Throughout 2024 we will be phasing out GitHub Issues as the feedback mechanism for content and replacing it with a new feedback system. For more information see:Submit and view feedback for