diff --git a/BlazorBootstrap.Demo.RCL/Pages/Form/NumberInput/NumberInput_Demo_02_Generic_Type.razor b/BlazorBootstrap.Demo.RCL/Pages/Form/NumberInput/NumberInput_Demo_02_Generic_Type.razor index ce7b01edc..6f005727e 100644 --- a/BlazorBootstrap.Demo.RCL/Pages/Form/NumberInput/NumberInput_Demo_02_Generic_Type.razor +++ b/BlazorBootstrap.Demo.RCL/Pages/Form/NumberInput/NumberInput_Demo_02_Generic_Type.razor @@ -1,41 +1,49 @@ 
+
Entered Number: @amount
+
Entered Number: @amount2
+
Entered Number: @amount3
+
Entered Number: @amount4
+
Entered Number: @amount5
+
Entered Number: @amount6
+
Entered Number: @amount7
+
Entered Number: @amount8
@code { diff --git a/BlazorBootstrap.Demo.RCL/Pages/Form/RangeInput/RangeInputDocumentation.razor b/BlazorBootstrap.Demo.RCL/Pages/Form/RangeInput/RangeInputDocumentation.razor index 967a0a210..90f22a243 100644 --- a/BlazorBootstrap.Demo.RCL/Pages/Form/RangeInput/RangeInputDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Pages/Form/RangeInput/RangeInputDocumentation.razor @@ -46,16 +46,15 @@
The Step parameter is a number that specifies the granularity that the value must adhere to. Only values that match the specified stepping interval are valid.
+ +
+ +
To add tick marks to a RangeInput, set the TickMarks parameter.
- - - - -
- + @code { private string pageUrl = "/form/range-input"; private string title = "Blazor RangeInput Component"; diff --git a/BlazorBootstrap.Demo.RCL/Pages/Form/RangeInput/RangeInput_Demo_06_Decimals.razor b/BlazorBootstrap.Demo.RCL/Pages/Form/RangeInput/RangeInput_Demo_05_Decimals.razor similarity index 77% rename from BlazorBootstrap.Demo.RCL/Pages/Form/RangeInput/RangeInput_Demo_06_Decimals.razor rename to BlazorBootstrap.Demo.RCL/Pages/Form/RangeInput/RangeInput_Demo_05_Decimals.razor index d950f5907..da11f1cde 100644 --- a/BlazorBootstrap.Demo.RCL/Pages/Form/RangeInput/RangeInput_Demo_06_Decimals.razor +++ b/BlazorBootstrap.Demo.RCL/Pages/Form/RangeInput/RangeInput_Demo_05_Decimals.razor @@ -1,5 +1,6 @@ -@amount1 +
@amount1
+ @code { decimal amount1 = 0; } \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Pages/Form/RangeInput/RangeInput_Demo_05_Tick_Marks.razor b/BlazorBootstrap.Demo.RCL/Pages/Form/RangeInput/RangeInput_Demo_06_Tick_Marks.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Pages/Form/RangeInput/RangeInput_Demo_05_Tick_Marks.razor rename to BlazorBootstrap.Demo.RCL/Pages/Form/RangeInput/RangeInput_Demo_06_Tick_Marks.razor diff --git a/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor b/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor index 69c30159b..8c372dbee 100644 --- a/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor +++ b/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor @@ -8,9 +8,9 @@ id="@ElementId" class="@ClassNames @fieldCssClasses" style="@StyleNames" - value="@Value" + value="@GetInvariantNumber(Value)" + step="@Step?.ToString(CultureInfo.InvariantCulture)" disabled="@Disabled" placeholder="@Placeholder" - step="@step" autocomplete="@autoComplete" @onchange="OnChange"/> diff --git a/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor.cs b/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor.cs index e23a872bf..2c54ac0b0 100644 --- a/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor.cs +++ b/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor.cs @@ -4,6 +4,8 @@ public partial class NumberInput : BlazorBootstrapComponentBase { #region Fields and Constants + private CultureInfo cultureInfo = default!; + private FieldIdentifier fieldIdentifier; private string step = default!; @@ -24,7 +26,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { - await JS.InvokeVoidAsync("window.blazorBootstrap.numberInput.initialize", ElementId, isFloatingNumber(), AllowNegativeNumbers); + await JS.InvokeVoidAsync("window.blazorBootstrap.numberInput.initialize", ElementId, isFloatingNumber(), AllowNegativeNumbers, cultureInfo.NumberFormat.NumberDecimalSeparator); var currentValue = Value; // object @@ -71,6 +73,15 @@ protected override async Task OnInitializedAsync() step = Step.HasValue ? $"{Step.Value}" : "any"; + try + { + cultureInfo = new CultureInfo(Locale); + } + catch (CultureNotFoundException) + { + cultureInfo = new CultureInfo("en-US"); + } + await base.OnInitializedAsync(); } @@ -84,6 +95,20 @@ protected override async Task OnInitializedAsync() /// public void Enable() => Disabled = false; + private string GetInvariantNumber(TValue value) + { + if (value is null) return string.Empty; + + if (value is float floatValue) return floatValue.ToString(CultureInfo.InvariantCulture); + + if (value is double doubleValue) return doubleValue.ToString(CultureInfo.InvariantCulture); + + if (value is decimal decimalValue) return decimalValue.ToString(CultureInfo.InvariantCulture); + + // All numbers without decimal places work fine by default + return value?.ToString() ?? string.Empty; + } + private bool isFloatingNumber() => typeof(TValue) == typeof(float) || typeof(TValue) == typeof(float?) @@ -290,7 +315,7 @@ private bool TryParseValue(object value, out TValue newValue) if (typeof(TValue) == typeof(float?) || typeof(TValue) == typeof(float)) { - newValue = (TValue)Convert.ChangeType(value, typeof(float)); + newValue = (TValue)Convert.ChangeType(value, typeof(float), CultureInfo.InvariantCulture); return true; } @@ -298,7 +323,7 @@ private bool TryParseValue(object value, out TValue newValue) if (typeof(TValue) == typeof(double?) || typeof(TValue) == typeof(double)) { - newValue = (TValue)Convert.ChangeType(value, typeof(double)); + newValue = (TValue)Convert.ChangeType(value, typeof(double), CultureInfo.InvariantCulture); return true; } @@ -306,7 +331,7 @@ private bool TryParseValue(object value, out TValue newValue) if (typeof(TValue) == typeof(decimal?) || typeof(TValue) == typeof(decimal)) { - newValue = (TValue)Convert.ChangeType(value, typeof(decimal)); + newValue = (TValue)Convert.ChangeType(value, typeof(decimal), CultureInfo.InvariantCulture); return true; } @@ -362,6 +387,13 @@ private bool TryParseValue(object value, out TValue newValue) private string fieldCssClasses => EditContext?.FieldCssClass(fieldIdentifier) ?? ""; + /// + /// Gets or sets the locale. Default locale is 'en-US'. + /// + [Parameter] + //[EditorRequired] + public string Locale { get; set; } = "en-US"; + /// /// Gets or sets the max. /// Max ignored if EnableMinMax="false". diff --git a/blazorbootstrap/Components/Form/RangeInput/RangeInput.razor.cs b/blazorbootstrap/Components/Form/RangeInput/RangeInput.razor.cs index d8fd0d11c..3cc2eedf4 100644 --- a/blazorbootstrap/Components/Form/RangeInput/RangeInput.razor.cs +++ b/blazorbootstrap/Components/Form/RangeInput/RangeInput.razor.cs @@ -104,6 +104,20 @@ public async Task bsOnInput(object? newValue) /// public void Enable() => Disabled = false; + private string GetInvariantNumber(TValue value) + { + if (value is null) return string.Empty; + + if (value is float floatValue) return floatValue.ToString(CultureInfo.InvariantCulture); + + if (value is double doubleValue) return doubleValue.ToString(CultureInfo.InvariantCulture); + + if (value is decimal decimalValue) return decimalValue.ToString(CultureInfo.InvariantCulture); + + // All numbers without decimal places work fine by default + return value?.ToString() ?? string.Empty; + } + private async Task HandleChangeAsync() { await ValueChanged.InvokeAsync(Value); @@ -284,31 +298,6 @@ private void SetValue(object? newValue) Value = value; } - private string GetInvariantNumber(TValue value) - { - if (value is null) - { - return string.Empty; - } - - if (value is float floatValue) - { - return floatValue.ToString(CultureInfo.InvariantCulture); - } - - if (value is double doubleValue) - { - return doubleValue.ToString(CultureInfo.InvariantCulture); - } - - if (value is decimal decimalValue) - { - return decimalValue.ToString(CultureInfo.InvariantCulture); - } - - // All numbers without decimal places work fine by default - return value?.ToString() ?? string.Empty; - } private bool TryParseValue(object value, out TValue newValue) { try diff --git a/blazorbootstrap/wwwroot/blazor.bootstrap.js b/blazorbootstrap/wwwroot/blazor.bootstrap.js index 0f47a974b..071ab51df 100644 --- a/blazorbootstrap/wwwroot/blazor.bootstrap.js +++ b/blazorbootstrap/wwwroot/blazor.bootstrap.js @@ -467,13 +467,15 @@ window.blazorBootstrap = { } }, numberInput: { - initialize: (elementId, isFloat, allowNegativeNumbers) => { + initialize: (elementId, isFloat, allowNegativeNumbers, numberDecimalSeparator) => { let numberEl = document.getElementById(elementId); numberEl?.addEventListener('keydown', function (event) { let invalidChars = ["e", "E", "+"]; - if (!isFloat) + if (!isFloat) { invalidChars.push("."); // restrict '.' for integer types + invalidChars.push(numberDecimalSeparator); // restrict ',' for specific culture + } if (!allowNegativeNumbers) { invalidChars.push("-"); // restrict '-' diff --git a/docs/docs/04-forms/number-input.mdx b/docs/docs/04-forms/number-input.mdx index dcb0138db..95911ded7 100644 --- a/docs/docs/04-forms/number-input.mdx +++ b/docs/docs/04-forms/number-input.mdx @@ -25,6 +25,7 @@ Blazor Bootstrap `NumberInput` component is built around HTML input of `type="nu | AutoComplete | bool | false | | Indicates whether the NumberInput can complete the values automatically by the browser. | | Disabled | bool | false | | Gets or sets the disabled. | | EnableMinMax | bool | false | | Determines whether to restrict the user input to Min and Max range. If true, restricts the user input between the Min and Max range. Else accepts the user input. | +| Locale | string | `en-US` | ✔️ | Gets or sets the locale. | | Max| TValue | | | Gets or sets the max. Max ignored if EnableMinMax="false". | | Min| TValue | | | Gets or sets the min. Min ignored if EnableMinMax="false". | | Placeholder | string? | null | | Gets or sets the placeholder. | @@ -36,8 +37,8 @@ Blazor Bootstrap `NumberInput` component is built around HTML input of `type="nu | Name | Description | |:--|:--| -| Disable | Disables number input. | -| Enable | Enables number input. | +| Disable() | Disables number input. | +| Enable() | Enables number input. | ## Events @@ -75,45 +76,53 @@ By default, `e + -` are blocked. For all integral numeric types, dot `.` is bloc Blazor Bootstrap: Number Input Component - Generic type -```cshtml {3,8,13,18,23,28,33,38} showLineNumbers +```cshtml {3,9,15,21,27,33,39,45} showLineNumbers
+
Entered Number: @amount
+
Entered Number: @amount2
+
Entered Number: @amount3
+
Entered Number: @amount4
+
Entered Number: @amount5
+
Entered Number: @amount6
+
Entered Number: @amount7
+
Entered Number: @amount8
``` @@ -464,4 +473,4 @@ This event fires on every user keystroke that changes the `NumberInput` value. } ``` -[See demo here](https://demos.blazorbootstrap.com/form/number-input#event-value-changed) \ No newline at end of file +[See demo here](https://demos.blazorbootstrap.com/form/number-input#event-value-changed) diff --git a/docs/docs/04-forms/range-input.mdx b/docs/docs/04-forms/range-input.mdx index a538ea5c7..a70e1d124 100644 --- a/docs/docs/04-forms/range-input.mdx +++ b/docs/docs/04-forms/range-input.mdx @@ -224,10 +224,27 @@ The `Step` parameter is a number that specifies the granularity that the value m [See demo here](https://demos.blazorbootstrap.com/form/range-input#step) +### Decimals + +Blazor Bootstrap: Range Input Component - Decimals + +```cshtml {} showLineNumbers + +
@amount1
+``` + +```cs {} showLineNumbers +@code { + decimal amount1 = 0; +} +``` + +[See demo here](https://demos.blazorbootstrap.com/form/range-input#decimals) + ### Tick marks To add tick marks to a `RangeInput`, set the `TickMarks` parameter. -` + Blazor Bootstrap: Range Input Component - Tick marks ```cshtml {3} showLineNumbers diff --git a/docs/package.json b/docs/package.json index 44a8d6de6..a3ea95552 100644 --- a/docs/package.json +++ b/docs/package.json @@ -1,6 +1,6 @@ { "name": "blazorbootstrap", - "version": "2.0.0", + "version": "2.1.0", "private": true, "scripts": { "docusaurus": "docusaurus",