ASP.NET Core 5.0 : MVC, Razor Pages, Web API, EF Core, Blazor, Design Patterns, and more. Private online coaching for software developers. Click here for more details.

Use Arbitrary Parameters and Attribute Splatting in Blazor

In the previous article we discussed how parameters can be passed to Blazor component. In the examples discussed so far you created a fixed number of parameters (for example, Value parameter of the Message component) and assigned them some value from the parent component (Index.razor in our examples). What if you want to pass arbitrary number of parameters to a component? That means you won't know the exact parameters at development time. The parent component (Index.razor) will set arbitrary parameters on a child component (Message.razor) when the child component is used. This article explores how this can be accomplished. In the process you will also learn about what is known as Attribute Splatting.

Let's get going!

Open the same Blazor Server project you created in the previous article. Currently, the Message component contains just a single parameter Value:

[Parameter]
public string Value { get; set; }

Add one more parameter called ArbitraryAttributeDictionary as shown below:

[Parameter(CaptureUnmatchedValues =true)]
public Dictionary<string, object> 
ArbitraryAttributeDictionary { get; set; }

Here, the ArbitraryAttributeDictionary property is a Dictionary. The keys of the Dictionary will be strings whereas the values will be objects. The ArbitraryAttributeDictionary property is decorated with [Parameter] attribute. This time we also set the CaptureUnmatchedValues property of the Parameter attribute to true. This indicates that any attributes set by the parent component that do not have matching parameter properties in the child component will be made available in the ArbitraryAttributeDictionary.

Before we actually use the arbitrary attributes passed in the ArbitraryAttributeDictionary, let's first see the usage syntax of the newly added parameter.

Open Index.razor parent component and place the <Message> component like this:

<Message id="div1" 
         class="divClass" 
         title="This is sample <DIV> element."
         Value="Hello World!">
</Message>

Notice this markup carefully. It sets three attributes that do not have any matching parameters - id, class, and title. It also sets the Value attribute that maps to the Value paremeter.

So far so good.

Now that the parent is passing four parameters to the Message component, let's put these parameters to use inside the Message component.

Go back to the Message.razor and place a <div> element as shown below:

<div @attributes="ArbitraryAttributeDictionary">
    @Value
</div>

Here, the @attributes directive points to the ArbitraryAttributeDictionary dictionary. It then adds the key-value pairs from the dictionary to the <div> element. This is called Attribute Splatting. So, at runtime the <div> element will look like this:

<div id="div1" 
     class="divClass" 
     title="This is sample <DIV> element.">
Hello World!
</div>

Where do we put the divClass CSS class? You can attach a component specific CSS style sheet file and add the divClass there.

To do so, add a new Style Sheet named Message.razor.css

Because of this particular naming convention, it will appear nested in the Solution Explorer.

Now add the following CSS class to the newly added style sheet.

.divClass {
    border:5px solid red;
    padding:5px;
    background-color:yellow;
    width:60%;
    font-size:20px;
    font-weight:bold;
}

Run the application and notice how the <div> is rendered on the page.

As you can see the <div> has correctly picked the class and title attribute values.

It should be noted that attribute splatting can be used independently of arbitrary attributes. For example, you can create a Dictionary parameter without setting CaptureUnmatchedValues property and then set that parameter explicitly from the parent component (like you did with the Value parameter).

Consider the following parameter added to the Message component.

[Parameter]
public Dictionary<string,object> AttributeDictionary 
{ get; set; }

Here, AttributeDictionary is a normal parameter that stores key-value Dictionary.

You can set this parameter from the Index.razor parent component as follows:

<Message AttributeDictionary="objDictionary" 
         Value="Hello World!">
</Message>

The AttributeDictionary attribute is set to a Dictionary object named objDictionary containing required key-value pairs. The objDictionary gets created in the Index.razor @code block:

@code{
    Dictionary<string, object> objDictionary = 
new Dictionary<string, object>()
    {
        {"id","div1" },
        {"class","divClass" },
        {"title","This is sample <DIV> element." }
    };
}

The <div> element inside the Message component will now use AttributeDictionary for attribute splatting.

<div @attributes="AttributeDictionary">
    @Value
</div>

Run the application again. The outcome will be identical to the previous run but this time we didn't use arbitrary parameters.

What will happen if the parent component doesn't set the AttributeDictionary parameter? Obviously, the <div> won't have id, class, and title attributes at all. You might want to set some default values for id, class, and title attributes just in case the parent doesn't set the AttributeDictionary parameter. This is how you can do that:

[Parameter]
public Dictionary<string, object> AttributeDictionary 
{ get; set; } = new Dictionary<string, object>()
    {
        {"id","div100" },
        {"class","divClass2" },
        {"title","Sample Title" }
    };

Here, we assigned some default values to AttributeDictionary property.

The divClass2 used above can be added to the Message.razor.css file:

.divClass2 {
    border: 5px solid blue;
    padding: 5px;
    background-color: cyan;
    width: 60%;
    font-size: 20px;
    font-weight: bold;
}

Open the Index.razor parent component and change the <Message> element like this:

<Message Value="Hello World!">
</Message>

So, here we didn't set the AttributeDictionary attribute at all.

If you run the application now, you will get this output:

As you can see, the <div> has now picked up the default values for id, class, and title attributes.

That's it for now! Keep coding!!


Bipin Joshi is an independent software consultant, trainer, author, yoga mentor, and meditation teacher. He has been programming, meditating, and teaching for 24+ years. He conducts instructor-led online training courses in ASP.NET family of technologies for individuals and small groups. He is a published author and has authored or co-authored books for Apress and Wrox press. Having embraced the Yoga way of life he also teaches Ajapa Yoga to interested individuals. To know more about him click here.

Get connected : Facebook  Twitter  LinkedIn  YouTube

Posted On : 11 January 2021


Tags : ASP.NET ASP.NET Core MVC .NET Framework C# Visual Studio


Subscribe to our newsletter

Get monthly email updates about new articles, tutorials, code samples, and how-tos getting added to our knowledge base.

  

Receive Weekly Updates