While writing Blazor components, I got sick of wrapping the visibility of content inside @if.../else logic to show different content when data was present, to when it wasn't. In this simple trick, we are going to look at a handy little method of displaying content depending on whether or not data is present.
Introduction
I have been working on a Blazor application and I hated that one of my forms had this big old ugly @if (a == b)
show some content else
show a message to say there was no data. It was ugly, and it didn't fit into the templated nature of the code so I decided to do something about it.
Background
This is a simple component that consists of three variables, but it makes life look a lot neater. Gone is the code that looks like this:
@if (_value == 0) {
<p>There is no data</p>
} else {
<div class="mb-8">
<p>There is content here.</p>
</div>
}
That code is replaced by the (in my eye), much more elegant:
<DataContainer HasData="@(_value > 0)">
<NoData>
<p>There is no data</p>
</NoData>
<DataTemplate>
<div class="mb-8">
<p>There is content here</p>
</div>
</DataTemplate>
</DataContainer>
The Code
The code behind this relies on the ability of razor to let us create RenderFragments
and use this to create our own RenderTree
. The code is as simple as creating three parameters, and overriding the BuildRenderTree
method like this:
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
namespace Goldlight.ServiceVirtualisation.Components;
public class DataContainer : ComponentBase
{
[Parameter] public bool HasData { get; set; }
[Parameter] public RenderFragment DataTemplate { get; set; } = null!;
[Parameter] public RenderFragment NoData { get; set; } = null!;
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
builder.AddContent(0, HasData ? DataTemplate : NoData);
}
}
That's it; that's all there is to it. Having created this component, I find that I use it all over the place. It's simple to use a similar concept to build a component that shows and hides a spinner, replacing it with content to manage a loading component.
A point of note; I have chosen to deliberately set the components with null!
to show that, even though they start defined as null
, they will definitely have a value before I use them when I'm building the render tree. I could have added checks in the build method, if these were nullable properties, but as the problem I am solving is to show different data under different conditions, then I don't need to make the render fragments nullable.
I hope you like this tip (there's no code download because the code for the tip is a dozen lines long or so). When you start to play around with render fragments, you'll find all sorts of situations in which you will want to use them.
History
- 26th June, 2023: Initial version