Introduction
Blazor is a new framework built by Microsoft for creating interactive client-side web UI with .NET codebase. We can write both client-side and server-side code in C#.NET itself. I have already written five articles about Blazor server on C# Corner. Please refer to below articles for more basics about Blazor framework.
- Create A Simple Blazor Server Application With .NET Core 3.0
- Create a Single Page App with Blazor Server and Entity Framework Core 3.0
- Combine SQL-DB and MongoDB in Same Blazor App
- Create A Blazor Server SPA with Dapper
- Combine ADO.NET, EF Core and Dapper in Same Blazor App
Components are implemented in Razor component files (. razor) using a combination of C# and HTML mark-up. A component in Blazor is formally referred to as a Razor component.
We can create a child component and reuse in another component. We will share data between these components very easily. We will create a custom textbox as child component. This custom textbox will show the current character count in the textbox and will restrict the total number of characters, if needed. I will explain all the actions step by step.
Create Blazor application in Visual Studio 2019
We can define the html mark-up in the component.
- <div class="float-right">
- <i>Total Characters : @TextLength/@LengthString</i>
- </div>
- <div class="form-group row mb-2">
- <label class="col-md-3 col-form-label"
- for="Name">@FieldName</label>
- <div class="col-md7">
- <input class="form-control"
- type="text"
- placeholder="@FieldName" value="@Value" @οninput="OnValueChanged" maxlength="@MaxLength" />
- </div>
- </div>
We can add the C# code also inside the @code block.
- @code {
- [Parameter]
- public string Value { get; set; }
- [Parameter]
- public string FieldName { get; set; }
- [Parameter]
- public int MaxLength { get; set; } = -1;
- [Parameter]
- public EventCallback<string> ValueChanged { get; set; }
- string LengthString;
- int TextLength;
- protected override void OnInitialized()
- {
- TextLength = Value.Length;
- LengthString = (MaxLength == -1) ? "Unlimited" : MaxLength.ToString();
- }
- private Task OnValueChanged(ChangeEventArgs e)
- {
- Value = e.Value.ToString();
- TextLength = Value.Length;
- return ValueChanged.InvokeAsync(Value);
- }
- }
We have defined three parameters properties “Value”, “FieldName” and “MaxLength”.
FieldName is used for displaying field name and placeholder value in the custom textbox. MaxLength is used to restrict maximum characters limit in custom textbox, if needed. FieldName and MaxLength properties in Blazor act as @Input decorator in Angular. These properties are used to share data from parent component to child component. Value property acts as @Output decorator in Angular. This will be used for sharing data back from child component to parent component. In Angular, we use EventEmitter along with Output decorators to share data from child to parent component. In Blazor, we use “EventCallback” parameter to emit value from child component to parent component. Please note, “Changed” suffix is added to the value property parameter. This is the default convention used in Blazor.
We have created a “OnValueChanged” method and bind with “@oninput” attribute of input control in html mark-up.
CustomTextbox.razor
- <div class="float-right">
- <i>Total Characters : @TextLength/@LengthString</i>
- </div>
- <div class="form-group row mb-2">
- <label class="col-md-3 col-form-label"
- for="Name">@FieldName</label>
- <div class="col-md7">
- <input class="form-control"
- type="text"
- placeholder="@FieldName" value="@Value" @οninput="OnValueChanged" maxlength="@MaxLength" />
- </div>
- </div>
- @code {
- [Parameter]
- public string Value { get; set; }
- [Parameter]
- public string FieldName { get; set; }
- [Parameter]
- public int MaxLength { get; set; } = -1;
- [Parameter]
- public EventCallback<string> ValueChanged { get; set; }
- string LengthString;
- int TextLength;
- protected override void OnInitialized()
- {
- TextLength = Value.Length;
- LengthString = (MaxLength == -1) ? "Unlimited" : MaxLength.ToString();
- }
- private Task OnValueChanged(ChangeEventArgs e)
- {
- Value = e.Value.ToString();
- TextLength = Value.Length;
- return ValueChanged.InvokeAsync(Value);
- }
- }
We can add this child component inside a parent component. We can create new parent component.
ParentComponent.razor
- @page "/parentcomponent"
- <CustomTextbox @bind-Value="name" FieldName="Name" MaxLength="20" />
- <CustomTextbox @bind-Value="address" FieldName="Address" />
- @code {
- string name = "Sarath Lal";
- string address = "Kakkanad";
- }
We have added two custom textbox child components inside this parent component. “@bind-{parametername}” is used for binding child component field with parent component field. Here, “Value” is the field name in the child component. So that, we used this as “@bind-Value”. We can pass these two input parameters “FieldName” and “MaxLength” from parent component. I have not passed MaxLength property for second child component. Hence, the default value -1 will be assigned to this component in run time.
We can modify the shared component “NavMenu” to add a navigation to parent component.
NavMenu.razor
- <div class="top-row pl-4 navbar navbar-dark">
- <a class="navbar-brand" href="">BlazorReusableComponent</a>
- <button class="navbar-toggler" @οnclick="ToggleNavMenu">
- <span class="navbar-toggler-icon"></span>
- </button>
- </div>
- <div class="@NavMenuCssClass" @οnclick="ToggleNavMenu">
- <ul class="nav flex-column">
- <li class="nav-item px-3">
- <NavLink class="nav-link" href="" Match="NavLinkMatch.All">
- <span class="oi oi-home" aria-hidden="true"></span> Home
- </NavLink>
- </li>
- <li class="nav-item px-3">
- <NavLink class="nav-link" href="counter">
- <span class="oi oi-plus" aria-hidden="true"></span> Counter
- </NavLink>
- </li>
- <li class="nav-item px-3">
- <NavLink class="nav-link" href="fetchdata">
- <span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
- </NavLink>
- </li>
- <li class="nav-item px-3">
- <NavLink class="nav-link" href="parentcomponent">
- <span class="oi oi-list-rich" aria-hidden="true"></span> Parent Component
- </NavLink>
- </li>
- </ul>
- </div>
- @code {
- bool collapseNavMenu = true;
- string NavMenuCssClass => collapseNavMenu ? "collapse" : null;
- void ToggleNavMenu()
- {
- collapseNavMenu = !collapseNavMenu;
- }
- }
We can run the application.
You can notice that, a new “Parent Component” link is appeared in the menu. You can click that link to see the parent component.
We have defined two custom textbox components inside the parent component. For the first textbox, we have given 20-character limit and for second component, no character limit is given. So that, you can enter unlimited characters in second textbox. The total characters count is also visible in the screen.
Conclusion
In this post, we have created a reusable child component in Blazor and easily used in another parent component. We have shared the data from parent component to child component and vice versa also.