diff --git a/EgwCoreLib.BlazorTest/Data/TestData.cs b/EgwCoreLib.BlazorTest/Data/TestData.cs index da6bd65..4908dc1 100644 --- a/EgwCoreLib.BlazorTest/Data/TestData.cs +++ b/EgwCoreLib.BlazorTest/Data/TestData.cs @@ -7,6 +7,7 @@ namespace EgwCoreLib.BlazorTest.Data public static Dictionary MenuList { get; set; } = new() { {"TestPdfViewer", "Test PdfViewer"}, + {"TestInput", "Test Input Ext"}, {"TestQrDisplay", "Test QrDisplay"}, {"TestGraphCompo", "Test Graph Compo"}, {"TestBarcodeReader", "Test Barcode Read"}, diff --git a/EgwCoreLib.BlazorTest/Pages/TestInput.razor b/EgwCoreLib.BlazorTest/Pages/TestInput.razor new file mode 100644 index 0000000..16f3551 --- /dev/null +++ b/EgwCoreLib.BlazorTest/Pages/TestInput.razor @@ -0,0 +1,50 @@ +@page "/TestInput" + +TestInput + + +
+
+

Test Input Specializzati

+
+
+
+
+
+ Decimal +
+
+ + Decimal 0 +
+
+ + Decimal 3 +
+
+
+
+ Percentage +
+
+ + Percent P0 +
+
+ + Percent P2 +
+
+ + Percent P2 Invariant +
+
+
+
+
+
+ +@code { + private decimal DecimalValue = 0; + private decimal PercValue = 0.123M; +} diff --git a/EgwCoreLib.Razor/InputDecimal.razor b/EgwCoreLib.Razor/InputDecimal.razor new file mode 100644 index 0000000..80cd1c8 --- /dev/null +++ b/EgwCoreLib.Razor/InputDecimal.razor @@ -0,0 +1,64 @@ +@using System.Globalization + + +@code { + /// + /// Actual bind value + /// + [Parameter] + public decimal Value { get; set; } + + /// + /// Event for value changed + /// + [Parameter] + public EventCallback ValueChanged { get; set; } + + /// + /// Numero di cifre decimali gestite + /// + [Parameter] + public int Decimals { get; set; } = 3; + + /// + /// Step incremento + /// + [Parameter] + public decimal Step { get; set; } = 0.001M; + + /// + /// Valore minimo ammesso + /// + [Parameter] + public decimal? Min { get; set; } + + /// + /// Valore massimo ammesso + /// + [Parameter] + public decimal? Max { get; set; } + + /// + /// CssClass for input component + /// + [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); + } + } +} diff --git a/EgwCoreLib.Razor/InputPercent.razor b/EgwCoreLib.Razor/InputPercent.razor new file mode 100644 index 0000000..534ea11 --- /dev/null +++ b/EgwCoreLib.Razor/InputPercent.razor @@ -0,0 +1,89 @@ +@using System.Globalization + + +@code { + /// + /// Actual bind value + /// + [Parameter] + public decimal Value { get; set; } + + /// + /// Event for value changed + /// + [Parameter] + public EventCallback ValueChanged { get; set; } + + /// + /// CssClass for input component + /// + [Parameter] + public string CssClass { get; set; } = string.Empty; + + /// + /// Number of decimal places to display in percentage format. + /// Example: Decimals=2 → "15.00%". + /// + [Parameter] + public int Decimals { get; set; } = 2; + + /// + /// If true, parsing is always done with InvariantCulture. + /// If false (default), try CurrentCulture first, then InvariantCulture. + /// + [Parameter] + public bool ForceInvariantParsing { get; set; } = false; + + /// + /// Percentage format string + /// + private string DisplayValue => Value.ToString($"P{Decimals}"); + + /// + /// Change value event + /// + 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); + } + } +} diff --git a/EgwCoreLib.Utils/DictUtils.cs b/EgwCoreLib.Utils/DictUtils.cs new file mode 100644 index 0000000..d8eb7f3 --- /dev/null +++ b/EgwCoreLib.Utils/DictUtils.cs @@ -0,0 +1,40 @@ +namespace EgwCoreLib.Utils +{ + public class DictUtils + { + #region Public Methods + + /// + /// Comparatore equality obj dizionario + /// + /// + /// + /// + /// + /// + public static bool DictAreEqual(Dictionary dict1, Dictionary 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.Default.Equals(kvp.Value, value)) + return false; // Value mismatch + } + + return true; + } + + #endregion Public Methods + } +}