Skip to content

Commit bf7b859

Browse files
committed
Add boolean input component
1 parent 2a336c6 commit bf7b859

File tree

3 files changed

+430
-0
lines changed

3 files changed

+430
-0
lines changed
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
using Microsoft.AspNetCore.Components;
2+
using Microsoft.AspNetCore.Components.Rendering;
3+
4+
namespace Privileged.Components;
5+
6+
/// <summary>
7+
/// A custom input component for selecting boolean values (<c>bool</c> or <c>bool?</c>).
8+
/// </summary>
9+
/// <typeparam name="TValue">The type of the value bound to the input. Must be <c>bool</c> or <c>bool?</c>.</typeparam>
10+
public class PrivilegeInputBoolean<TValue> : PrivilegeInputSelect<TValue>
11+
{
12+
/// <summary>
13+
/// The label to display for the null option (only shown for <c>bool?</c>). Defaults to "- select -".
14+
/// </summary>
15+
[Parameter]
16+
public string NullLabel { get; set; } = "- select -";
17+
18+
/// <summary>
19+
/// The label to display for the true option. Defaults to "True".
20+
/// </summary>
21+
[Parameter]
22+
public string TrueLabel { get; set; } = "True";
23+
24+
/// <summary>
25+
/// The label to display for the false option. Defaults to "False".
26+
/// </summary>
27+
[Parameter]
28+
public string FalseLabel { get; set; } = "False";
29+
30+
/// <summary>
31+
/// Called when component parameters are set. Ensures only <c>bool</c> or <c>bool?</c> are allowed and sets the default child content.
32+
/// </summary>
33+
/// <exception cref="InvalidOperationException">Thrown if <typeparamref name="TValue"/> is not <c>bool</c> or <c>bool?</c>.</exception>
34+
protected override void OnParametersSet()
35+
{
36+
base.OnParametersSet();
37+
38+
if (typeof(TValue) != typeof(bool) && typeof(TValue) != typeof(bool?))
39+
throw new InvalidOperationException("Component only supports bool or bool? types.");
40+
41+
ChildContent ??= RenderBooleanOptions;
42+
}
43+
44+
/// <summary>
45+
/// Converts the value to a string for rendering in the select element.
46+
/// </summary>
47+
/// <param name="value">The value to format.</param>
48+
/// <returns>
49+
/// "true" or "false" for <c>bool</c> and <c>bool?</c> values, <c>null</c> for a null <c>bool?</c>, or the base implementation for other types.
50+
/// </returns>
51+
protected override string? FormatValueAsString(TValue? value)
52+
{
53+
if (typeof(TValue) == typeof(bool))
54+
{
55+
if (value is bool b)
56+
return b ? "true" : "false";
57+
58+
return "false";
59+
}
60+
else if (typeof(TValue) == typeof(bool?))
61+
{
62+
if (value is null)
63+
return null;
64+
65+
if (value is bool b)
66+
return b ? "true" : "false";
67+
68+
return null;
69+
}
70+
71+
return base.FormatValueAsString(value);
72+
}
73+
74+
/// <summary>
75+
/// Renders the boolean options for the select element.
76+
/// Includes a null option for <c>bool?</c> types.
77+
/// </summary>
78+
/// <param name="builder">The <see cref="RenderTreeBuilder"/> used to build the options.</param>
79+
protected void RenderBooleanOptions(RenderTreeBuilder builder)
80+
{
81+
if (typeof(TValue) == typeof(bool?))
82+
{
83+
builder.OpenElement(0, "option");
84+
builder.AddAttribute(1, "value", "");
85+
builder.AddContent(2, NullLabel);
86+
builder.CloseElement();
87+
}
88+
89+
builder.OpenElement(3, "option");
90+
builder.AddAttribute(4, "value", "true");
91+
builder.AddContent(5, TrueLabel);
92+
builder.CloseElement();
93+
94+
builder.OpenElement(6, "option");
95+
builder.AddAttribute(7, "value", "false");
96+
builder.AddContent(8, FalseLabel);
97+
builder.CloseElement();
98+
}
99+
}

0 commit comments

Comments
 (0)