90 lines
2.4 KiB
Plaintext
90 lines
2.4 KiB
Plaintext
@using System.Globalization
|
|
<input value="@DisplayValue"
|
|
@onchange="OnChange"
|
|
class="@CssClass" />
|
|
|
|
@code {
|
|
/// <summary>
|
|
/// Actual bind value
|
|
/// </summary>
|
|
[Parameter]
|
|
public decimal Value { get; set; }
|
|
|
|
/// <summary>
|
|
/// Event for value changed
|
|
/// </summary>
|
|
[Parameter]
|
|
public EventCallback<decimal> ValueChanged { get; set; }
|
|
|
|
/// <summary>
|
|
/// CssClass for input component
|
|
/// </summary>
|
|
[Parameter]
|
|
public string CssClass { get; set; } = string.Empty;
|
|
|
|
/// <summary>
|
|
/// Number of decimal places to display in percentage format.
|
|
/// Example: Decimals=2 → "15.00%".
|
|
/// </summary>
|
|
[Parameter]
|
|
public int Decimals { get; set; } = 2;
|
|
|
|
/// <summary>
|
|
/// If true, parsing is always done with InvariantCulture.
|
|
/// If false (default), try CurrentCulture first, then InvariantCulture.
|
|
/// </summary>
|
|
[Parameter]
|
|
public bool ForceInvariantParsing { get; set; } = false;
|
|
|
|
/// <summary>
|
|
/// Percentage format string
|
|
/// </summary>
|
|
private string DisplayValue => Value.ToString($"P{Decimals}");
|
|
|
|
/// <summary>
|
|
/// Change value event
|
|
/// </summary>
|
|
private async Task OnChange(ChangeEventArgs e)
|
|
{
|
|
var input = e.Value?.ToString()?.Trim();
|
|
|
|
if (string.IsNullOrWhiteSpace(input))
|
|
{
|
|
Value = 0;
|
|
await ValueChanged.InvokeAsync(0);
|
|
return;
|
|
}
|
|
|
|
// Remove % if present
|
|
var cleaned = input.Replace("%", "").Trim();
|
|
|
|
decimal parsed;
|
|
bool success;
|
|
|
|
if (ForceInvariantParsing)
|
|
{
|
|
// Option 3: Always invariant
|
|
success = decimal.TryParse(cleaned, NumberStyles.Any, CultureInfo.InvariantCulture, out parsed);
|
|
}
|
|
else
|
|
{
|
|
// Option 2: Try current culture, then invariant
|
|
success = decimal.TryParse(cleaned, NumberStyles.Any, CultureInfo.CurrentCulture, out parsed)
|
|
|| decimal.TryParse(cleaned, NumberStyles.Any, CultureInfo.InvariantCulture, out parsed);
|
|
}
|
|
|
|
if (success)
|
|
{
|
|
decimal result = parsed <= 1 ? parsed : parsed / 100;
|
|
Value = result;
|
|
await ValueChanged.InvokeAsync(result);
|
|
}
|
|
else
|
|
{
|
|
// Invalid input → reset to 0
|
|
Value = 0;
|
|
await ValueChanged.InvokeAsync(0);
|
|
}
|
|
}
|
|
}
|