Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public partial class EditorForm<TModel> : IShowLabel
.Build();

private string? FormStyleString => CssBuilder.Default()
.AddClass($"--bb-row-label-width: {LabelWidth}px;", LabelWidth.HasValue)
.AddStyle("--bb-row-label-width", $"{LabelWidth}px", LabelWidth.HasValue)
.Build();

/// <summary>
Expand Down
8 changes: 7 additions & 1 deletion src/BootstrapBlazor/Components/Label/BootstrapLabel.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,17 @@ public partial class BootstrapLabel
[Parameter]
public int? LabelWidth { get; set; }

[CascadingParameter]
private BootstrapLabelSetting? Setting { get; set; }

private bool _showTooltip;

private string? ClassString => CssBuilder.Default("form-label")
.AddClassFromAttributes(AdditionalAttributes)
.Build();

private string? StyleString => CssBuilder.Default()
.AddClass($"--bb-row-label-width: {LabelWidth}px;", LabelWidth.HasValue)
.AddStyle($"--bb-row-label-width", $"{LabelWidth}px", LabelWidth.HasValue)
.Build();

/// <summary>
Expand All @@ -52,5 +55,8 @@ protected override void OnParametersSet()
_showTooltip = ShowLabelTooltip.Value;
}
Value ??= "";

// 获得级联参数的 LabelWidth
LabelWidth ??= Setting?.LabelWidth;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@namespace BootstrapBlazor.Components

<CascadingValue Value="this" IsFixed="true">
@ChildContent
</CascadingValue>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the Apache 2.0 License
// See the LICENSE file in the project root for more information.
// Maintainer: Argo Zhang([email protected]) Website: https://www.blazor.zone

namespace BootstrapBlazor.Components;

/// <summary>
/// BootstrapLabelSetting 组件类
/// </summary>
public partial class BootstrapLabelSetting
{
/// <summary>
/// 获得/设置 子组件
/// </summary>
[Parameter]
public RenderFragment? ChildContent { get; set; }

/// <summary>
/// 获得/设置 标签宽度 默认 null 未设置使用全局设置 <code>--bb-row-label-width</code> 值
/// </summary>
[Parameter]
public int? LabelWidth { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ public partial class ValidateForm
private string? ShowAllInvalidResultString => ShowAllInvalidResult ? "true" : null;

private string? StyleString => CssBuilder.Default()
.AddClass($"--bb-row-label-width: {LabelWidth}px;", LabelWidth.HasValue)
.AddStyle("--bb-row-label-width", $"{LabelWidth}px", LabelWidth.HasValue)
.Build();

/// <summary>
Expand Down
66 changes: 65 additions & 1 deletion src/BootstrapBlazor/Utils/CssBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,71 @@ public CssBuilder AddClassFromAttributes(IDictionary<string, object>? additional
}

/// <summary>
/// Adds a conditional Style when it exists in a dictionary to the builder with space separator.
/// Adds a raw string to the builder that will be concatenated with the next style or value added to the builder.
/// </summary>
/// <param name="key">style property name</param>
/// <param name="value">CSS style to conditionally add.</param>
/// <returns>CssBuilder</returns>
public CssBuilder AddStyle(string key, string? value)
{
if (!string.IsNullOrEmpty(value)) stringBuffer.Add($"{key}: {value};");
return this;
}

/// <summary>
/// Adds a conditional css Style to the builder with space separator.
/// </summary>
/// <param name="key">style property name</param>
/// <param name="value">CSS style to conditionally add.</param>
/// <param name="when">Condition in which the CSS style is added.</param>
/// <returns>CssBuilder</returns>
public CssBuilder AddStyle(string key, string? value, bool when = true) => when ? AddStyle(key, value) : this;

/// <summary>
/// Adds a conditional css Style to the builder with space separator.
/// </summary>
/// <param name="key">style property name</param>
/// <param name="value">CSS style to conditionally add.</param>
/// <param name="when">Condition in which the CSS Style is added.</param>
/// <returns>CssBuilder</returns>
public CssBuilder AddStyle(string key, string? value, Func<bool> when) => AddStyle(key, value, when());

/// <summary>
/// Adds a conditional css Style to the builder with space separator.
/// </summary>
/// <param name="key">style property name</param>
/// <param name="value">Function that returns a css Style to conditionally add.</param>
/// <param name="when">Condition in which the CSS Style is added.</param>
/// <returns>CssBuilder</returns>
public CssBuilder AddStyle(string key, Func<string?> value, bool when = true) => when ? AddStyle(key, value()) : this;

/// <summary>
/// Adds a conditional css Style to the builder with space separator.
/// </summary>
/// <param name="key">style property name</param>
/// <param name="value">Function that returns a css Style to conditionally add.</param>
/// <param name="when">Condition in which the CSS Style is added.</param>
/// <returns>CssBuilder</returns>
public CssBuilder AddStyle(string key, Func<string?> value, Func<bool> when) => AddStyle(key, value, when());

/// <summary>
/// Adds a conditional nested CssBuilder to the builder with space separator.
/// </summary>
/// <param name="builder">CSS Style to conditionally add.</param>
/// <param name="when">Condition in which the CSS Style is added.</param>
/// <returns>CssBuilder</returns>
public CssBuilder AddStyle(CssBuilder builder, bool when = true) => when ? AddClass(builder.Build()) : this;

/// <summary>
/// Adds a conditional CSS Class to the builder with space separator.
/// </summary>
/// <param name="builder">CSS Class to conditionally add.</param>
/// <param name="when">Condition in which the CSS Class is added.</param>
/// <returns>CssBuilder</returns>
public CssBuilder AddStyle(CssBuilder builder, Func<bool> when) => AddClass(builder, when());

/// <summary>
/// Adds a conditional css Style when it exists in a dictionary to the builder with space separator.
/// Null safe operation.
/// </summary>
/// <param name="additionalAttributes">Additional Attribute splat parameters</param>
Expand Down
40 changes: 40 additions & 0 deletions test/UnitTest/Components/BootstrapLabelTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the Apache 2.0 License
// See the LICENSE file in the project root for more information.
// Maintainer: Argo Zhang([email protected]) Website: https://www.blazor.zone

namespace UnitTest.Components;

public class BootstrapLabelTest : BootstrapBlazorTestBase
{
[Fact]
public void BootstrapLabelSetting_LabelWidth_Ok()
{
var cut = Context.RenderComponent<BootstrapLabelSetting>(pb =>
{
pb.Add(a => a.LabelWidth, 120);
pb.AddChildContent<BootstrapLabel>();
});
Assert.Equal("<label class=\"form-label\" style=\"--bb-row-label-width: 120px;\"></label>", cut.Markup);

var label = cut.FindComponent<BootstrapLabel>();
label.SetParametersAndRender(pb =>
{
pb.Add(a => a.LabelWidth, 80);
});
Assert.Equal("<label class=\"form-label\" style=\"--bb-row-label-width: 80px;\"></label>", cut.Markup);
}

[Fact]
public void LabelWidth_Ok()
{
var cut = Context.RenderComponent<BootstrapLabel>();
Assert.Equal("<label class=\"form-label\"></label>", cut.Markup);

cut.SetParametersAndRender(pb =>
{
pb.Add(a => a.LabelWidth, 120);
});
Assert.Equal("<label class=\"form-label\" style=\"--bb-row-label-width: 120px;\"></label>", cut.Markup);
}
}
66 changes: 66 additions & 0 deletions test/UnitTest/Utils/CssBuilderTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,51 @@ public void AddClass_When()
Assert.Contains("cls_test", classString);
}

[Fact]
public void AddStyle_When()
{
var classString = CssBuilder.Default()
.AddStyle("width", () => "cls_test", () => false)
.Build();
Assert.DoesNotContain("widht: cls_test;", classString);

classString = CssBuilder.Default()
.AddStyle("width", () => "cls_test", false)
.Build();
Assert.DoesNotContain("widht: cls_test;", classString);

classString = CssBuilder.Default()
.AddStyle("width", "cls_test", false)
.Build();
Assert.DoesNotContain("widht: cls_test;", classString);

classString = CssBuilder.Default()
.AddStyle("width", () => "cls_test", () => true)
.Build();
Assert.Contains("width: cls_test;", classString);

classString = CssBuilder.Default()
.AddStyle("width", () => "cls_test", true)
.Build();
Assert.Contains("width: cls_test;", classString);

classString = CssBuilder.Default()
.AddStyle("width", "cls_test", true)
.Build();
Assert.Contains("width: cls_test;", classString);

classString = CssBuilder.Default()
.AddStyle("width", "cls_test", () => true)
.Build();
Assert.Contains("width: cls_test;", classString);

classString = CssBuilder.Default()
.AddStyle("width", "cls_test_width")
.AddStyle("height", "cls_test_height")
.Build();
Assert.Equal("width: cls_test_width; height: cls_test_height;", classString);
}

[Fact]
public void AddClass_Builder()
{
Expand All @@ -37,6 +82,27 @@ public void AddClass_Builder()
Assert.Contains("cls_test", classString);
}

[Fact]
public void AddStyle_Builder()
{
var builder = CssBuilder.Default("width: cls_test_width;");

var classString = CssBuilder.Default()
.AddStyle(builder, false)
.Build();
Assert.DoesNotContain("width: cls_test_width;", classString);

classString = CssBuilder.Default()
.AddStyle(builder, () => true)
.Build();
Assert.Contains("width: cls_test_width;", classString);

classString = CssBuilder.Default()
.AddStyle(builder, true)
.Build();
Assert.Contains("width: cls_test_width;", classString);
}

[Fact]
public void AddStyleFromAttributes_Ok()
{
Expand Down