Click here to Skip to main content
15,887,135 members
Articles / Web Development / Blazor
Tip/Trick

Templated Data container with Razor

Rate me:
Please Sign up or sign in to vote.
5.00/5 (10 votes)
26 Jun 2023CPOL2 min read 8.5K   7   4
Rather than littering a razor component with @if (a == b) logic to show items, use render fragments to make a declarative component
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:

ASP.NET
@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:

ASP.NET
<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:

C#
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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
CEO
United Kingdom United Kingdom
A developer for over 30 years, I've been lucky enough to write articles and applications for Code Project as well as the Intel Ultimate Coder - Going Perceptual challenge. I live in the North East of England with 2 wonderful daughters and a wonderful wife.

I am not the Stig, but I do wish I had Lotus Tuned Suspension.

Comments and Discussions

 
SuggestionAn Alternative Approach Pin
George Swan27-Jun-23 6:21
mveGeorge Swan27-Jun-23 6:21 

Thanks for the interesting post. An alternative approach is to define a DataContainer component like this.

@if (IsShow)
{
     <div class="container" >
        @ChildContent
     </div >
}

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

And to use is like this.

<h1 >Weather Forecast </h1 >

 <p >This component demonstrates fetching data from a service. </p >
 <DataContainer IsShow=@IsLoading > <p >There is no data </p > </DataContainer >
 <DataContainer IsShow=@(!IsLoading) >
     <div class="mb-8" >
         <p >There is content here </p >
     </div >
 </DataContainer >

The advantage of this approach is that only a single component is used and the code behind is limited to parameter definitions.


GeneralRe: An Alternative Approach Pin
Pete O'Hanlon27-Jun-23 6:55
mvePete O'Hanlon27-Jun-23 6:55 
PraisePerfectly simple Pin
AaronSmithUK27-Jun-23 2:05
AaronSmithUK27-Jun-23 2:05 
GeneralMy vote of 5 Pin
Graeme_Grant26-Jun-23 14:19
mvaGraeme_Grant26-Jun-23 14:19 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.