In the last lesson, the Kladde’s pages moved to Blazor, but every page is still a single block of HTML. In this lesson you break them down into components: small building blocks with one job that get values from outside and look the same everywhere. It’s the same principle as with methods and classes in K1: Whatever appears twice or is understandable on its own gets a name.

In the end, the pages have three building blocks: a page header PageHeader, the list ContactList and a contact’s row ContactCard. Each brings its own stylesheet, and the look stays as it was.

Building a component

Every .razor file is a component, even one without @page. The page header is the first building block: a heading with a frame around it. In the Kladde, create src/Kladde.Web/Components/Shared/PageHeader.razor:

Razor
<div class="page-header">
    <h1>@Title</h1>
</div>

@code {
    [Parameter]
    public string Title { get; set; } = string.Empty;
}

A parameter is a public property with the attribute [Parameter]. Whoever uses the component sets it like an HTML attribute. So that the name PageHeader is known everywhere, add the folder’s namespace to Components/_Imports.razor:

Razor
@using Kladde.Web.Components.Shared

Then the home page writes, instead of <h1>Kladde</h1>:

Razor
<PageHeader Title="Kladde" />

Components begin with an uppercase letter, HTML elements with a lowercase one. That’s how the compiler knows what’s meant. A typo like <Pageheader> is therefore not an error but an unknown HTML element; the compiler warns with RZ10012, and because warnings are errors in the Kladde, the build fails.

What goes in an attribute

For a parameter of type string, the value is text. With @, you give a C# expression instead:

Razor
<PageHeader Title="Contacts" />
<PageHeader Title="@pageTitle" />
<PageHeader Title="@($"Contacts ({count})")" />

For all other types, the value is always C#, even without @. So Contacts="contacts" passes the field contacts, not the text “contacts”. You may write the @ all the same, and many people do for clarity.

Required parameters

A page header without a title is a mistake. The compiler should find this mistake, not only someone who looks at the page. That’s what [EditorRequired] is for:

Razor
@code {
    [Parameter, EditorRequired]
    public string Title { get; set; } = string.Empty;
}

If Title is missing where the component is used, the Razor compiler reports the warning RZ2012. In the Kladde, warnings are errors, so the build stops:

Contacts.razor(8,1): error RZ2012: Component 'PageHeader' expects a value for the parameter 'Title', but a value may not have been provided.

The initial value string.Empty is still necessary, because nullable is on, and the compiler doesn’t know that Blazor sets the parameter.