Number Input - mousewheeel fix, prevent of enetering flase characters
This commit is contained in:
parent
ed15c8f24d
commit
1fd0028557
@ -5,18 +5,18 @@
|
||||
@typeparam NumberType
|
||||
|
||||
<div class="@InputFieldClassList">
|
||||
<input type="number"
|
||||
<input type="text"
|
||||
placeholder="@Placeholder"
|
||||
step="@_step"
|
||||
disabled="@Disabled"
|
||||
readonly="@Readonly"
|
||||
@onmousewheel="@OnMouseWheel"
|
||||
@onwheel="@OnMouseWheel"
|
||||
@oninput=@ChangeValueAsync
|
||||
@bind-value="@Value"
|
||||
@attributes="@InputAttributes">
|
||||
</input>
|
||||
|
||||
@onkeydown=@(args => ChangeValue(args))
|
||||
@onkeydown:preventDefault="@_preventDefaultAction"
|
||||
@oninput=@GetValueAsync
|
||||
@onmousewheel=@OnMouseWheel
|
||||
@onwheel="OnMouseWheel"
|
||||
@bind-value="@_value"
|
||||
@attributes="@InputAttributes" />
|
||||
|
||||
<span class="highlight"></span>
|
||||
<span class="bar"></span>
|
||||
@ -34,6 +34,10 @@
|
||||
}
|
||||
<span class="input-glyph-wraper">
|
||||
<span class="input-glyph">
|
||||
<span style="display:inline-block">
|
||||
<Glyph Width=16 Height=16 SVG="@Icons.Material.Outlined.KeyboardArrowUp" Click="StepUp" />
|
||||
<Glyph Width=16 Height=16 SVG="@Icons.Material.Outlined.KeyboardArrowDown" Click="StepDown"></Glyph>
|
||||
</span>
|
||||
@if (Clearable && Value.ToString().Length > 0)
|
||||
{
|
||||
<span class="input-glyph button" @onclick="Clear">
|
||||
|
@ -3,11 +3,11 @@ using Connected.Utilities;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using System.Numerics;
|
||||
using static Connected.Colors;
|
||||
|
||||
namespace Connected.Components;
|
||||
public partial class NumberInput<NumberType>:InputBase where NumberType : INumber<NumberType>
|
||||
{
|
||||
|
||||
private double _step =1;
|
||||
[Parameter]
|
||||
public double Step {
|
||||
@ -22,30 +22,56 @@ public partial class NumberInput<NumberType>:InputBase where NumberType : INumbe
|
||||
}
|
||||
|
||||
[Parameter]
|
||||
public bool DisableMouseWheel { get; set; } = false;
|
||||
public bool DisableMouseWheel
|
||||
{
|
||||
get;
|
||||
set;
|
||||
} = false;
|
||||
|
||||
private async Task StepUp()
|
||||
{
|
||||
try
|
||||
{
|
||||
double num = (double)Convert.ChangeType(Value, typeof(double));
|
||||
num += _step;
|
||||
Value = AdjustDecimalPlaces((NumberType)Convert.ChangeType(num, typeof(NumberType)));
|
||||
if (DecimalPlaces > 0)
|
||||
num = Math.Round(num, DecimalPlaces);
|
||||
Value = (NumberType)Convert.ChangeType(num, typeof(NumberType));
|
||||
if (IsError) ErrorText = string.Empty;
|
||||
}
|
||||
catch
|
||||
{
|
||||
ErrorText = "Error with step up!";
|
||||
Value = default(NumberType);
|
||||
}
|
||||
await ValueChanged.InvokeAsync(Value);
|
||||
}
|
||||
|
||||
private async Task StepDown()
|
||||
{
|
||||
try
|
||||
{
|
||||
double num = (double)Convert.ChangeType(Value, typeof(double));
|
||||
|
||||
num -= _step;
|
||||
Value = AdjustDecimalPlaces((NumberType)Convert.ChangeType(num, typeof(NumberType)));
|
||||
if (DecimalPlaces > 0)
|
||||
num = Math.Round(num, DecimalPlaces);
|
||||
Value = (NumberType)Convert.ChangeType(num, typeof(NumberType));
|
||||
if (IsError) ErrorText = string.Empty;
|
||||
} catch
|
||||
{
|
||||
ErrorText = "Error with step down!";
|
||||
Value = default(NumberType);
|
||||
}
|
||||
await ValueChanged.InvokeAsync(Value);
|
||||
}
|
||||
protected async Task OnMouseWheel(WheelEventArgs obj)
|
||||
protected async Task OnMouseWheel(WheelEventArgs args)
|
||||
{
|
||||
if (DisableMouseWheel==false)
|
||||
if (DisableMouseWheel == false)
|
||||
{
|
||||
if (!obj.ShiftKey || Disabled || Readonly)
|
||||
if (args.ShiftKey || Disabled || Readonly)
|
||||
return;
|
||||
if (obj.DeltaY < 0)
|
||||
if (args.DeltaY >= 0)
|
||||
{
|
||||
await StepDown();
|
||||
}
|
||||
@ -53,69 +79,136 @@ public partial class NumberInput<NumberType>:InputBase where NumberType : INumbe
|
||||
{
|
||||
await StepUp();
|
||||
}
|
||||
} else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private string _value;
|
||||
|
||||
[Parameter]
|
||||
public NumberType Value
|
||||
public NumberType? Value
|
||||
{
|
||||
get;
|
||||
set;
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(_value)) return default(NumberType);
|
||||
return (NumberType)Convert.ChangeType(_value, typeof(NumberType));
|
||||
}
|
||||
set
|
||||
{
|
||||
_value = value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[Parameter]
|
||||
public int DecimalPlaces { get; set; } =0;
|
||||
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<NumberType> ValueChanged { get; set; }
|
||||
|
||||
public async Task ChangeValueAsync(ChangeEventArgs args)
|
||||
public async Task GetValueAsync(ChangeEventArgs args)
|
||||
{
|
||||
if (args.Value is not null)
|
||||
{
|
||||
NumberType value = (NumberType)Convert.ChangeType(args.Value, typeof(NumberType));
|
||||
if (value.ToString().Length <= 0)
|
||||
string newVal = args.Value.ToString();
|
||||
if (!newVal.Equals("0"))
|
||||
{
|
||||
|
||||
value = (NumberType)Convert.ChangeType(0, typeof(NumberType));
|
||||
if (newVal.ToString().Contains("-"))
|
||||
newVal = "-" + newVal.ToString().Replace("-", "");
|
||||
if (newVal.ToString().ToLower().Contains("e"))
|
||||
newVal = "e" + newVal.ToString().Replace("e", "");
|
||||
}
|
||||
await ValueChanged.InvokeAsync((NumberType)Convert.ChangeType(AdjustDecimalPlaces(value), typeof(NumberType)));
|
||||
if (string.IsNullOrEmpty(newVal))
|
||||
{
|
||||
await ValueChanged.InvokeAsync((NumberType)Convert.ChangeType(AdjustDecimalPlaces((NumberType)Convert.ChangeType(null, typeof(NumberType))), typeof(NumberType)));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!newVal.Equals(_value))
|
||||
await ValueChanged.InvokeAsync((NumberType)Convert.ChangeType(AdjustDecimalPlaces((NumberType)Convert.ChangeType(newVal, typeof(NumberType))), typeof(NumberType)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Parameter] public EventCallback<KeyboardEventArgs> OnKeyDown { get; set; }
|
||||
|
||||
private bool CheckKey(string key)
|
||||
{
|
||||
bool result;
|
||||
if (Helper.IsNumeric(key)) return true;
|
||||
switch (key.ToLower())
|
||||
{
|
||||
case "backspace":
|
||||
case "delete":
|
||||
case "arrowleft":
|
||||
case "arrowright":
|
||||
case "-":
|
||||
//case "e":
|
||||
{
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((key.Equals("-") || key.Equals("-")) && _value.Contains(key)) result = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
private bool _preventDefaultAction = true;
|
||||
public async Task ChangeValue(KeyboardEventArgs args)
|
||||
{
|
||||
_preventDefaultAction= true;
|
||||
if (args is not null)
|
||||
{
|
||||
var key = args.Key.ToString().ToLower();
|
||||
if (CheckKey(key))
|
||||
{
|
||||
_preventDefaultAction = false;
|
||||
|
||||
await OnKeyDown.InvokeAsync(args);
|
||||
}
|
||||
} else
|
||||
{
|
||||
args.Key = null;
|
||||
}
|
||||
}
|
||||
|
||||
private NumberType AdjustDecimalPlaces(NumberType value)
|
||||
{
|
||||
NumberType result = value;
|
||||
if (Helper.NumberHasDecimalPlaces(value))
|
||||
{
|
||||
var result = value;
|
||||
if (DecimalPlaces > 0)
|
||||
{
|
||||
decimal rounded = (decimal)Convert.ChangeType(value, typeof(decimal));
|
||||
rounded = Math.Round(rounded, DecimalPlaces);
|
||||
result = (NumberType)Convert.ChangeType(rounded, typeof(NumberType));
|
||||
}
|
||||
double converted = Math.Round((double)Convert.ChangeType(result, typeof(double)), DecimalPlaces);
|
||||
return (NumberType)Convert.ChangeType(converted, typeof(NumberType));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task Clear()
|
||||
{
|
||||
_value = string.Empty;
|
||||
await ValueChanged.InvokeAsync((NumberType)Convert.ChangeType(0, typeof(NumberType)));
|
||||
}
|
||||
|
||||
#region Lifecycle
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (DecimalPlaces > 0)
|
||||
if (firstRender)
|
||||
{
|
||||
if (!DecimalPlaces.Equals(Helper.GetDecimalPlaces(Value)))
|
||||
{
|
||||
Value = AdjustDecimalPlaces(Value);
|
||||
await ValueChanged.InvokeAsync(Value);
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region Lifecycle
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
if (typeof(NumberType).Name.ToLower().Contains("int"))
|
||||
|
@ -1,5 +1,7 @@
|
||||
using Connected.Utilities;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using static Connected.Colors;
|
||||
using static System.Net.Mime.MediaTypeNames;
|
||||
|
||||
namespace Connected.Models;
|
||||
public class InputBase : ComponentBase
|
||||
@ -71,6 +73,22 @@ public class InputBase : ComponentBase
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fired when the text value changes.
|
||||
/// </summary>
|
||||
[Parameter] public EventCallback<string> TextChanged { get; set; }
|
||||
public string Text { get; set; }
|
||||
|
||||
protected virtual async Task SetTextAsync(string text)
|
||||
{
|
||||
if (Text != text)
|
||||
{
|
||||
Text = text;
|
||||
await TextChanged.InvokeAsync(text);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private string _helperText = string.Empty;
|
||||
[Parameter]
|
||||
public string HelperText
|
||||
|
@ -135,11 +135,11 @@ public static class Helper
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsVariableNumeric(string input)
|
||||
public static bool IsNumeric(string input)
|
||||
{
|
||||
try
|
||||
{
|
||||
var number = Decimal.Parse(input);
|
||||
var number = Double.Parse(input);
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
|
@ -10,6 +10,7 @@ namespace Connected.Utilities;
|
||||
public struct StyleBuilder
|
||||
{
|
||||
private string stringBuffer;
|
||||
private string style;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a StyleBuilder used to define conditional in-line style used in a component. Call Build() to return the completed style as a string.
|
||||
@ -35,6 +36,7 @@ public struct StyleBuilder
|
||||
/// <param name="prop"></param>
|
||||
/// <param name="value"></param>
|
||||
public StyleBuilder(string prop, string value) => stringBuffer = $"{prop}:{value};";
|
||||
public StyleBuilder(string style) : this() => this.style = style;
|
||||
|
||||
/// <summary>
|
||||
/// Adds a conditional in-line style to the builder with space separator and closing semicolon.
|
||||
|
Loading…
x
Reference in New Issue
Block a user