Merge branch 'release/AddInputSpecialCompo'

This commit is contained in:
Samuele Locatelli
2025-11-03 11:12:12 +01:00
5 changed files with 244 additions and 0 deletions
+1
View File
@@ -7,6 +7,7 @@ namespace EgwCoreLib.BlazorTest.Data
public static Dictionary<string, string> MenuList { get; set; } = new()
{
{"TestPdfViewer", "Test PdfViewer"},
{"TestInput", "Test Input Ext"},
{"TestQrDisplay", "Test QrDisplay"},
{"TestGraphCompo", "Test Graph Compo"},
{"TestBarcodeReader", "Test Barcode Read"},
@@ -0,0 +1,50 @@
@page "/TestInput"
<PageTitle>TestInput</PageTitle>
<div class="card">
<div class="card-header">
<h3>Test Input Specializzati</h3>
</div>
<div class="card-body py-1">
<div class="row">
<div class="col-4">
<div class="fs-4">
Decimal
</div>
<div class="input-group">
<InputDecimal Decimals="0" Step="0.001M" CssClass="form-control form-control-lg text-end w-auto" @bind-Value="@DecimalValue"></InputDecimal>
<span class="input-group-text">Decimal 0</span>
</div>
<div class="input-group">
<InputDecimal Decimals="3" Step="0.001M" CssClass="form-control form-control-lg text-end w-auto" @bind-Value="@DecimalValue"></InputDecimal>
<span class="input-group-text">Decimal 3</span>
</div>
</div>
<div class="col-4">
<div class="fs-4">
Percentage
</div>
<div class="input-group">
<InputPercent CssClass="form-control form-control-lg text-end w-auto" @bind-Value="@PercValue" Decimals="0"></InputPercent>
<span class="input-group-text">Percent P0</span>
</div>
<div class="input-group">
<InputPercent CssClass="form-control form-control-lg text-end w-auto" @bind-Value="@PercValue" Decimals="2"></InputPercent>
<span class="input-group-text">Percent P2</span>
</div>
<div class="input-group">
<InputPercent CssClass="form-control form-control-lg text-end w-auto" @bind-Value="@PercValue" Decimals="2" ForceInvariantParsing="true"></InputPercent>
<span class="input-group-text">Percent P2 Invariant</span>
</div>
</div>
<div class="col-4"></div>
</div>
</div>
</div>
@code {
private decimal DecimalValue = 0;
private decimal PercValue = 0.123M;
}
+64
View File
@@ -0,0 +1,64 @@
@using System.Globalization
<input type="number"
value="@FormattedValue"
@onchange="OnChange"
step="@Step.ToString(CultureInfo.InvariantCulture)"
min="@(Min?.ToString(CultureInfo.InvariantCulture))"
max="@(Max?.ToString(CultureInfo.InvariantCulture))"
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>
/// Numero di cifre decimali gestite
/// </summary>
[Parameter]
public int Decimals { get; set; } = 3;
/// <summary>
/// Step incremento
/// </summary>
[Parameter]
public decimal Step { get; set; } = 0.001M;
/// <summary>
/// Valore minimo ammesso
/// </summary>
[Parameter]
public decimal? Min { get; set; }
/// <summary>
/// Valore massimo ammesso
/// </summary>
[Parameter]
public decimal? Max { get; set; }
/// <summary>
/// CssClass for input component
/// </summary>
[Parameter]
public string CssClass { get; set; } = string.Empty;
private string FormattedValue => Value.ToString($"F{Decimals}", CultureInfo.InvariantCulture);
private async Task OnChange(ChangeEventArgs e)
{
if (decimal.TryParse(e.Value?.ToString(), NumberStyles.Any, CultureInfo.InvariantCulture, out var parsed))
{
var rounded = Math.Round(parsed, Decimals);
Value = rounded;
await ValueChanged.InvokeAsync(rounded);
}
}
}
+89
View File
@@ -0,0 +1,89 @@
@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);
}
}
}
+40
View File
@@ -0,0 +1,40 @@
namespace EgwCoreLib.Utils
{
public class DictUtils
{
#region Public Methods
/// <summary>
/// Comparatore equality obj dizionario
/// </summary>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TValue"></typeparam>
/// <param name="dict1"></param>
/// <param name="dict2"></param>
/// <returns></returns>
public static bool DictAreEqual<TKey, TValue>(Dictionary<TKey, TValue> dict1, Dictionary<TKey, TValue> dict2)
{
// Handle null cases
if (dict1 == null || dict2 == null)
return dict1 == dict2;
// Quick size check
if (dict1.Count != dict2.Count)
return false;
// Compare each key-value pair
foreach (var kvp in dict1)
{
if (!dict2.TryGetValue(kvp.Key, out TValue value))
return false; // Key missing in dict2
if (!EqualityComparer<TValue>.Default.Equals(kvp.Value, value))
return false; // Value mismatch
}
return true;
}
#endregion Public Methods
}
}