Based on the hierarchical model in Blazor, it is trivial to call a method in a parent component from within a child component. But what if you want to do the opposite? A use case for this type of scenario might be a data entry form where a variety of different sections are rendered as child components; however, there might only be a single Submit button for the form which is inside the parent component. So when a user clicks Submit the application may want to call a method in each child component to perform validation or even save the information to a database. Let 's explore a few different options to accomplish our goal.
First, let 's create a very simple child component which has a method named "Save" that we want to invoke when a user clicks a button on a parent component.
Child.razor
<br />@message<br />
@code {
string message = "";
public void Save()
{
message = "Child Component Save Method Invoked!!";
StateHasChanged();
}
}
Now we will create a parent component which contains a button and calls the Save method in the child component. This option is the simplest to implement and will be the most common scenario for developers. I refer to this as the "static" option because it assumes that a child component is statically embedded in a parent component during development.
Parent1.razor
@page "/parent1"
<button class="btn btn-primary" @onclick="@Save">Invoke Save Method In Child Component Statically</button>
<Child @ref="child" @ref:suppressField />
@code {
Child child;
private void Save()
{
child.Save();
}
}
But what if we wanted to dynamically inject the child component into the parent component? This is common scenario in applications which offer a high level of customization or personalization. In these cases the user interface is generated at run-time based on configuration provided by the end user.
@page "/parent2"
<button class="btn btn-primary" @onclick="@Save">Invoke Save Method In Child Component Dynamically</button>
@DynamicComponent
@code {
string ChildComponentName = "WebApplication1.Pages.Child";
RenderFragment DynamicComponent { get; set; }
object child;
protected override void OnInitialized()
{
DynamicComponent = builder =>
{
Type moduleType = Type.GetType(ChildComponentName);
if (moduleType != null)
{
builder.OpenComponent(0, moduleType);
builder.AddComponentReferenceCapture(1, inst => { child = Convert.ChangeType(inst, moduleType); });
builder.CloseComponent();
}
};
}
private void Save()
{
Type.GetType(ChildComponentName).GetMethod("Save").Invoke(child, null);
}
}
The above logic is a lot more verbose, but it is also more flexible. Using some of the more primitive Blazor construction methods, it dynamically injects the child component into the parent and saves a reference to it so that it can invoke its Save method using reflection.
In this blog we have explored a few different options for calling a method in a child component from a parent component in Blazor. The dynamic option took some effort to figure out, so I hope this blog saves some time for other developers. More information on this topic can be found on this Gist by Steve Sanderson https://github.com/aspnet/Blazor/pull/685