features/nuget_autobuild
stm 2 years ago
parent 9f1214fd9f
commit a04a0f07e2

@ -139,11 +139,11 @@ public abstract class FormComponent<T, U> : UIComponent, IFormComponent, IDispos
/// </summary> /// </summary>
public bool HasErrors => HasError || ConversionError || ValidationErrors.Count > 0; public bool HasErrors => HasError || ConversionError || ValidationErrors.Count > 0;
/// <summary> /// <summary>
/// Return the validation error text or the conversion error message. /// Return the validation error text or the conversion error message.
/// </summary> /// </summary>
/// <returns>Error text/message</returns> /// <returns>Error text/message</returns>
public string? GetErrorText() public string? GetErrorText(bool test = false)
{ {
// ErrorText is either set from outside or the first validation error // ErrorText is either set from outside or the first validation error
if (!IsNullOrWhiteSpace(ErrorText)) if (!IsNullOrWhiteSpace(ErrorText))
@ -152,6 +152,8 @@ public abstract class FormComponent<T, U> : UIComponent, IFormComponent, IDispos
if (!IsNullOrWhiteSpace(ConversionErrorMessage)) if (!IsNullOrWhiteSpace(ConversionErrorMessage))
return ConversionErrorMessage; return ConversionErrorMessage;
if (test) return "Error: test";
return null; return null;
} }

@ -1,6 +1,5 @@
using System.Timers; using System.Timers;
using Connected.Annotations; using Connected.Annotations;
using Connected.Utilities.BindingConverters;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
namespace Connected.Components; namespace Connected.Components;

@ -3,6 +3,23 @@
@inherits InputBase<T> @inherits InputBase<T>
<div class="@Classname"> <div class="@Classname">
<InputControl Label="@Label"
Variant="@Variant"
HelperText="@HelperText"
HelperTextOnFocus="@HelperTextOnFocus"
CounterText="@GetCounterText()"
FullWidth="@FullWidth"
Class="@Classname"
Error="@HasErrors"
ErrorText="@ErrorText"
ErrorId="@ErrorId"
Disabled="@Disabled"
Margin="@Margin"
Required="@Required"
ForId="@FieldId">
<CascadingValue Name="SubscribeToParentForm" Value="@base.SubscribeToParentForm" IsFixed="true">
@if (Adornment == Adornment.Start) @if (Adornment == Adornment.Start)
{ {
<InputAdornment Class="@AdornmentClassname" <InputAdornment Class="@AdornmentClassname"
@ -15,131 +32,135 @@
AriaLabel="@AdornmentAriaLabel" AriaLabel="@AdornmentAriaLabel"
/> />
} }
<InputContent>
@if (Lines > 1) @if (Lines > 1)
{ {
<textarea class="@InputClassname" <textarea class="@InputClassname"
@ref="ElementReference" @ref="ElementReference"
rows="@Lines" rows="@Lines"
@attributes="CustomAttributes" @attributes="CustomAttributes"
type="@InputTypeString" type="@InputTypeString"
placeholder="@Placeholder" placeholder="@Placeholder"
disabled=@Disabled disabled=@Disabled
readonly="@ReadOnly" readonly="@ReadOnly"
inputmode="@InputMode.ToString()" inputmode="@InputMode.ToString()"
@oninput="OnInput" @oninput="OnInput"
@onchange="OnChange" @onchange="OnChange"
@onblur="@OnBlurred" @onblur="@OnBlurred"
@onkeydown="@InvokeKeyDown" @onkeydown="@InvokeKeyDown"
@onkeypress="@InvokeKeyPress" @onkeypress="@InvokeKeyPress"
@onkeyup="@InvokeKeyUp" @onkeyup="@InvokeKeyUp"
@onpaste="@OnPaste" @onpaste="@OnPaste"
value="@_internalText" value="@_internalText"
maxlength="@MaxLength" maxlength="@MaxLength"
@onkeydown:preventDefault="@KeyDownPreventDefault" @onkeydown:preventDefault="@KeyDownPreventDefault"
@onkeypress:preventDefault="@KeyPressPreventDefault" @onkeypress:preventDefault="@KeyPressPreventDefault"
@onkeyup:preventDefault="@KeyUpPreventDefault" @onkeyup:preventDefault="@KeyUpPreventDefault"
@onmousewheel="@OnMouseWheel" @onmousewheel="@OnMouseWheel"
@onwheel="@OnMouseWheel" @onwheel="@OnMouseWheel"
aria-invalid="@HasError.ToString().ToLower()" aria-invalid="@HasError.ToString().ToLower()"
aria-describedby="@ErrorId" aria-describedby="@ErrorId"
>
@Text
</textarea>
@*Note: double mouse wheel handlers needed for Firefox because it doesn't know onmousewheel*@
@*note: the value="@_internalText" is absolutely essential here. the inner html @Text is needed by tests checking it*@
}
else
{
<input class="@InputClassname"
@ref="ElementReference"
@attributes="CustomAttributes"
type="@InputTypeString"
value="@_internalText"
@oninput="OnInput"
@onchange="OnChange"
placeholder="@Placeholder"
disabled=@Disabled
readonly="@ReadOnly"
@onblur="@OnBlurred"
inputmode="@InputMode.ToString()"
pattern="@Pattern"
@onkeydown="@InvokeKeyDown"
@onkeypress="@InvokeKeyPress"
@onkeyup="@InvokeKeyUp"
maxlength="@MaxLength"
@onkeydown:preventDefault="KeyDownPreventDefault"
@onkeypress:preventDefault="@KeyPressPreventDefault"
@onkeyup:preventDefault="@KeyUpPreventDefault"
@onmousewheel="@OnMouseWheel"
@onwheel="@OnMouseWheel"
aria-invalid="@HasError.ToString().ToLower()"
aria-describedby="@ErrorId"
/>
@*Note: double mouse wheel handlers needed for Firefox because it doesn't know onmousewheel*@
@if (Disabled) {
@*Note: this div must always be there to avoid crashes in WASM, but it is hidden most of the time except if ChildContent should be shown.
In Disabled state the tabindex attribute must NOT be set at all or else it will get focus on click
*@
<div class="@InputClassname"
style="@("display:"+(InputType == InputType.Hidden && ChildContent != null ? "inline" : "none"))"
@onblur="@OnBlurred" @ref="@_elementReference1"
> >
@ChildContent @Text
</div> </textarea>
@*Note: double mouse wheel handlers needed for Firefox because it doesn't know onmousewheel*@
@*note: the value="@_internalText" is absolutely essential here. the inner html @Text is needed by tests checking it*@
}
else
{
<input class="@InputClassname"
@ref="ElementReference"
@attributes="CustomAttributes"
type="@InputTypeString"
value="@_internalText"
@oninput="OnInput"
@onchange="OnChange"
placeholder="@Placeholder"
disabled=@Disabled
readonly="@ReadOnly"
@onblur="@OnBlurred"
inputmode="@InputMode.ToString()"
pattern="@Pattern"
@onkeydown="@InvokeKeyDown"
@onkeypress="@InvokeKeyPress"
@onkeyup="@InvokeKeyUp"
maxlength="@MaxLength"
@onkeydown:preventDefault="KeyDownPreventDefault"
@onkeypress:preventDefault="@KeyPressPreventDefault"
@onkeyup:preventDefault="@KeyUpPreventDefault"
@onmousewheel="@OnMouseWheel"
@onwheel="@OnMouseWheel"
aria-invalid="@HasError.ToString().ToLower()"
aria-describedby="@ErrorId"
/>
@*Note: double mouse wheel handlers needed for Firefox because it doesn't know onmousewheel*@
@if (Disabled) {
@*Note: this div must always be there to avoid crashes in WASM, but it is hidden most of the time except if ChildContent should be shown.
In Disabled state the tabindex attribute must NOT be set at all or else it will get focus on click
*@
<div class="@InputClassname"
style="@("display:"+(InputType == InputType.Hidden && ChildContent != null ? "inline" : "none"))"
@onblur="@OnBlurred" @ref="@_elementReference1"
>
@ChildContent
</div>
}
else
{
@*Note: this div must always be there to avoid crashes in WASM, but it is hidden most of the time except if ChildContent should be shown.*@
<div class="@InputClassname"
style="@("display:"+(InputType == InputType.Hidden && ChildContent != null ? "inline" : "none"))"
tabindex="@(InputType == InputType.Hidden && ChildContent != null ? 0 : -1)"
@onblur="@OnBlurred" @ref="@_elementReference1"
>
@ChildContent
</div>
}
} }
else
@if (_showClearable && !Disabled)
{ {
@*Note: this div must always be there to avoid crashes in WASM, but it is hidden most of the time except if ChildContent should be shown.*@
<div class="@InputClassname"
style="@("display:"+(InputType == InputType.Hidden && ChildContent != null ? "inline" : "none"))"
tabindex="@(InputType == InputType.Hidden && ChildContent != null ? 0 : -1)"
@onblur="@OnBlurred" @ref="@_elementReference1"
>
@ChildContent
</div>
} }
}
@if (_showClearable && !Disabled)
{
<IconButton Class="@ClearButtonClassname"
Color="@ThemeColor.Default"
Icon="@ClearIcon"
Size="@Size.Small"
OnClick="@ClearButtonClickHandlerAsync"
tabindex="-1"
/>
}
@if (Adornment == Adornment.End)
{
<InputAdornment Class="@AdornmentClassname"
Icon="@AdornmentIcon"
Color="@AdornmentColor"
Size="@IconSize"
Text="@AdornmentText"
Edge="@Edge.End"
AdornmentClick="@OnAdornmentClick"
AriaLabel="@AdornmentAriaLabel"
/>
}
@if (Variant == Variant.Outlined) @if (Adornment == Adornment.End)
{ {
<div class="input-outlined-border"></div> <InputAdornment Class="@AdornmentClassname"
} Icon="@AdornmentIcon"
Color="@AdornmentColor"
Size="@IconSize"
Text="@AdornmentText"
Edge="@Edge.End"
AdornmentClick="@OnAdornmentClick"
AriaLabel="@AdornmentAriaLabel"
/>
}
@if (!HideSpinButtons) @if (Variant == Variant.Outlined)
{ {
<div class="input-numeric-spin"> <div class="input-outlined-border"></div>
<Button Variant="Variant.Text" @onclick="OnIncrement" Disabled="@(Disabled || ReadOnly)" tabindex="-1"> }
<Icon Icon="@NumericUpIcon" Size="@GetButtonSize()" />
</Button> @if (!HideSpinButtons)
<Button Variant="Variant.Text" @onclick="OnDecrement" Disabled="@(Disabled || ReadOnly)" tabindex="-1"> {
<Icon Icon="@NumericDownIcon" Size="@GetButtonSize()" /> <div class="input-numeric-spin">
</Button> <Button Variant="Variant.Text" @onclick="OnIncrement" Disabled="@(Disabled || ReadOnly)" tabindex="-1">
</div> <Icon Icon="@NumericUpIcon" Size="@GetButtonSize()" />
} </Button>
<Button Variant="Variant.Text" @onclick="OnDecrement" Disabled="@(Disabled || ReadOnly)" tabindex="-1">
<Icon Icon="@NumericDownIcon" Size="@GetButtonSize()" />
</Button>
</div>
}
</InputContent>
</CascadingValue>
</InputControl>
</div> </div>

@ -2,12 +2,192 @@
using Connected.Utilities; using Connected.Utilities;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.Web;
using System.Numerics;
using System.Text.RegularExpressions;
using System.Timers;
namespace Connected.Components; namespace Connected.Components;
public partial class Input<T> : InputBase<T> public partial class Input<T> : InputBase<T>
{ {
protected string Classname => InputCssHelper.GetClassname(this,
/*
* Debounce
*
*/
/// <summary>
/// The current character counter, displayed below the text field.
/// </summary>
[Parameter] public string CounterText { get; set; }
private System.Timers.Timer _timer;
private double _debounceInterval;
/// <summary>
/// Interval to be awaited in MILLISECONDS before changing the Text value
/// </summary>
[Parameter]
public double TextChangeDelay
{
get => _debounceInterval;
set
{
if (NumericConverter<double>.AreEqual(_debounceInterval, value))
return;
_debounceInterval = value;
if (_debounceInterval == 0)
{
// not debounced, dispose timer if any
ClearTimer(suppressTick: false);
return;
}
SetTimer();
}
}
/// <summary>
/// callback to be called when the debounce interval has elapsed
/// receives the Text as a parameter
/// </summary>
[Parameter] public EventCallback<string> OnDebounceIntervalElapsed { get; set; }
protected Task OnDebounceChange()
{
if (TextChangeDelay > 0 && _timer != null)
{
_timer.Stop();
return base.UpdateValuePropertyAsync(false);
}
return Task.CompletedTask;
}
protected override Task UpdateValuePropertyAsync(bool updateText)
{
// This method is called when Value property needs to be refreshed from the current Text property, so typically because Text property has changed.
// We want to debounce only text-input, not a value being set, so the debouncing is only done when updateText==false (because that indicates the
// change came from a Text setter)
if (updateText)
{
// we have a change coming not from the Text setter, no debouncing is needed
return base.UpdateValuePropertyAsync(updateText);
}
// if debounce interval is 0 we update immediately
if (TextChangeDelay <= 0 || _timer == null)
return base.UpdateValuePropertyAsync(updateText);
// If a debounce interval is defined, we want to delay the update of Value property.
_timer.Stop();
// restart the timer while user is typing
_timer.Start();
return Task.CompletedTask;
}
protected override void OnParametersSet()
{
base.OnParametersSet();
// if input is to be debounced, makes sense to bind the change of the text to oninput
// so we set Immediate to true
if (TextChangeDelay > 0)
Immediate = true;
}
private void SetTimer()
{
if (_timer == null)
{
_timer = new System.Timers.Timer();
_timer.Elapsed += OnTimerTick;
_timer.AutoReset = false;
}
_timer.Interval = TextChangeDelay;
}
private void OnTimerTick(object sender, ElapsedEventArgs e)
{
InvokeAsync(OnTimerTickGuiThread).AndForget();
}
private async Task OnTimerTickGuiThread()
{
await base.UpdateValuePropertyAsync(false);
await OnDebounceIntervalElapsed.InvokeAsync(Text);
}
private void ClearTimer(bool suppressTick = false)
{
if (_timer == null)
return;
var wasEnabled = _timer.Enabled;
_timer.Stop();
_timer.Elapsed -= OnTimerTick;
_timer.Dispose();
_timer = null;
if (wasEnabled && !suppressTick)
OnTimerTickGuiThread().AndForget();
}
/*
* Debounce end
*/
protected CssBuilder CompiledHelperContainerClassList
{
get
{
return new CssBuilder("input-control-helper-container")
.AddClass($"px-1", Variant == Variant.Filled)
.AddClass($"px-2", Variant == Variant.Outlined)
.AddClass($"px-1", Variant == Variant.Text)
.AddClass(HelperContainerClassList);
}
}
/// <summary>
/// A space separated list of class names, added on top of the default helper container class list.
/// </summary>
[Parameter]
public string? HelperContainerClassList { get; set; }
protected CssBuilder CompiledHelperClassList
{
get
{
return new CssBuilder("input-helper-text")
.AddClass("input-helper-onfocus", HelperTextOnFocus)
.AddClass(HelperClassList);
}
}
/// <summary>
/// A space separated list of class names, added on top of the default helper class list.
/// </summary>
[Parameter]
public string? HelperClassList { get; set; }
/*protected string HelperContainer =>
new CssBuilder("input-control-helper-container")
.AddClass($"px-1", Variant == Variant.Filled)
.AddClass($"px-2", Variant == Variant.Outlined)
.Build();
protected string HelperClass =>
new CssBuilder("input-helper-text")
.AddClass("input-helper-onfocus", HelperTextOnFocus)
.Build();*/
private string GetCounterText()
{
string result = Text.Length.ToString();
if (string.IsNullOrEmpty(Text)) result = "0";
return result;
}
protected string Classname => InputCssHelper.GetClassname(this,
() => HasNativeHtmlPlaceholder() || !string.IsNullOrEmpty(Text) || Adornment == Adornment.Start || !string.IsNullOrWhiteSpace(Placeholder)); () => HasNativeHtmlPlaceholder() || !string.IsNullOrEmpty(Text) || Adornment == Adornment.Start || !string.IsNullOrWhiteSpace(Placeholder));
protected string InputClassname => InputCssHelper.GetInputClassname(this); protected string InputClassname => InputCssHelper.GetInputClassname(this);
@ -31,23 +211,89 @@ public partial class Input<T> : InputBase<T>
protected string InputTypeString => InputType.ToDescription(); protected string InputTypeString => InputType.ToDescription();
protected Task OnInput(ChangeEventArgs args) /*
private bool IsDecimalNumber(string type)
{
switch (type.ToLower())
{
case "double":
case "float":
return true;
default:
return false;
}
}
private bool IsNumber(string s)
{
bool result = false;
try
{
double d;
result= double.TryParse(s, out d);
} catch
{
result = false;
}
return result;
}
private string ValidateInput(string value)
{
string result = value;
if (value is not null)
{
var expectedType = typeof(T).Name;
if (IsNumericType(expectedType))
{
if (IsNumber(value.ToString()))
{
result = value.ToString();
}
else
{
if (IsDecimalNumber(value.ToString()))
result = Regex.Replace(value.ToString(), "[^0-9.]", "");
else result = Regex.Replace(value.ToString(), "[^0-9]", "");
}
}
else
{
result = value;
}
}
return result;
}*/
protected Task OnInput(ChangeEventArgs args)
{ {
if (!Immediate) if (!Immediate)
return Task.CompletedTask; return Task.CompletedTask;
_isFocused = true; _isFocused = true;
return SetTextAsync(args?.Value as string); return SetTextAsync(args?.Value as string);
}
}
protected async Task OnChange(ChangeEventArgs args) protected async Task OnChange(ChangeEventArgs args)
{ {
_internalText = args?.Value as string; if (TextChangeDelay > 0 && _timer != null)
await OnInternalInputChanged.InvokeAsync(args); {
if (!Immediate) _timer.Stop();
{ await UpdateValuePropertyAsync(false);
await SetTextAsync(args?.Value as string); }
} else
} {
_internalText = args?.Value as string;
await OnInternalInputChanged.InvokeAsync(args);
if (!Immediate)
{
await SetTextAsync(args?.Value as string);
}
}
}
/// <summary> /// <summary>
/// Paste hook for descendants. /// Paste hook for descendants.
@ -164,12 +410,12 @@ public partial class Input<T> : InputBase<T>
UpdateClearable(Text); UpdateClearable(Text);
} }
protected override async Task UpdateValuePropertyAsync(bool updateText) /*protected override async Task UpdateValuePropertyAsync(bool updateText)
{ {
await base.UpdateValuePropertyAsync(updateText); await base.UpdateValuePropertyAsync(updateText);
if (Clearable) if (Clearable)
UpdateClearable(Value); UpdateClearable(Value);
} }*/
protected virtual async Task ClearButtonClickHandlerAsync(MouseEventArgs e) protected virtual async Task ClearButtonClickHandlerAsync(MouseEventArgs e)
{ {
@ -197,14 +443,41 @@ public partial class Input<T> : InputBase<T>
// in WASM (or in BSS with TextUpdateSuppression==false) we always update // in WASM (or in BSS with TextUpdateSuppression==false) we always update
_internalText = Text; _internalText = Text;
} }
string baseTypeName = typeof(T).Name;
if (IsNumericType(baseTypeName))
{
InputType = InputType.Number;
}
} }
/// <summary> private bool IsNumericType(string type)
/// Sets the input text from outside programmatically {
/// </summary> switch (type.ToLower())
/// <param name="text"></param> {
/// <returns></returns> case "uint16":
public Task SetText(string text) case "uint32":
case "uint64":
case "int16":
case "int32":
case "int64":
case "int":
case "double":
case "decimal":
case "float":
return true;
default:
return false;
}
}
/// <summary>
/// Sets the input text from outside programmatically
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
public Task SetText(string text)
{ {
_internalText = text; _internalText = text;
return SetTextAsync(text); return SetTextAsync(text);

@ -211,7 +211,7 @@ public abstract class InputBase<T> : FormComponent<T, string>
protected virtual async Task SetTextAsync(string text, bool updateValue = true) protected virtual async Task SetTextAsync(string text, bool updateValue = true)
{ {
if (Text != text) if (Text != text)
{ {
Text = text; Text = text;
if (!string.IsNullOrWhiteSpace(Text)) if (!string.IsNullOrWhiteSpace(Text))
@ -220,6 +220,7 @@ public abstract class InputBase<T> : FormComponent<T, string>
await UpdateValuePropertyAsync(false); await UpdateValuePropertyAsync(false);
await TextChanged.InvokeAsync(Text); await TextChanged.InvokeAsync(Text);
} }
} }
/// <summary> /// <summary>
@ -329,7 +330,11 @@ public abstract class InputBase<T> : FormComponent<T, string>
/// Fired when the Value property changes. /// Fired when the Value property changes.
/// </summary> /// </summary>
[Parameter] [Parameter]
public EventCallback<T> ValueChanged { get; set; } public EventCallback<T> ValueChanged
{
get;
set;
}
/// <summary> /// <summary>
/// The value of this input element. /// The value of this input element.

@ -387,7 +387,7 @@ public partial class Picker<T> : FormComponent<T, string>
protected override void ResetValue() protected override void ResetValue()
{ {
_inputReference?.Reset(); _inputReference?.InputReference.Reset();
base.ResetValue(); base.ResetValue();
} }

@ -1,15 +1,15 @@
@namespace Connected.Components @namespace Connected.Components
@typeparam T @typeparam T
@inherits DebouncedInput<T> @inherits InputBase<T>
<CascadingValue Name="SubscribeToParentForm" Value="@SubscribeToParentForm" IsFixed="true"> <CascadingValue Name="SubscribeToParentForm" Value="@base.SubscribeToParentForm" IsFixed="true">
<InputControl Label="@Label" <InputControl Label="@Label"
Variant="@Variant" Variant="@Variant"
HelperText="@HelperText" HelperText="@HelperText"
HelperTextOnFocus="@HelperTextOnFocus" HelperTextOnFocus="@HelperTextOnFocus"
CounterText="@GetCounterText()" CounterText="@GetCounterText()"
FullWidth="@FullWidth" FullWidth="@FullWidth"
Class="@ClassList" class="@ClassList"
Error="@HasErrors" Error="@HasErrors"
ErrorText="@GetErrorText()" ErrorText="@GetErrorText()"
ErrorId="@ErrorId" ErrorId="@ErrorId"
@ -48,7 +48,6 @@
Margin="@Margin" Margin="@Margin"
OnBlur="@OnBlurred" OnBlur="@OnBlurred"
OnKeyDown="@InvokeKeyDown" OnKeyDown="@InvokeKeyDown"
OnInternalInputChanged="OnChange"
OnKeyPress="@InvokeKeyPress" OnKeyPress="@InvokeKeyPress"
OnKeyUp="@InvokeKeyUp" OnKeyUp="@InvokeKeyUp"
KeyDownPreventDefault="KeyDownPreventDefault" KeyDownPreventDefault="KeyDownPreventDefault"
@ -57,6 +56,7 @@
HideSpinButtons="true" HideSpinButtons="true"
Clearable="@Clearable" Clearable="@Clearable"
OnClearButtonClick="@OnClearButtonClick" OnClearButtonClick="@OnClearButtonClick"
Class="@CompiledClassList.Build()"
Pattern="@Pattern"/> Pattern="@Pattern"/>
} }
else else
@ -83,8 +83,10 @@
OnAdornmentClick="@OnAdornmentClick" OnAdornmentClick="@OnAdornmentClick"
Error="@HasError" Error="@HasError"
Immediate="@Immediate" Immediate="@Immediate"
Margin="@Margin" OnBlur="@OnBlurred" Margin="@Margin"
OnBlur="@OnBlurred"
Clearable="@Clearable" Clearable="@Clearable"
Class="@CompiledClassList.Build()"
OnClearButtonClick="@OnClearButtonClick"/> OnClearButtonClick="@OnClearButtonClick"/>
} }
</CascadingValue> </CascadingValue>

@ -5,7 +5,7 @@ using Microsoft.AspNetCore.Components.Web;
namespace Connected.Components; namespace Connected.Components;
public partial class TextField<T> : DebouncedInput<T> public partial class TextField<T> : InputBase<T>
{ {
private Mask? _maskReference; private Mask? _maskReference;
@ -19,7 +19,7 @@ public partial class TextField<T> : DebouncedInput<T>
internal override InputType GetInputType() => InputType; internal override InputType GetInputType() => InputType;
private string GetCounterText() => Counter == null ? string.Empty : (Counter == 0 ? (string.IsNullOrEmpty(Text) ? "0" : $"{Text.Length}") : ((string.IsNullOrEmpty(Text) ? "0" : $"{Text.Length}") + $" / {Counter}")); private string GetCounterText() => base.Counter == null ? string.Empty : (base.Counter == 0 ? (string.IsNullOrEmpty(base.Text) ? "0" : $"{base.Text.Length}") : ((string.IsNullOrEmpty(base.Text) ? "0" : $"{base.Text.Length}") + $" / {base.Counter}"));
/// <summary> /// <summary>
/// Show clear button. /// Show clear button.
@ -32,10 +32,25 @@ public partial class TextField<T> : DebouncedInput<T>
/// </summary> /// </summary>
[Parameter] public EventCallback<MouseEventArgs> OnClearButtonClick { get; set; } [Parameter] public EventCallback<MouseEventArgs> OnClearButtonClick { get; set; }
protected string ClassList => /*protected string ClassList =>
new CssBuilder("input-input-control") new CssBuilder("input-input-control")
.AddClass(base.AdditionalClassList) .AddClass(base.AdditionalClassList)
.Build(); .Build();*/
protected virtual CssBuilder CompiledClassList
{
get
{
return new CssBuilder("input-input-control")
.AddClass(ClassList);
}
}
/// <summary>
/// A space separated list of class names, added on top of the default class list.
/// </summary>
[Parameter]
public string? ClassList { get; set; }
public override ValueTask FocusAsync() public override ValueTask FocusAsync()
{ {
@ -128,10 +143,10 @@ public partial class TextField<T> : DebouncedInput<T>
{ {
if (_mask != null) if (_mask != null)
{ {
var textValue = Converter.Convert(value); var textValue = base.Converter.Convert(value);
_mask.SetText(textValue); _mask.SetText(textValue);
textValue = Mask.GetCleanText(); textValue = Mask.GetCleanText();
value = Converter.ConvertBack(textValue); value = base.Converter.ConvertBack(textValue);
} }
return base.SetValueAsync(value, updateText); return base.SetValueAsync(value, updateText);
} }

Loading…
Cancel
Save