DEV Community

Cover image for Building a Software Survey using Blazor - Part 3 - Components
Mark Taylor
Mark Taylor

Posted on • Originally published at red-folder.com

Building a Software Survey using Blazor - Part 3 - Components

I've decided to write a small survey site using Blazor. Part of this is an excuse to learn Blazor.

As I learn with Blazor I will blog about it as a series of articles.

This series of articles is not intended to be a training course for Blazor - rather my thought process as I go through learning to use the product.

Earlier articles in this series:


Blazor is very much based on components. This was something I was very pleased to see.

Having spent a lot of time with React, I've been quite a fan of the component structure. The MVC structure enforced by ASP.Net, while familiar, has always seems a little clunky since working with React.

So it was definitely good to see that Blazor was taking a lot of its direction from Javascript frameworks like React & Vue.

We still have a little time to wait for CSS isolation by component - but that seem to be coming soon in .Net 5. Something I'll take a look at again when released.

The basics

Creating a component is very much a first class activity within Visual Studio - simply add a new Razor Component.

This creates our sample component ready to go.

Test.razor

<h3>Test</h3>

@code {

}
Enter fullscreen mode Exit fullscreen mode

And we can then pull that component into any other Razor component or page by adding <Test />

One thing to watch out for is that you components namespace will be based on the folder you create it in. Just remember to include that namespace in the apps _Imports.razor file.

Code

While the markdown is easy - it just goes into the razor file. Where to put the code I suspect will produce debate in teams for years to come.

You basically have three choices:

  • In the Test.razor file within the @code { } block
  • In a Test.razor.cs file as a partial class
  • In a TestBase.cs "base" class (extending ComponentBase) and then @inherits TestBase in the Test.razor

While I suspect that which version is used will be personal taste, I personally would advise picking one and trying to stick to it to avoid confusion.

Personally I favour using the @code { } block within the razor file. It keeps the code & markup in one place and easy to see - similar to how I'd do it within React.

The @code { } block may get a bit unwieldy if you have a lot of code - but that maybe an indication that your trying to do too much in your component.

For me, the @code { } block should be fairly simple with any logic being injected in.

Composition over inheritance

In early versions of the Software Survey I leaned heavily on the "base" class technique. I used it to inhert functionality for the survey pages.

You can see this in this commit version; that I have two base classes used by all of the pages:

These two bases classes provided a level of functionality for all the Survey pages - which technically worked, but definitely didn't "smell" correct.

So I refactored the functionality out of the base classes into components. The components are then composed together - which has subsequently made the code considerably easier to understand.

If possible, always favour component composition over inheritance.

ChildContent

Similar to React, Blazor supports children being passed into a component.

An example of where I've used this is in the <EnsureBeenThroughStart /> component:

EnsureBeenThroughStart.razor

@if (_valid)
{
    @ChildContent
}

@code {
    [Parameter]
    public RenderFragment ChildContent { get; set; }

    private bool _valid;

    ...
}
Enter fullscreen mode Exit fullscreen mode

The component is used to ensure that the user has visited the start of the survey (if not it redirects to the start). It should avoid respondents accidentally deep linking part way through the survey.

If valid, the component shows the @ChildContent. That @ChildContent is automatically provided by Blazor as any thing defined between the <EnsureBeenThroughStart> </EnsureBeenThroughStart> tags.

As you can see below, I wrap the entire router within it.

App.razor

...

<PreRenderLoadingMessage>
    <EnsureBeenThroughStart>
        <Router AppAssembly="@typeof(Program).Assembly">
            <Found Context="routeData">
                <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
            </Found>
            <NotFound>
                <LayoutView Layout="@typeof(MainLayout)">
                    <p>Sorry, there's nothing at this address.</p>
                    @{ Is404 = true; }
                </LayoutView>
            </NotFound>
        </Router>
     </EnsureBeenThroughStart>
</PreRenderLoadingMessage>

...
Enter fullscreen mode Exit fullscreen mode

More to learn

Components can seem a simple concept, but like many simple things, I think they will take experience to get the best from them.

I learnt that during the refactor away from the "base" classes.

I suspect overtime (and usage) patterns of usage will emerge - as they have in React. I suspect that many ideas will cross-pollinate between Blazor and Javascript frameworks.

If you've not done so already, I'd recommend reading the Microsoft Create and use ASP.NET Core Razor components page

Top comments (0)