I’ve recently been trying C# Blazor for web application development, and found the <InputNumber />
experience to be a little unintuitive from a user-experience perspective.
The following component – which I’m calling InputParsable
– when rendered via InteractiveServer
will attempt to parse the value and “correct” user input in near real-time. You can see a demonstration of this below.
NB: This generates client/server traffic per keypress, and may not be runtime efficient on the server. This almost certainly is not an appropriate solution for traffic heavy applications – but appears to work in lightweight conditions.
Advantages over <InputNumber>
and <InputTex
t>:
- User is given near real-time feedback of mistakes when inputting data
- Input supports
nullable
and unsigned types (uint
, for example, as shown in the screen grab below) - Uses a plain
text
input, which may be preferred from a browser perspective, over number
(although could easily be modified to use either).
The TryParseValueFromString
may be an appropriate place for adding max
and min
constraints too, if you want those handled in near real-time as well.
@using System.Linq.Expressions
@using System.Numerics
@using System.ComponentModel
@using System.Diagnostics.CodeAnalysis
@typeparam TValue
@inherits InputBase<TValue>
<input @attributes="@AdditionalAttributes" @bind="@CurrentValueAsString" @bind:event="oninput" />
@code {
protected override bool TryParseValueFromString(string? value, [MaybeNullWhen(false)] out TValue? result, [NotNullWhen(false)] out string? validationErrorMessage)
{
// Cite: https://stackoverflow.com/a/2961702/817132
validationErrorMessage = null;
var converter = TypeDescriptor.GetConverter(typeof(TValue));
if (converter is null)
{
throw new NotSupportedException("No converter is available via TypeDescriptor.GetConverter for this type.");
}
try
{
result = (TValue?)converter.ConvertFromString(value ?? "");
}
catch
{
// restore the previous value.
// this behaves more as an near-realtime input constraint -
// rather than reverting to a default value on bad input.
result = Value;
}
return true;
}
}
Full credit to the luke on StackOverflow for the core of the solution.