-
-
Notifications
You must be signed in to change notification settings - Fork 71
/
Copy pathHxSmartComboBox.cs
134 lines (111 loc) · 5.95 KB
/
HxSmartComboBox.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;
using Havit.Blazor.Components.Web.Bootstrap.Internal;
using Microsoft.AspNetCore.Components.Rendering;
namespace Havit.Blazor.Components.Web.Bootstrap.Smart;
/// <summary>
/// Smart ComboBox is an AI upgrade to the traditional combo box.<br />
/// Traditional combo boxes suggest values only based on exact substring matches.
/// Smart ComboBox upgrades this by suggesting semantic matches
/// (i.e., options with the most closely related meanings).
/// This is much more helpful for users who don't know/remember
/// the exact predefined string they are looking for.<br />
/// <code>HxSmartComboBox</code> derives from <see href="https://github.com/dotnet-smartcomponents/smartcomponents/blob/main/docs/smart-combobox.md">SmartComboBox</see>,
/// a component created by the Microsoft Blazor team.
/// It extends the original component with Bootstrap styling and Hx-component features.
/// </summary>
public class HxSmartComboBox : HxInputBaseWithInputGroups<string>, IInputWithPlaceholder, IInputWithSize, IInputWithLabelType
{
/// <summary>
/// Application-wide defaults for the <see cref="HxInputFile"/> and derived components.<br />
/// Full documentation and demos: <see href="https://havit.blazor.eu/components/HxInputText">https://havit.blazor.eu/components/HxInputText</see>.
/// </summary>
public static InputTextSettings Defaults { get; set; }
static HxSmartComboBox()
{
Defaults = new InputTextSettings();
}
/// <summary>
/// Returns application-wide defaults for the component.
/// Enables overriding defaults in descendants (use a separate set of defaults).
/// </summary>
protected override InputTextSettings GetDefaults() => Defaults;
/// <summary>
/// Set of settings to be applied to the component instance (overrides <see cref="HxInputText.Defaults"/>, overridden by individual parameters).
/// </summary>
[Parameter] public InputTextSettings Settings { get; set; }
/// <summary>
/// Returns an optional set of component settings.
/// </summary>
/// <remarks>
/// Similar to <see cref="GetDefaults"/>, enables defining wider <see cref="Settings"/> in component descendants (by returning a derived settings class).
/// </remarks>
protected override InputTextSettings GetSettings() => Settings;
/// <summary>
/// API endpoint that Smart ComboBox will call to get suggestions.
/// </summary>
[Parameter, EditorRequired] public string Url { get; set; }
/// <summary>
/// Maximum number of suggestions offered. Default is <code>10</code>.
/// </summary>
[Parameter] public int MaxSuggestions { get; set; } = 10;
/// <summary>
/// Minimal similarity coefficient for an item to be offered. Default is <code>0.5</code>.
/// </summary>
[Parameter] public float SimilarityThreshold { get; set; } = 0.5f;
/// <summary>
/// The maximum number of characters (UTF-16 code units) that the user can enter.<br />
/// If the parameter value isn't specified, the <see cref="System.ComponentModel.DataAnnotations.MaxLengthAttribute"/> of the <c>Value</c> is checked and used.<br />
/// If not specified either, the user can enter an unlimited number of characters.
/// </summary>
[Parameter] public int? MaxLength { get; set; }
/// <summary>
/// Hint to browsers as to the type of virtual keyboard configuration to use when editing.<br/>
/// The default is <c>null</c> (not set).
/// </summary>
[Parameter] public InputMode? InputMode { get; set; }
protected InputMode? InputModeEffective => InputMode ?? GetSettings()?.InputMode ?? GetDefaults()?.InputMode;
/// <summary>
/// Placeholder for the input.
/// </summary>
[Parameter] public string Placeholder { get; set; }
/// <summary>
/// Size of the input.
/// </summary>
[Parameter] public InputSize? InputSize { get; set; }
protected InputSize InputSizeEffective => InputSize ?? GetSettings()?.InputSize ?? GetDefaults()?.InputSize ?? HxSetup.Defaults.InputSize; InputSize IInputWithSize.InputSizeEffective => InputSizeEffective;
/// <inheritdoc cref="Bootstrap.LabelType" />
[Parameter] public LabelType? LabelType { get; set; }
protected LabelType LabelTypeEffective => LabelType ?? GetSettings()?.LabelType ?? GetDefaults()?.LabelType ?? HxSetup.Defaults.LabelType;
LabelType IInputWithLabelType.LabelTypeEffective => LabelTypeEffective;
protected override void BuildRenderInput(RenderTreeBuilder builder)
{
RenderWithAutoCreatedEditContextAsCascadingValue(builder, 0, BuildRenderInputCore);
}
protected virtual void BuildRenderInputCore(RenderTreeBuilder builder)
{
LabelType labelTypeEffective = (this as IInputWithLabelType).LabelTypeEffective;
builder.OpenComponent<SmartComboBox>(1);
builder.AddAttribute(100, nameof(Value), Value);
builder.AddAttribute(101, nameof(ValueChanged), EventCallback.Factory.Create<string>(this, value => CurrentValue = value));
builder.AddAttribute(102, nameof(ValueExpression), ValueExpression);
builder.AddAttribute(103, nameof(Url), Url);
builder.AddAttribute(104, nameof(MaxSuggestions), MaxSuggestions);
builder.AddAttribute(105, nameof(SimilarityThreshold), SimilarityThreshold);
builder.AddAttribute(200, "id", InputId);
builder.AddAttribute(201, "class", CssClassHelper.Combine("smartcombobox", GetInputCssClassToRender()));
builder.AddAttribute(202, "disabled", EnabledEffective ? (bool?)null : true);
builder.AddAttribute(204, "placeholder", (labelTypeEffective == Havit.Blazor.Components.Web.Bootstrap.LabelType.Floating) ? "placeholder" : Placeholder);
int? maxLengthEffective = MaxLength ?? GetValueAttribute<MaxLengthAttribute>()?.Length;
if (maxLengthEffective > 0) // [MaxLength] attribute has a default value of -1
{
builder.AddAttribute(300, "maxlength", maxLengthEffective);
}
builder.AddMultipleAttributes(300, AdditionalAttributes);
builder.CloseComponent();
}
protected override bool TryParseValueFromString(string value, [MaybeNullWhen(false)] out string result, [NotNullWhen(false)] out string validationErrorMessage)
{
throw new NotSupportedException();
}
}