Download Sample Code

Parameter

In Blazor, passing parameters between components is a fundamental technique for component communication, particularly from parent to child. This tutorial will guide you through passing a parameter to another component and then receiving the update notification when the parameter changes. We will cover:

  • Passing a parameter to a child component.
  • What is parameter change notification?
  • Passing a parameter and notifying the parent with @bind-*.
  • Advanced techniques with @bind-*.
  • Passing a parameter and notifying the parent with EventCallback.

Passing a Parameter to a Child Component

  1. Declare the parameter in the child using the [Parameter] attribute:
<div>
    <h3>Child</h3>
    <div>Value: @Value</div>
</div>

@code {
    [Parameter]
    public int Value { get; set; }
}
  1. From the parent, pass the parameter to the child:
<div>
    <h3>Parent</h3>
    <div>Value: @ParentValue</div>
    <button @onclick="ChangeRandomValue" type="button">Change Value</button>
    <Child Value="ParentValue" />
</div>

@code {
    public int ParentValue { get; set; } = 0;

    public void ChangeRandomValue()
    {
        var random = new Random();
        ParentValue = random.Next(0, 100);
    }
}

Any changes from the parent component will affect the child component accordingly.

Developers can enforce the requirement of a parameter using the [EditorRequired] attribute:

@code {
    [EditorRequired]
    [Parameter]
    public int Value { get; set; }
}

If the parent component omits the Value parameter when using the child component, Visual Studio displays a warning or error message during development.

editor-required-example.webp


What is Parameter Change Notification

When a parameter is passed from the parent to the child component, it actually creates 2 copies - one at the parent and one at the child component. Because they are different properties, any changes to the property in the child component will not reflect in the parent component unless a notification is made to the parent component. Consider the following example:

We have the following child component:

<div>
    <h3>Child</h3>
    <div>Value: @Value</div>
    <button @onclick="ChangeRandomValue" type="button">Change Value</button>
</div>

@code {
    [Parameter]
    public int Value { get; set; }

    public void ChangeRandomValue()
    {
        var random = new Random();
        Value = random.Next(0, 100);
    }
}

And the parent component:

<div>
    <h3>Parent</h3>
    <div>Value: @ParentValue</div>
    <button @onclick="ChangeRandomValue" type="button">Change Value</button>
    <Child Value="ParentValue" />
</div>

@code {
    public int ParentValue { get; set; } = 0;

    public void ChangeRandomValue()
    {
        var random = new Random();
        ParentValue = random.Next(0, 100);
    }
}

In this example, you can see both values at the parent and the child component. When the "Change Value" button in the child component is clicked, the value in the child component changes but not in the parent component.

To make the parent acknowledge the new value from the child component, a notification mechanism must be implemented. There are 2 mechanisms that provide the notification back to the parent: the bind keyword and EventCallback.

  • The bind keyword is the minimal code, and changes are notified automatically.
  • EventCallback requires more code setup but allows developers to notify changes when needed.

Passing a Parameter and Notifying the Parent With @bind-*

To implement the binding mechanism, in the child component, declare an additional property with type EventCallback<T> where T is the data type of the property you want to notify. The name of this EventCallback<T> must be the name of the property with the suffix Changed. For example, if the property you want to notify is int Value, then there must be a property EventCallback<int> ValueChanged with the [Parameter] attribute:

<div>
    <h3>Child</h3>
    <div>Value: @Value</div>
    <button @onclick="ChangeRandomValue" type="button">Change Value</button>
</div>

@code {
    [Parameter]
    public int Value { get; set; }

    [Parameter]
    public EventCallback<int> ValueChanged { get; set; }
}

When the value changes in the child component, it is not required to change the property of the child component as it will cause overhead since the child component will be re-rendered by the parent component. Instead, just use the EventCallback<T> to notify the parent about the changes:

public void ChangeRandomValue()
{
    var random = new Random();
    // Should not change the value directly in the child component. Notify the parent and let the child component render the new value
    // Value = random.Next(0, 100);
    // Notify the parent component about the change
    ValueChanged.InvokeAsync(random.Next(0, 100));
}

With this in mind, here is the full code of the child component:

<div>
    <h3>Child</h3>
    <div>Value: @Value</div>
    <button @onclick="ChangeRandomValue" type="button">Change Value</button>
</div>

@code {
    [Parameter]
    public int Value { get; set; }

    [Parameter]
    public EventCallback<int> ValueChanged { get; set; }

    public void ChangeRandomValue()
    {
        var random = new Random();
        // Should not change the value directly in the child component. Notify the parent and let the child component render the new value
        // Value = random.Next(0, 100);
        // Notify the parent component about the change
        ValueChanged.InvokeAsync(random.Next(0, 100));
    }
}

The parent component uses @bind-<ParameterName> to pass the parameter:

<div>
    <h3>Parent</h3>
    <div>Value: @ParentValue</div>
    <Child @bind-Value="ParentValue" />
</div>

@code {
    public int ParentValue { get; set; } = 0;
}
Note: With every parameter in the child component, you need an additional property declared. With this approach, each change from the child component will notify the parent component, even if there may still be changes from other properties of the child component. When it is costly to re-render the parent, consider using the EventCallback approach to notify for the whole component’s changes instead of each property in the component.

Advanced Techniques with @bind-*

When passing a parameter to the child component, developers can combine modifiers get, set, and after with the bind keyword to inject logic when getting the parameter value (get), when setting the parameter value (set), or after the parameter value has been set (after). Consider the following changes count example:

<div>
    <h3>Parent</h3>
    <div>Value: @_parentValue</div>
    <div>Changes count: @ChangesCount</div>
    <Child @bind-Value:get="_parentValue" />
    <Child @bind-Value:get="_parentValue" @bind-Value:set="SetParentValue" />
    <Child @bind-Value:get="_parentValue" @bind-Value:set="SetParentValueAsync" />
    <Child @bind-Value:get="_parentValue" @bind-Value:after="AfterSetParentValue" />
    <Child @bind-Value:get="_parentValue" @bind-Value:after="AfterSetParentValueAsync" />
</div>

@code {
    private int _parentValue = 0;
    public int ChangesCount { get; set; } = 0;

    public void SetParentValue(int newValue)
    {
        Console.WriteLine("SetParentValue executed");
        _parentValue = newValue;
        ChangesCount++;
    }

    public async Task SetParentValueAsync(int newValue)
    {
        await Task.Delay(1000); // Simulate some async work
        Console.WriteLine("SetParentValueAsync executed");
        _parentValue = newValue;
        ChangesCount++;
    }

    public void AfterSetParentValue()
    {
        Console.WriteLine("AfterSetParentValue executed");
        _parentValue = _parentValue * 100;
        ChangesCount++;
    }

    public async Task AfterSetParentValueAsync()
    {
        await Task.Delay(1000); // Simulate some async work
        Console.WriteLine("AfterSetParentValueAsync executed");
        _parentValue = _parentValue * 100;
        ChangesCount++;
    }
}
Note: When using asynchronous logic in binding modifiers like @bind-Value:set or @bind-Value:after (e.g., SetParentValueAsync or AfterSetParentValueAsync with a 1 second delay), a lock-screen feature should be implemented. This is critical because the UI may update without user interaction after a delay, potentially confusing users, as demonstrated in the example.

Passing a Parameter and Notifying the Parent with EventCallback

Notifying a parent component of multiple parameter changes in a child can lead to performance issues if done per parameter, as each notification triggers a re-render. Using a single EventCallback to handle all changes at once is a more efficient approach.

  1. Define the event argument.
public record ChildComponentChangeArgument(int Value1, int Value2, int Value3);
  1. Declare the parameters and an EventCallback<ChildComponentChangeArgument> in the child component.
@code {
    [Parameter]
    public int Value1 { get; set; }

    [Parameter]
    public int Value2 { get; set; }

    [Parameter]
    public int Value3 { get; set; }

    [Parameter]
    public EventCallback<ChildComponentChangeArgument> ComponentUpdated { get; set; }
}
  1. When updating those parameters in batch, use the EventCallback<T> to notify the parent component:
public void ChangeRandomValue()
{
    var random = new Random();
    int newValue1 = random.Next(0, 100);
    int newValue2 = random.Next(0, 100);
    int newValue3 = random.Next(0, 100);
    // Notify the parent component about the change
    ComponentUpdated.InvokeAsync(new(newValue1, newValue2, newValue3));
}

With that said, this is the full code of the child component:

<div>
    <h3>Child</h3>
    <div>Value1: @Value1</div>
    <div>Value2: @Value2</div>
    <div>Value3: @Value3</div>
    <button @onclick="ChangeRandomValue" type="button">Change Value</button>
</div>

@code {
    [Parameter]
    public int Value1 { get; set; }

    [Parameter]
    public int Value2 { get; set; }

    [Parameter]
    public int Value3 { get; set; }

    [Parameter]
    public EventCallback<ChildComponentChangeArgument> ComponentUpdated { get; set; }

    public void ChangeRandomValue()
    {
        var random = new Random();
        int newValue1 = random.Next(0, 100);
        int newValue2 = random.Next(0, 100);
        int newValue3 = random.Next(0, 100);
        // Notify the parent component about the change
        ComponentUpdated.InvokeAsync(new(newValue1, newValue2, newValue3));
    }
}
  1. In the parent component, pass the parameters as usual, and also pass the event handler.
<div>
    <h3>Parent</h3>
    <div>Value1: @ParentValue1</div>
    <div>Value2: @ParentValue2</div>
    <div>Value3: @ParentValue3</div>
    <Child Value1="ParentValue1" Value2="ParentValue2" Value3="ParentValue3" ComponentUpdated="OnComponentChanged" />
</div>

@code {
    public int ParentValue1 { get; set; } = 0;
    public int ParentValue2 { get; set; } = 0;
    public int ParentValue3 { get; set; } = 0;

    public void OnComponentChanged(ChildComponentChangeArgument argument)
    {
        ParentValue1 = argument.Value1;
        ParentValue2 = argument.Value2;
        ParentValue3 = argument.Value3;
    }
}
BLAZOR SCHOOL
Designed and built with care by our dedicated team, with contributions from a supportive community. We strive to provide the best learning experience for our users.
Docs licensed CC-BY-SA-4.0
Copyright © 2021-2025 Blazor School
An unhandled error has occurred. Reload 🗙