VOOZH about

URL: https://www.nuget.org/packages/BlazorComponentUtilities/

⇱ NuGet Gallery | BlazorComponentUtilities 1.8.0




👁 Image
BlazorComponentUtilities 1.8.0

dotnet add package BlazorComponentUtilities --version 1.8.0
 
 
NuGet\Install-Package BlazorComponentUtilities -Version 1.8.0
 
 
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="BlazorComponentUtilities" Version="1.8.0" />
 
 
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="BlazorComponentUtilities" Version="1.8.0" />
 
Directory.Packages.props
<PackageReference Include="BlazorComponentUtilities" />
 
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add BlazorComponentUtilities --version 1.8.0
 
 
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: BlazorComponentUtilities, 1.8.0"
 
 
#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.
#:package BlazorComponentUtilities@1.8.0
 
 
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=BlazorComponentUtilities&version=1.8.0
 
Install as a Cake Addin
#tool nuget:?package=BlazorComponentUtilities&version=1.8.0
 
Install as a Cake Tool
The NuGet Team does not provide support for this client. Please contact its maintainers for support.

CSS & Style Builder Pattern

Read the full API docs in the Wiki section

When building complex components for ASP.NET Razor Components there are often CSS classes generated by multiple factors. Styles can often be added by system & component state, public parameters, and static base CSS classes. Combining many CSS classes together doesn't scale well, and when components get large it can be tough to reason about. The CSS builder pattern fixes this problem by offering a easy to repeat, easy to read pattern to use across components in a project. A clean code approach to conditional CSS in Razor Components.

The problem

Given the component below, the Tab's CSS class is set by multiple sources. The component has paramater UserCss which can be set at externally. A base CSS class bl-nav-link which does not change. Two state based CSS classes bl-active and bl-disabled which are dependent on if the Tab is active or disabled. Rendering for the CSS class is spread across multiple concerns and is hard to maintain.

Component

<Tab UserCss="my-class" Disabled=true >...</Tab>

Component Source Markup

<li class="bl-nav-item">
 <a onclick=@Activate class="bl-nav-link @ActiveCssClass @DisabledCssClass" role="button">
 @Title
 </a>
</li>

Component Source Logic

[Parameter] string UserCss = String.Empty;
protected string ActiveCssClass => IsActive ? "bl-active" : String.Empty;
protected string DisabledCssClass => Disabled ? "bl-disabled" : String.Empty;

The Solution

Using the CSS Builder pattern we can clean up the code and move everything to a single concern. Refactoring the component, we move all of the CSS code to the components logic. In the OnParameterSet lifecycle method, we condense all of the CSS responsibilities into a single variable ClassToRender (this name variable is optional). Next, using the CssBuilder we define what classes should be added to the builder and when they should be rendered. The pattern is as follows AddClass the CSS class and the condition when it should appear AddClass(value, when: bool). If the value is static, we can discard the when parameter. Finally, Build is called. All CSS classes are then combined into a single string, properly spaced and trimmed.

The refactored code becomes:

Component Source Markup (refactor)

<li class="bl-nav-item">
 <a onclick=@Activate class="@ClassToRender" role="button">
 @Title
 </a>
</li>

Component Source Logic (refactor)

protected override void OnParametersSet()
{
 ClassToRender = new CssBuilder(UserCss)
 .AddClass("bl-nav-link")
 .AddClass("bl-active", when: IsActive)
 .AddClass("bl-disabled", when: Disabled)
 .Build();
}

Component Source Logic (refactor with SetPrefix)

protected override void OnParametersSet()
{
 ClassToRender = new CssBuilder(UserCss)
 .SetPrefix("bl-")
 .AddClass("nav-link")
 .AddClass("active", when: IsActive)
 .AddClass("disabled", when: Disabled)
 .Build();
}

Dynamic values

If you encounter a dynamic value where some string is added to a CSS class name, we can easily handle this as well. Consider the CSS namespace bl- must be prefixed to a value SomeValue supplied by the component state or user input. This is easily handled with string interpolation ${var}.

protected override void OnParametersSet()
{
 ClassToRender = new CssBuilder(UserCss)
 .AddClass("bl-nav-link")
 .AddClass("bl-active", when: IsActive)
 .AddClass("bl-disabled", when: Disabled)
			.AddClass("bl-${SomeValue}", when: IsConditionMet)
 .Build();
}

Attribute Splatting

If you encounter dynamic values due to attribute splatting, we can easily handle this as well. Consider the senario where we need to merge a splatted CSS attribute while preserving default values.


<MyComponent class="custom-value">

<div class="my-base custom-value">
<div @attributes="AdditionalAttributes" class="@CssClass">

@code {

 [Parameter(CaptureUnmatchedValues = true)]
 public IReadOnlyDictionary<string, object> AdditionalAttributes { get; set; } = new Dictionary<string, Object>();

 CssBuilder CssClass => new CssBuilder("my-base").AddClassFromAttributes(attributes);
}

Func When

Func<bool> is also accepted as an arguement for the when parameter. This allows either inline functions or named functions to be called directly.

protected override void OnParametersSet()
{
 ClassToRender = new CssBuilder(UserCss)
 .AddClass("bl-nav-link")
			.AddClass("bl-foo", when: ()=> 
			 !string.IsNullOrEmpty(Foo) ||
 !Disabled ||
 IsActive)
 .AddClass("bl-active", when: IsActive)
 .AddClass("bl-disabled", when: Disabled)
 .Build();
}

Named function, example.


bool HasMeaningfulName() => !string.IsNullOrEmpty(Foo) || !Disabled || IsActive);

protected override void OnParametersSet()
{
 ClassToRender = new CssBuilder(UserCss)
 .AddClass("bl-nav-link")
			.AddClass("bl-foo", when: HasMeaningfulName)
 .AddClass("bl-active", when: IsActive)
 .AddClass("bl-disabled", when: Disabled)
 .Build();
}

Removing Unused Attributes

When using dynamic attributes may result in empty attribute. When Blazor renders an attribute that has an empty string value, it will result in an empty attribute tag. However, if the value is null the attribute will be excluded. When an empty attribute is expected, the extension method NullIfEmpty can be used to clean up the resulting markup. Note: This method is only necessary when no default value is supplied. Ex: new CssBuilder() or CssBuilder().Empty(). Forgetting to call NullIfEmpty should not have any impact on the UI.


<div class="">


<div>
<div class="@CssClass">

@code {

 //string CssClass => new CssBuilder().AddClassFromAttributes(attributes).Build();
 string CssClass => new CssBuilder().AddClassFromAttributes(attributes).NullIfEmpty();
}
Product Versions Compatible and additional computed target framework versions.
.NET net5.0 net5.0 was computed.  net5.0-windows net5.0-windows was computed.  net6.0 net6.0 was computed.  net6.0-android net6.0-android was computed.  net6.0-ios net6.0-ios was computed.  net6.0-maccatalyst net6.0-maccatalyst was computed.  net6.0-macos net6.0-macos was computed.  net6.0-tvos net6.0-tvos was computed.  net6.0-windows net6.0-windows was computed.  net7.0 net7.0 was computed.  net7.0-android net7.0-android was computed.  net7.0-ios net7.0-ios was computed.  net7.0-maccatalyst net7.0-maccatalyst was computed.  net7.0-macos net7.0-macos was computed.  net7.0-tvos net7.0-tvos was computed.  net7.0-windows net7.0-windows was computed.  net8.0 net8.0 was computed.  net8.0-android net8.0-android was computed.  net8.0-browser net8.0-browser was computed.  net8.0-ios net8.0-ios was computed.  net8.0-maccatalyst net8.0-maccatalyst was computed.  net8.0-macos net8.0-macos was computed.  net8.0-tvos net8.0-tvos was computed.  net8.0-windows net8.0-windows was computed.  net9.0 net9.0 was computed.  net9.0-android net9.0-android was computed.  net9.0-browser net9.0-browser was computed.  net9.0-ios net9.0-ios was computed.  net9.0-maccatalyst net9.0-maccatalyst was computed.  net9.0-macos net9.0-macos was computed.  net9.0-tvos net9.0-tvos was computed.  net9.0-windows net9.0-windows was computed.  net10.0 net10.0 was computed.  net10.0-android net10.0-android was computed.  net10.0-browser net10.0-browser was computed.  net10.0-ios net10.0-ios was computed.  net10.0-maccatalyst net10.0-maccatalyst was computed.  net10.0-macos net10.0-macos was computed.  net10.0-tvos net10.0-tvos was computed.  net10.0-windows net10.0-windows was computed. 
.NET Core netcoreapp2.0 netcoreapp2.0 was computed.  netcoreapp2.1 netcoreapp2.1 was computed.  netcoreapp2.2 netcoreapp2.2 was computed.  netcoreapp3.0 netcoreapp3.0 was computed.  netcoreapp3.1 netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 netstandard2.0 is compatible.  netstandard2.1 netstandard2.1 was computed. 
.NET Framework net461 net461 was computed.  net462 net462 was computed.  net463 net463 was computed.  net47 net47 was computed.  net471 net471 was computed.  net472 net472 was computed.  net48 net48 was computed.  net481 net481 was computed. 
MonoAndroid monoandroid monoandroid was computed. 
MonoMac monomac monomac was computed. 
MonoTouch monotouch monotouch was computed. 
Tizen tizen40 tizen40 was computed.  tizen60 tizen60 was computed. 
Xamarin.iOS xamarinios xamarinios was computed. 
Xamarin.Mac xamarinmac xamarinmac was computed. 
Xamarin.TVOS xamarintvos xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

    • No dependencies.

NuGet packages (27)

Showing the top 5 NuGet packages that depend on BlazorComponentUtilities:

Package Downloads
BlazorStrap

A bootstrap 5 component library for Blazor

BlazorPro.Spinkit

A collection of loading indicators animated with CSS for Blazor. Spinkit also includes the SpinLoader component with templates for handling null values during async operations. Spinkit includes CSS from the Spinkit project by Tobias Ahlin https://tobiasahlin.com/spinkit/

BlazorStrap.V5

Bootstrap 5.x component library for BlazorStrap

Blazicons

Provides support for displaying SVG based icons in Blazor projects.

CsuChhs.Blazor

Blazor Tools for .Net Projects

GitHub repositories (1)

Showing the top 1 popular GitHub repositories that depend on BlazorComponentUtilities:

Repository Stars
FritzAndFriends/BlazorWebFormsComponents
A collection of Blazor components that emulate the ASP.NET Web Forms controls of the same name
Version Downloads Last Updated
1.8.0 1,211,772 12/10/2021
1.7.1 726,004 7/30/2021
1.7.0 14,100 6/14/2021
1.6.0 1,229,353 1/24/2020
1.5.0 2,255 1/23/2020
1.4.0 2,290 1/23/2020
1.3.1 2,673 1/16/2020
1.3.0 17,414 1/5/2020
1.2.1 2,475 1/4/2020
1.1.0 55,423 7/10/2019
1.0.0 3,447 4/11/2019

1.8.0
Fixed null ref error when using AddClassFromAttributes and passing a null attribute value.
1.7.1
Fixed trivial performance issue with redundant assignment when building strings
1.7.0
Added SetPrefix method to reduce reptititive class prefixing
1.6.0
Added Func<string> value overload for ValueBuilder
1.5.0
     Added Func<string> value overload for StyleBuilder
     Minor performance improvements for .Add*Attributes
1.4.0
     Added ValueBuilder for complex styles
      Updated /// docs
1.3.0
     Added utlitiy mehtod for Attribute Splatting.
     Added utility method for returning null for empty strings. This is useful for splatting scenarios.
     Added utility method for starting off new builders.