Types of Blazor Components Routable Non-Routable Templated Dynamic

In my last article, we explored the fundamentals of components in Blazor and how they contribute to creating a Single Page Application (SPA). You can read it here. But what is this entity called a component?

let me give you a 50,000-foot view of what a component in Blazor is.

A component is a reusable piece of UI; it is a combination of C# code, HTML markup, and CSS styles. We use components to render UI, encapsulate UI logic with data, and handle user interactions. Components can interact with each other through parameters and events, and they automatically update the UI when their state changes.

This is the basic syntax of a component.

@page "/mycomponent"
<h3>Hello, @name!</h3>
<button @onclick="ChangeName">Change Name</button>
@code {
    private string name = "Blazor";
    private void ChangeName()
    {
        name = "World";
    }
}

Code Snippet 1. Basic Component Syntax

Types of Components in Blazor

In this article, we'll explore four types of components.

  1. Routable Components
  2. Non-Routable Components
  3. Templated Components
  4. Dynamic Components

To illustrate these components, we'll create a Marvel superhero app. Start by creating a Blazor Web App using any template you prefer.

1. Routable Components

A routable component is accessed via a URL. These components define routes using the @page directive, which specifies the URL that maps to the component. Routable components typically go in the Pages folder.

@page "/superheroes"
@using Models
@using MyFirstBlazorWebApp.Components.UI;
<h3>Marvel Superheroes</h3>
<div>
    @foreach (var hero in superheroes)
    {
        <div>
            <SuperHero Hero="hero" />
        </div>
    }
</div>
@code {
    private List<Superhero> superheroes = new List<Superhero>
    {
        new Superhero { Name = "Spider-Man", Superpower = "Wall-crawling, web-shooting, spider-sense" },
        new Superhero { Name = "Iron Man", Superpower = "Genius-level intellect, powered armor suit" },
        new Superhero { Name = "Captain America", Superpower = "Superhuman strength, agility, endurance" },
        new Superhero { Name = "Thor", Superpower = "God of Thunder, superhuman strength, control over lightning" },
        new Superhero { Name = "Hulk", Superpower = "Unlimited strength, invulnerability" }
    };
}

Code snippet 2. SuperHeroes.razor

In this example, this component lists various superheroes and uses another component called SuperHero.razor, at line number 22, to display details for each hero. Users can navigate to "/superheroes" to see this component.

2. Non-Routable Components

Non-routable components are components that cannot be directly accessed via a URL. These components are typically reusable UI elements that can be used within other components. Non-routable components usually go in a Components folder or a specific folder like Components/UI.

In the above example, the one we are calling at line number 22 is a non-routable component SuperHero.razor, which you can see below. It can be reused inside any component.

@using MyFirstBlazorWebApp.Models
<div>
    <div>
        <h5>@Hero.Name</h5>
        <p><strong>Superpowers:</strong> @Hero.Superpower</p>
    </div>
</div>

@code {
    [Parameter] public Superhero Hero { get; set; }
}

Code snippet 3. SuperHero.razor

It is used within the SuperHeroes component to display individual SuperHero details. It accepts a parameter, Hero, which contains the superhero's information.

Let's see how it looks in the output. In the following image 1, I am loading the routable component "SuperHeroes.razor" through the URL "/superheroes", which then goes through a list of movies and loads the non-routable component "SuperHero.razor" for each movie.

SuperHeroes razor

Image 1: Routable component loading a non-routable component

3. Templated Components

Templated components allow you to define a UI template for their content. They use RenderFragment<T> to create a template for items in a collection.

Let's create a MovieTemplate component.

To define a template, we need the following.

  • @typeparam TItem: This defines a generic type parameter TItem for the component, allowing it to be used with any type.
  • Items parameter: Accepts a collection of items of type TItem to be rendered by the component.
  • ItemTemplate parameter: Accepts a render fragment that defines how each item should be rendered. The RenderFragment<TItem> type allows the template to take an item of type TItem as a parameter.
@typeparam TItem
<div>
    @foreach (var item in Items)
    {
        @ItemTemplate(item)
    }
</div>
@code {
    [Parameter] public IEnumerable<TItem> Items { get; set; }
    [Parameter] public RenderFragment<TItem> ItemTemplate { get; set; }
}

Code snippet 4. MovieTemplate.razor

Now let's use the MovieTemplate component in the following Movies.razor component.

We're calling MovieTemplate at line number 8 in code snippet 5, where we're passing a list of movies to the Items parameter in MovieTemplate. Immediately following Items, we pass ItemTemplate, which is then forwarded to the RenderFragment of MovieTemplate to define how each movie item should be rendered.

The Context="movie" attribute assigns the current item to the movie variable within the template.

@page "/movies"
@using MyFirstBlazorWebApp.Components.UI
@using MyFirstBlazorWebApp.Models
<h3>Marvel Movies</h3>
<MovieTemplate Items="movies">
    <ItemTemplate Context="selectedMovie">
        <div>
            <h5>@selectedMovie.Title</h5>
            <p><strong>Director:</strong> @selectedMovie.Director</p>
            <p><strong>Release Year:</strong> @selectedMovie.ReleaseYear</p>
        </div>
    </ItemTemplate>
</MovieTemplate>
@code {
    private List<Movie> movies = new List<Movie>
    {
        new Movie { Title = "Iron Man", Director = "Jon Favreau", ReleaseYear = 2008 },
        new Movie { Title = "The Avengers", Director = "Joss Whedon", ReleaseYear = 2012 },
        new Movie { Title = "Guardians of the Galaxy", Director = "James Gunn", ReleaseYear = 2014 },
        new Movie { Title = "Black Panther", Director = "Ryan Coogler", ReleaseYear = 2018 },
        new Movie { Title = "Avengers: Endgame", Director = "Anthony and Joe Russo", ReleaseYear = 2019 }
    };
}

Code snippet 5. Movies.razor

Let's run this and check its output.

All the green highlights in the image below represent the template being called by Movies.razor for the list of movies.

Movies.razor

Image 2: Movies component loading template components

4. Dynamic Components

Dynamic components allow you to load and render components at runtime based on certain conditions. This is useful for creating highly dynamic and configurable UIs.

For example, users can select a Marvel superhero from a dropdown menu and dynamically display the corresponding component with information about the selected superhero.

@page "/dynamicmovies"
@using MyFirstBlazorWebApp.Components.UI
@rendermode InteractiveServer
<h3>Dynamically Load Movies</h3>
<p>
    <label>
        Select a Marvel superhero:
        <select @onchange="OnDropdownChange">
            <option value="">Select a superhero</option>
            @foreach (var superHero in superheroes.Keys)
            {
                <option value="@superHero">@superHero</option>
            }
        </select>
    </label>
</p>
@if (selectedSuperhero is not null)
{
    <div>
        <DynamicComponent Type="superheroes[selectedSuperhero]" />
    </div>
}
@code {
    private string selectedSuperhero;
    private readonly Dictionary<string, Type> superheroes = new()
    {
         ["Iron Man"] = typeof(IronMan),
         ["Captain America"] = typeof(CaptainAmerica),
         ["Thor"] = typeof(Thor),
         ["Black Widow"] = typeof(BlackWidow),
         ["Spider-Man"] = typeof(SpiderMan)
    };
    private void OnDropdownChange(ChangeEventArgs e)
    {
        if ((e.Value is string dropdownValue) && !String.IsNullOrWhiteSpace(dropdownValue))
        {
            selectedSuperhero = dropdownValue;
        }
        else
        {
            selectedSuperhero = null;
        }
    }
}

Code snippet 6. DynamicMovies.razor

A dictionary is used in the DynamicMovies.razor component to dynamically select and render the appropriate SuperHero component based on user input. When a user selects a superhero from a dropdown list, the OnDropdownChange() method gets triggered. This method looks up the selected superhero's name in the dictionary to find the corresponding component type. The component is then rendered dynamically using the DynamicComponent.

Let's create 5 dynamic components for each superhero, Black Widow, Captain America, Iron Man, Spider-Man, and Thor.

<h2>Black Widow</h2>
<p>
    Black Widow, Natasha Romanoff, is a fictional superhero appearing in
    American comic books published by Marvel Comics. She is a trained spy
    and assassin.
</p>

Code snippet 7. BlackWidow.razor

<h2>Captain America</h2>
<p>
    Captain America, Steve Rogers, is a fictional superhero appearing in
    American comic books published by Marvel Comics.
</p>

Code snippet 8. CaptainAmerica.razor

<h2>Iron Man</h2>
<p>
    Iron Man is a superhero appearing in Marvel Comics, created by Stan Lee,
    Larry Lieber, Don Heck, and Jack Kirby. He is portrayed by Robert Downey Jr.
    in the Marvel Cinematic Universe.
</p>

Code snippet 9. IronMan.razor

<h2>Spider-Man</h2>
<p>
    Spider-Man, Peter Parker, is a fictional superhero created by writer
    Stan Lee and artist Steve Ditko. He first appeared in Amazing
    Fantasy #15 in 1962.
</p>

Code snippet 10. SpiderMan.razor

<h2>Thor</h2>
<p>
    Thor Odinson is a fictional superhero appearing in American comic books
    published by Marvel Comics. He is based on the Norse deity of the same name.
</p>

Code snippet 11. Thor.razor

In Image 3, I selected Iron Man from the dropdown, which found the IronMan component "Code snippet 9" and loaded it on the UI.

Code snippet 9

Image 3: Dynamically loading the Iron Man component

In Image 4, I changed superhero to Spider-Man from the dropdown. This action finds the SpiderMan.razor component "Code snippet 10" and loads it on the UI.

Code snippet 10

Image 3: Dynamically loading the Spider Man component

This is how you can dynamically render components based on their type.

Conclusion

Blazor offers versatile component types that allow you to build dynamic and interactive UIs. Understanding the different types of components, routable, non-routable, templated, and dynamic will help you to leverage for creating sophisticated web applications.

We covered all four types of component, you can use them in your projects as per your project's needs.

Note. Download the attached source code for your reference.


Similar Articles