Passing Data to Components | Blazor Tutorial
Blazor .NET .NET Core

Passing Data to Components | Blazor Tutorial

Mishel Shaji
Mishel Shaji

In the previous post, we discussed about routable and shared components. They are the building blocks of any Blazor app. In a real-world application, there can be tens or even hundreds of components.

Now the question is, How will these components communicate with each other? How can we pass data from one component to another? We’ll find an answer to these questions in this post.

Parameters

We can pass data to different components using parameters. In our previous example (previous post), we displayed a list of customers using the CustomerList component. All data needed for it to function properly was contained within the component.

<h3>Customer List</h3>
@foreach (var customer in Customers)
{
    <div class="card mb-3">
        <div class="card-header">
            @customer.Name
            @if (customer.IsSubscribedToNewsletter)
            {
                <span class="badge badge-success">Subscribed</span>
            }
            else
            {
                <span class="badge badge-danger">Not subscribed</span>
            }
        </div>
        <div class="card-body">@customer.Email</div>
    </div>
}

@code {
    public class Customer
    {
        public string Name { get; set; }
        public string Email { get; set; }
        public bool IsSubscribedToNewsletter { get; set; }
    }

    List<Customer> Customers = new List<Customer>()
    {
        new Customer(){Name= "John Doe", Email="john@mail.com", IsSubscribedToNewsletter=true},
        new Customer(){Name= "Jane Doe", Email="jane@mail.com", IsSubscribedToNewsletter=true},
        new Customer(){Name= "Janet Doe", Email="janet@mail.com", IsSubscribedToNewsletter=false},
    };
}

The problem with this implementation is that this component cannot accept a list of customers from other components and display them. To solve this problem, well use parameters.

To create input parameters, follow these steps.

Step 1: Open BlazorApp.Shared project and create a new folder named Models. Then create a new C# class named Customer in it.

using System;
using System.Collections.Generic;
using System.Text;

namespace BlazorApp.Shared.Models
{
    public class Customer
    {
        public string Name { get; set; }
        public string Email { get; set; }
        public bool IsSubscribedToNewsletter { get; set; }
    }
}

Step 2: go to BlazorApp.Client project -> Pages -> _Imports.razor and add reference to the Models namespace (see the last line).

@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.WebAssembly.Http
@using Microsoft.JSInterop
@using BlazorApp.Client
@using BlazorApp.Client.Shared
@using Helpers;
@using BlazorApp.Shared.Models;

All classes in the models namespace can be now accessed in any components without manually importing them.

Reference added in _Imports.razor will be available in all components of the Blazor application.

Step 3: In the BlazorApp.Client project, Right-click on the Shared folder -> go to New Item -> Razor Component and create a new component named CusromerList.razor. If you have already created this component, you can skip this step.

Step 4: Replace the content of CustomerList.razor with this code.

<h3>Customer List</h3>
@foreach (var customer in Customers)
{
    <div class="card mb-3">
        <div class="card-header">
            @customer.Name
            @if (customer.IsSubscribedToNewsletter)
            {
                <span class="badge badge-success">Subscribed</span>
            }
            else
            {
                <span class="badge badge-danger">Not subscribed</span>
            }
        </div>
        <div class="card-body">@customer.Email</div>
    </div>
}

@code {

    [Parameter]
    public List<Customer> Customers { get; set; }

}

As I said earlier, I prefixed the Customers list with [Parameter] attribute. This marks the list as a parameter that can be passed from any other components.

If we add [Parameter] attribute to any public properties of a component, the property will become a parameter that can be passed to the component.

Step 5: Open Index Component (Pages/Index.razor) and create a list of customers.

@code{
    List<Customer> _customers = new List<Customer>()
    {
        new Customer(){Name= "John Doe", Email="john@mail.com", IsSubscribedToNewsletter=true},
        new Customer(){Name= "Jane Doe", Email="jane@mail.com", IsSubscribedToNewsletter=true},
        new Customer(){Name= "Janet Doe", Email="janet@mail.com", IsSubscribedToNewsletter=false},
    };
}

Step 6: Now, we can pass the list of customers to CustomerList component.

<CustomerList Customers="_customers"/>

Here’s the complete code of Index component.

@page "/"

<CustomerList Customers="_customers"/>

@code{
    List<Customer> _customers = new List<Customer>()
    {
        new Customer(){Name= "John Doe", Email="john@mail.com", IsSubscribedToNewsletter=true},
        new Customer(){Name= "Jane Doe", Email="jane@mail.com", IsSubscribedToNewsletter=true},
        new Customer(){Name= "Janet Doe", Email="janet@mail.com", IsSubscribedToNewsletter=false},
    };
}

Arbitrary parameters

In Blazor, we can also pass arbitrary parameters to components. Arbitrary parameters are additional optional parameters that can be passed to a component.

To create arbitrary parameter in a Blazor component, we can use the same [Parameter] attribute that we used just before with an extra parameter CaptureUnmatchedValues = true.

Here’s an example.

[Parameter(CaptureUnmatchedValues = true)]
public IDictionary<string, string> Attributes { get; set; }

Now, let us create a new component and pass some arbitrary parameters to it.

In the Shared folder, create a new component named Alert. We’ll use this component to display alert messages in our application.

Replace the content of Alert component with this code.

<div class="alert @Style" @attributes="Attributes">
    @Message
</div>

@code {
    [Parameter]
    public string Message { get; set; }

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

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

This component has three properties.

  • Message – The message to be displayed.
  • Style – This is basically the bootstrap class. It can be any classes like alert-success, alert-danger etc.
  • Attributes – This property is used to hold parameters than the Message and Style.

These properties will be applied to the div tag when this component is rendered. Unlike other properties, arbitrary parameters are displayed using @attributes.

Now, go to the index component and add the following lines anywhere in the HTML markup.

<Alert Message="Displaying list of customers" Style="alert-success" title="Hover to see the title"></Alert>

I’ve added it just below the @page directive. Note that we are passing title as a parameter to the component. But this parameter is not declared in the component. So, title is an arbitrary parameter.

Compile the application, reload the browser tab and bring the mouse pointer over the alert to see the title attribute, that was an arbitrary parameter, displayed there.

In the next post, we’ll learn about data binding in Blazor.