Fuzzy.Blazor.FluentRenderTreeBuilder 3.0.1

dotnet add package Fuzzy.Blazor.FluentRenderTreeBuilder --version 3.0.1                
NuGet\Install-Package Fuzzy.Blazor.FluentRenderTreeBuilder -Version 3.0.1                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Fuzzy.Blazor.FluentRenderTreeBuilder" Version="3.0.1" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Fuzzy.Blazor.FluentRenderTreeBuilder --version 3.0.1                
#r "nuget: Fuzzy.Blazor.FluentRenderTreeBuilder, 3.0.1"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Fuzzy.Blazor.FluentRenderTreeBuilder as a Cake Addin
#addin nuget:?package=Fuzzy.Blazor.FluentRenderTreeBuilder&version=3.0.1

// Install Fuzzy.Blazor.FluentRenderTreeBuilder as a Cake Tool
#tool nuget:?package=Fuzzy.Blazor.FluentRenderTreeBuilder&version=3.0.1                

FluentRenderTreeBuilder

The FluentRenderTreeBuilder library extends Blazor's built-in RenderTreeBuilder with a clean and fluent API for building Blazor components in pure C# code, and automatically generates source-code-line-based sequence numbers, whilst still allowing specific sequence numbers to be specified if desired.

The resulting markup code is identical to the razor compiler output, with minor whitespace differences, and optionally output can be automatically minified by disabling the built-in 'pretty printing' feature, which is enabled by default to match the behaviour of Blazor's razor page compiler.

Fluent API

Developers don't have to hand-write repetitive calls to the built-in RenderTreeBuilder as the FluentRenderTreeBuilder allows fluent chaining of calls.

Taking an example from Chris Sainty's blog, this code:

protected override void BuildRenderTree(
    RenderTreeBuilder builder)
{
  base.BuildRenderTree(builder);
  builder.OpenElement(0, "nav");
  builder.AddAttribute(1, "class", "menu");
  
  builder.OpenElement(2, "ul");
  builder.OpenElement(3, "li");
  builder.OpenComponent<NavLink>(4);
  builder.AddAttribute(5, "href", "/");
  builder.AddAttribute(6, "Match", NavLinkMatch.All);
  builder.AddAttribute(7, "ChildContent", (RenderFragment)((builder2) => {
    builder2.AddContent(8, "Home");
  }));
  builder.CloseComponent();
  builder.CloseElement();
  
  builder.OpenElement(9, "li");
  builder.OpenComponent<NavLink>(10);
  builder.AddAttribute(11, "href", "/contact");
  builder.AddAttribute(12, "ChildContent", (RenderFragment)((builder2) => {
    builder2.AddContent(13, "Contact");
  }));
  builder.CloseComponent();
  builder.CloseElement();
  builder.CloseElement();
  builder.CloseElement();
}

can now be written as:

protected override void BuildRenderTree(
    RenderTreeBuilder builder)
  => builder.Build()
    .OpenElement("nav", "menu")
      .OpenAutoList()
        .OpenComponent<NavLink>()
          .Attribute("href", "/")
          .Attribute("Match", NavLinkMatch.All)
          .ChildContent("Home")
        .Close()
      .NewItem()
        .OpenComponent<NavLink>()
          .Attribute("href", "/contact")
          .Attribute("Match", NavLinkMatch.All)
          .ChildContent("Contact")
    .CloseAll();

There are many new convenience methods and parameters provided, such as automatically generating id and class attributes from optional parameters to OpenElement, as shown above with the menu CSS class.

See the pages and components in the test app provided in the source code repo on GitHub for more usage examples.

Extensibility

Extension methods can be used to add new high-level functionality, and many are already included to help with table, list and attribute generation. In the above code snippet the OpenElement method which takes optional CSS class and id attributes extends the built-in OpenElement method.

For example, an extension method to automatically generate NavLink content might look like this (an example if this is included in the test app in the source repo):

public static FluentRenderTreeBuilder NavLink(
    this FluentRenderTreeBuilder fluentbuilder,
    string href, string markup,
    NavLinkMatch match = NavLinkMatch.Prefix,
    string? @class = null, string? id = null)
  => fluentbuilder
    .OpenComponent<NavLink>(@class ?? "nav-link", id)
      .Attribute("href", href)
      .Attribute("Match", match)
      .ChildContent((MarkupString) markup, prettyPrint: true)
      .NewLine(prettyPrint: true)
    .Close();

This now allows the above example to be written as:

protected override void BuildRenderTree(
    RenderTreeBuilder builder)
  => builder.Build()
    .OpenElement("nav", "menu")
      .OpenAutoList()
        .NavLink("/", "Home", NavLinkMatch.All)
      .NewItem()
        .NavLink("/contact", "Contact")
    .CloseAll();

This makes navigation list generation possible with just a few lines of code. However, going one step further by using the Menu() extensibility example included in the test app in the source repo, it can be reduced even further to:

protected override void BuildRenderTree(
    RenderTreeBuilder builder)
  => builder.Build()
    .Menu(
      ("", "home", "Home"),
      ("contacts", "people", "Counter"),

The Menu() extensibility example above also includes an icon parameter for each menu item which sets the nav item's icon from Blazor's built-in Open Iconic icon set.

Source code line-based sequence numbers

When using FluentRenderTreeBuilder developers don't have to manually provide and maintain the sequence numbers for each call to RenderTreeBuilder.

Unlike variable-based or calculated sequence numbers, which must not be used in Blazor components, FluentRenderTreeBuilder makes use of the [CallerLineNumber] attribute to generate each tree frame's sequence number based on the calling source code line number.

Product Compatible and additional computed target framework versions.
.NET net5.0 is compatible.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (4)

Showing the top 4 NuGet packages that depend on Fuzzy.Blazor.FluentRenderTreeBuilder:

Package Downloads
KingTech.Web.FormGenerator

Package Description

KingTech.Web.Markdown

Package Description

KingTech.Web.Markdown.NuGet

Package Description

Markdown2Markup

Blazor markdown to HTML converter based on MarkDig.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
3.0.1 2,821 6/30/2021
2.2.0 979 8/24/2020
2.1.0 959 8/17/2020
2.0.0 952 8/9/2020

Documentation

Please find the docs here:
https://fuzzy-work.github.io/FluentRenderTreeBuilder/


Version History

3.0.1:
- Note to self: release notes are text, not Markdown!

3.0.0:
- Updated to .NET 5.
- Added more detail to Callback examples to better show what's going on.
- Addressed several nullability warnings.
- Updated doc comments.
- Code clean-up.

2.2.0:
- Exposed `GetSequence()` and `Builder` to give extensions more control.
- Added `NewAutoItem()` in list extensions.
- Added `NewAutoRow()` in table extensions.
- Fixed logic for callbacks with render fragments.
- Made weather forecast more 'accurate' (couldn't resist!).

2.1.0
- Added new `Callback()` methods.
- Added new Callback examples.

2.0.0
- Added `key` parameter on various methods for automatic generation of `SetKey()` calls.
- Added `Break()` to generate `<br />`.
- Added `Close(n)` to close multiple nested blocks.
- Added `CloseAll()` to close all open blocks.
- Added `CloseHelper()` to allow methods generating composite content to handle their own block closing.
- BREAKING CHANGE: removed `CloseAutoTable`, `CloseTableBody`, `CloseAutoList` (now replaced with `CloseHelper`s).
- Improved example code.
- Improved logging output.
- Updated documentation.

1.1.1
- Updated readme and release notes.

1.1.0
- Added full code documentation.
- Added list extension methods for list generation.
- Added more example code.

1.0.1
- Removed an unnecessary dependency.

1.0.0
- Initial release.


Please raise an issue if there are any problems!

Cheers,
Fuzzy Work Ltd.