Understand Cascading Parameters and Cascading Values in Blazor

In the previous article
we discussed arbitrary parameters and attribute splatting. Now it's time to
understand one more aspect of passing values to a Blazor component from the
external world - Cascading Parameters and Cascading Values. In all the examples
discussed so far, we explicitly set a parameter value from the parent component.
This means if we want to pass a value to, say, ten components, we must set a
parameter of all the ten components. In such cases Cascading Parameters and
Cascading Values come handy. The remainder of this article discusses how.
Open the same Blazor project you created in the previous article. Recollect
that we have already created Message component in the project. For the sake of
this article, we will create two components - UpperCaseMessage and
LowerCaseMessage - to demonstrate our point of discussion
So, add two Razor Components namely UpperCaseMessage.razor and
LowerCaseMessage.razor to the project. These are quite simple components that
display a specified message in uppercase and lowercase letters respectively. For
the sake of clear understanding we will first build them with normal parameters
and then convert them to use cascading parameters.
The UpperCaseMessage.razor looks like this:
<h2>@Value.ToUpper()</h2>
@code {
[Parameter]
public string Value { get; set; }
}
The LowerCaseMessage.razor looks like this:
<h2>@Value.ToLower()</h2>
@code {
[Parameter]
public string Value { get; set; }
}
On the Index.razor parent component you can use them components as follows:
<UpperCaseMessage Value="Hello Universe!">
</UpperCaseMessage>
<LowerCaseMessage Value="Hello Universe!">
</LowerCaseMessage>
And the outcome will be similar to the following figure:

Now let's change the components to use cascading parameters.
Modify UpperCaseMessage component as shown below:
<h2>@Value.ToUpper()</h2>
@code {
[CascadingParameter]
public string Value { get; set; }
}
And LowerCaseMessage component as shown below:
<h2>@Value.ToLower()</h2>
@code {
[CascadingParameter]
public string Value { get; set; }
}
As you can see the Value property is now decorated with [CascadingParameter]
attribute.
To set the Value cascading parameter from the Index.razor parent component
you will use Blazor's CascadingValue component.
<CascadingValue Value="@MessageText">
<UpperCaseMessage></UpperCaseMessage>
<LowerCaseMessage></LowerCaseMessage>
</CascadingValue>
@code{
private string MessageText = "Hello Universe!";
}
The CascadingValue component indicates a value that is passed to all its
child components. In this case the value stored in the MessageText string
variable (Hello Universe!) is passed to the child components <UpperCaseMessage>
and <LowerCaseMessage>.
If you run the application again the results will be identical to the
previous example.
Now let's pass one more value to the UpperCaseMessage and LowerCaseMessage
components.
<CascadingValue Value="@MessageText">
<CascadingValue Value="@ShowLength">
<UpperCaseMessage></UpperCaseMessage>
<LowerCaseMessage></LowerCaseMessage>
</CascadingValue>
</CascadingValue>
@code{
private string MessageText = "Hello Universe!";
private bool ShowLength = true;
}
As you can see from the above code, we now have two nested <CascadingValue>
components. The outer instance passes MessageText and the inner instance passes
ShowLength boolean value. We will use this boolean value to display (or not
diasplay) the length of the message inside the UpperCaseMessage and
LowerCaseMessage components.
So, open UpperCaseMessage.razor and make the following change.
<h2>@Value.ToUpper()</h2>
@if(LengthIndicator)
{
<h3>(@Value.Length characters)</h3>
}
@code {
[CascadingParameter]
public string Value { get; set; }
[CascadingParameter]
public bool LengthIndicator { get; set; }
}
As you can see, we added one more [CascadingParameter] property called
LengthIndicator. You might be wondering how Blazor maps the cascading values to
the cascading parameters. Blazor does so based on data type of the value. In
this example, MessageText is a string value and hence it is mapped to the Value
string property. Similarly, ShowLength is a boolean value and it is mapped to
the LengthIndicator boolean property.
We use the LengthIndicator property in the component markup to output the
length of the message.
Modify LowerCase.razor on similar lines.
<h2>@Value.ToLower()</h2>
@if (LengthIndicator)
{
<h3>(@Value.Length characters)</h3>
}
@code {
[CascadingParameter]
public string Value { get; set; }
[CascadingParameter]
public bool LengthIndicator { get; set; }
}
Now run the application again. Your output should look like this:

Now let's take this concept one step further. We will pass third cascading
value to both the components as shown below:
<CascadingValue Value="@MessageText" Name="MsgText">
<CascadingValue Value="@ShowLength">
<CascadingValue Value="@MessageTitle" Name="MsgTitle">
<UpperCaseMessage></UpperCaseMessage>
<LowerCaseMessage></LowerCaseMessage>
</CascadingValue>
</CascadingValue>
</CascadingValue>
@code{
private string MessageText = "Hello Universe!";
private bool ShowLength = true;
private string MessageTitle =
"This is a message title from parent.";
}
This time we want to pass three values to both the components. Two of them -
MessageText and MessageTitle - are string values whereas ShowLength is boolean.
Since there are two string values the Blazor's mapping based on data type might
give unexpected results. The safest way is to explicitly assign some Name to the
cascading value being passed. Therefore, we named MessageText value as MsgText
and MessageTitle as MsgTitle.
Now open UpperCaseMessage component and add this code:
<h2 title="@Title">@Value.ToUpper()</h2>
@if(LengthIndicator)
{
<h3>(@Value.Length characters)</h3>
}
@code {
[CascadingParameter(Name = "MsgText")]
public string Value { get; set; }
[CascadingParameter]
public bool LengthIndicator { get; set; }
[CascadingParameter(Name = "MsgTitle")]
public string Title { get; set; }
}
Now the Value cascading parameter is explicitly mapped to the MsgText
cascading value via the Name property of [CascadingParameter] attribute. And
Title cascading property is mapped to MsgTitle cascading value. The Title
property is used to set the title attribute of <h2> element.
Make similar changes to the LowerCaseMessage.razor component:
<h2 title="@Title">@Value.ToLower()</h2>
@if (LengthIndicator)
{
<h3>(@Value.Length characters)</h3>
}
@code {
[CascadingParameter(Name = "MsgText")]
public string Value { get; set; }
[CascadingParameter]
public bool LengthIndicator { get; set; }
[CascadingParameter(Name = "MsgTitle")]
public string Title { get; set; }
}
Running the application after making these changes will produce this output:

Let's conclude this article by observing the state change behavior of
cascading values.
We will add a button to our parent component (Index.razor). Clicking on the
button will change the values of MessageText, ShowLength, and MessageTitle
properties.
<button @onclick="ChangeCascadingValues">
Change Cascading Parameters
</button>
And the ChangeCascadingValues() event handler method looks like this:
private void ChangeCascadingValues()
{
MessageText = "Hello Galaxy!";
MessageTitle = "Message title changed.";
ShowLength = false;
}
Run the application again and click on the newly added button. You will find
that the child components reflect the changed values.

This means Blazor is continuously monitoring the cascading values and updates
the child components whenever they change. This constant monitoring can be
turned off if you are concerned about the performance. Of course, after
disabling that the child components won't reflect the changed state.
You disable the monitoring using IsFixed property of the <CascadingValue>
component. The following code fragment shows how:
<CascadingValue Value="@MessageText"
Name="MsgText" IsFixed="true">
<CascadingValue Value="@ShowLength" IsFixed="true">
<CascadingValue Value="@MessageTitle"
Name="MsgTitle" IsFixed="true">
<UpperCaseMessage></UpperCaseMessage>
<LowerCaseMessage></LowerCaseMessage>
</CascadingValue>
</CascadingValue>
</CascadingValue>
We set IsFixed to true for all the three cascading values indicating that the
values are fixed (and don't need change monitoring).
After making this change run the application again and click on the button.
This time the child components won't reflect any change.
That's it for now! Keep coding!!