You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Connected.Components/Components/Input/Input.razor.cs

223 lines
7.1 KiB

2 years ago
using Connected.Extensions;
using Connected.Utilities;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
namespace Connected.Components;
public partial class Input<T> : InputBase<T>
{
protected string Classname => InputCssHelper.GetClassname(this,
() => HasNativeHtmlPlaceholder() || !string.IsNullOrEmpty(Text) || Adornment == Adornment.Start || !string.IsNullOrWhiteSpace(Placeholder));
protected string InputClassname => InputCssHelper.GetInputClassname(this);
protected string AdornmentClassname => InputCssHelper.GetAdornmentClassname(this);
protected string ClearButtonClassname =>
new CssBuilder()
.AddClass("me-n1", Adornment == Adornment.End && HideSpinButtons == false)
.AddClass("mud-icon-button-edge-end", Adornment == Adornment.End && HideSpinButtons == true)
.AddClass("me-6", Adornment != Adornment.End && HideSpinButtons == false)
.AddClass("mud-icon-button-edge-margin-end", Adornment != Adornment.End && HideSpinButtons == true)
.Build();
/// <summary>
/// Type of the input element. It should be a valid HTML5 input type.
/// </summary>
[Parameter] public InputType InputType { get; set; } = InputType.Text;
internal override InputType GetInputType() => InputType;
protected string InputTypeString => InputType.ToDescriptionString();
protected Task OnInput(ChangeEventArgs args)
{
if (!Immediate)
return Task.CompletedTask;
_isFocused = true;
return SetTextAsync(args?.Value as string);
}
protected async Task OnChange(ChangeEventArgs args)
{
_internalText = args?.Value as string;
await OnInternalInputChanged.InvokeAsync(args);
if (!Immediate)
{
await SetTextAsync(args?.Value as string);
}
}
/// <summary>
/// Paste hook for descendants.
/// </summary>
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
protected virtual async Task OnPaste(ClipboardEventArgs args)
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
{
// do nothing
return;
}
/// <summary>
/// ChildContent of the MudInput will only be displayed if InputType.Hidden and if its not null.
/// </summary>
[Parameter] public RenderFragment ChildContent { get; set; }
public ElementReference ElementReference { get; private set; }
private ElementReference _elementReference1;
public override async ValueTask FocusAsync()
{
try
{
if (InputType == InputType.Hidden && ChildContent != null)
await _elementReference1.FocusAsync();
else
await ElementReference.FocusAsync();
}
catch (Exception e)
{
Console.WriteLine("Input.FocusAsync: " + e.Message);
}
}
public override ValueTask BlurAsync()
{
return ElementReference.BlurAsync();
}
public override ValueTask SelectAsync()
{
return ElementReference.SelectAsync();
}
public override ValueTask SelectRangeAsync(int pos1, int pos2)
{
return ElementReference.SelectRangeAsync(pos1, pos2);
}
/// <summary>
/// Invokes the callback when the Up arrow button is clicked when the input is set to <see cref="InputType.Number"/>.
/// Note: use the optimized control <see cref="NumericField{T}"/> if you need to deal with numbers.
/// </summary>
[Parameter] public EventCallback OnIncrement { get; set; }
/// <summary>
/// Invokes the callback when the Down arrow button is clicked when the input is set to <see cref="InputType.Number"/>.
/// Note: use the optimized control <see cref="MudNumericField{T}"/> if you need to deal with numbers.
/// </summary>
[Parameter] public EventCallback OnDecrement { get; set; }
/// <summary>
/// Hides the spin buttons for <see cref="MudNumericField{T}"/>
/// </summary>
[Parameter] public bool HideSpinButtons { get; set; } = true;
/// <summary>
/// Show clear button.
/// </summary>
[Parameter] public bool Clearable { get; set; } = false;
/// <summary>
/// Button click event for clear button. Called after text and value has been cleared.
/// </summary>
[Parameter] public EventCallback<MouseEventArgs> OnClearButtonClick { get; set; }
/// <summary>
/// Mouse wheel event for input.
/// </summary>
[Parameter] public EventCallback<WheelEventArgs> OnMouseWheel { get; set; }
/// <summary>
/// Custom clear icon.
/// </summary>
[Parameter] public string ClearIcon { get; set; } = Icons.Material.Filled.Clear;
/// <summary>
/// Custom numeric up icon.
/// </summary>
[Parameter] public string NumericUpIcon { get; set; } = Icons.Material.Filled.KeyboardArrowUp;
/// <summary>
/// Custom numeric down icon.
/// </summary>
[Parameter] public string NumericDownIcon { get; set; } = Icons.Material.Filled.KeyboardArrowDown;
private Size GetButtonSize() => Margin == Margin.Dense ? Size.Small : Size.Medium;
private bool _showClearable;
private void UpdateClearable(object value)
{
var showClearable = Clearable && ((value is string stringValue && !string.IsNullOrWhiteSpace(stringValue)) || (value is not string && value is not null));
if (_showClearable != showClearable)
_showClearable = showClearable;
}
protected override async Task UpdateTextPropertyAsync(bool updateValue)
{
await base.UpdateTextPropertyAsync(updateValue);
if (Clearable)
UpdateClearable(Text);
}
protected override async Task UpdateValuePropertyAsync(bool updateText)
{
await base.UpdateValuePropertyAsync(updateText);
if (Clearable)
UpdateClearable(Value);
}
protected virtual async Task ClearButtonClickHandlerAsync(MouseEventArgs e)
{
await SetTextAsync(string.Empty, updateValue: true);
await ElementReference.FocusAsync();
await OnClearButtonClick.InvokeAsync(e);
}
private string _internalText;
public override async Task SetParametersAsync(ParameterView parameters)
{
await base.SetParametersAsync(parameters);
//if (!_isFocused || _forceTextUpdate)
// _internalText = Text;
if (RuntimeLocation.IsServerSide && TextUpdateSuppression)
{
// Text update suppression, only in BSS (not in WASM).
// This is a fix for #1012
if (!_isFocused || _forceTextUpdate)
_internalText = Text;
}
else
{
// in WASM (or in BSS with TextUpdateSuppression==false) we always update
_internalText = Text;
}
}
/// <summary>
/// Sets the input text from outside programmatically
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
public Task SetText(string text)
{
_internalText = text;
return SetTextAsync(text);
}
// Certain HTML5 inputs (dates and color) have a native placeholder
private bool HasNativeHtmlPlaceholder()
{
return GetInputType() is InputType.Color or InputType.Date or InputType.DateTimeLocal or InputType.Month
or InputType.Time or InputType.Week;
}
}
public class InputString : Input<string> { }