[WIP] Refactor components to match converter refactor

pull/2/head
Matija Koželj 2 years ago
parent f3ae953772
commit 6f91dacb0c

@ -5,14 +5,14 @@
<CascadingValue Name="SubscribeToParentForm" Value="false" IsFixed="true">
<div class="@AutocompleteClassList">
<InputControl Label="@Label" Variant="@Variant" HelperText="@HelperText" HelperTextOnFocus="@HelperTextOnFocus" FullWidth="@FullWidth" Margin="@Margin" Class="@ClassList()" Style="@Style"
Error="@Error" ErrorText="@ErrorText" Disabled="@Disabled" @onclick="@ToggleMenu" Required="@Required" ForId="@FieldId">
Error="@HasError" ErrorText="@ErrorText" Disabled="@Disabled" @onclick="@ToggleMenu" Required="@Required" ForId="@FieldId">
<InputContent>
<Input @ref="_elementReference" @key="_elementKey" InputType="InputType.Text"
Class="select-input" Margin="@Margin"
Variant="@Variant"
TextUpdateSuppression="@TextUpdateSuppression"
Value="@Text" DisableUnderLine="@DisableUnderLine"
Disabled="@Disabled" ReadOnly="@ReadOnly" Error="@Error"
Disabled="@Disabled" ReadOnly="@ReadOnly" Error="@HasError"
OnAdornmentClick="@OnAdornmentClick" AdornmentIcon="@CurrentIcon" Adornment="@Adornment" AdornmentColor="@AdornmentColor" IconSize="@IconSize" AdornmentText="@AdornmentText"
Clearable="@Clearable" OnClearButtonClick="@OnClearButtonClick"
@attributes="UserAttributes"

File diff suppressed because it is too large Load Diff

@ -44,17 +44,17 @@ public class BooleanInput<T> : FormComponent<T, bool?>
/// </summary>
[Parameter] public EventCallback<T> CheckedChanged { get; set; }
protected bool? BoolValue => Converter.Set(Checked);
protected bool? BoolValue => Converter.Convert(Checked);
protected virtual Task OnChange(ChangeEventArgs args)
{
Touched = true;
Modified = true;
return SetBoolValueAsync((bool?)args.Value);
}
protected Task SetBoolValueAsync(bool? value)
{
return SetCheckedAsync(Converter.Get(value));
return SetCheckedAsync(Converter.ConvertBack(value));
}
protected async Task SetCheckedAsync(T value)
@ -74,7 +74,7 @@ public class BooleanInput<T> : FormComponent<T, bool?>
{
var changed = base.SetConverter(value);
if (changed)
SetBoolValueAsync(Converter.Set(Checked)).AndForget();
SetBoolValueAsync(Converter.Convert(Checked)).AndForget();
return changed;
}

@ -139,7 +139,7 @@ public partial class CheckBox<T> : BooleanInput<T>
protected override Task OnChange(ChangeEventArgs args)
{
Touched = true;
Modified = true;
// Apply only when TriState parameter is set to true and T is bool?
if (TriState && typeof(T) == typeof(bool?))

File diff suppressed because it is too large Load Diff

@ -30,7 +30,7 @@ public class DatePicker : DatePickerBase
{
if (_value != date)
{
Touched = true;
Modified = true;
if (date is not null && IsDateDisabledFunc(date.Value.Date))
{
@ -40,10 +40,8 @@ public class DatePicker : DatePickerBase
_value = date;
if (updateValue)
{
Converter.GetError = false;
await SetTextAsync(Converter.Set(_value), false);
}
await SetTextAsync(Converter.Convert(_value), false);
await DateChanged.InvokeAsync(_value);
BeginValidate();
FieldChanged(_value);
@ -52,15 +50,15 @@ public class DatePicker : DatePickerBase
protected override Task DateFormatChanged(string newFormat)
{
Touched = true;
return SetTextAsync(Converter.Set(_value), false);
Modified = true;
return SetTextAsync(Converter.Convert(_value), false);
}
protected override Task StringValueChanged(string value)
{
Touched = true;
Modified = true;
// Update the date property (without updating back the Value property)
return SetDateAsync(Converter.Get(value), false);
return SetDateAsync(Converter.ConvertBack(value), false);
}
protected override string GetDayClasses(int month, DateTime day)

@ -230,7 +230,7 @@ public abstract partial class DatePickerBase : Picker<DateTime?>
base.OnPickerOpened();
if (Editable == true && Text != null)
{
DateTime? a = Converter.Get(Text);
DateTime? a = Converter.ConvertBack(Text);
if (a.HasValue)
{
a = new DateTime(a.Value.Year, a.Value.Month, 1);

@ -1,4 +1,6 @@
namespace Connected.Components;
using Connected.Extensions;
namespace Connected.Components;
public class DateRange : Range<DateTime?>, IEquatable<DateRange>
{
@ -15,7 +17,7 @@ public class DateRange : Range<DateTime?>, IEquatable<DateRange>
if (Start == null || End == null)
return string.Empty;
return RangeConverter<DateTime>.Join(converter.Set(Start.Value), converter.Set(End.Value));
return RangeConverter<DateTime>.Join(converter.Convert(Start.Value), converter.Convert(End.Value));
}
public string ToIsoDateString()
@ -40,12 +42,14 @@ public class DateRange : Range<DateTime?>, IEquatable<DateRange>
{
date = null;
var endDate = converter.Get(end);
if (converter.GetError)
var endDate = converter.ConvertBack(end);
if (endDate is null)
return false;
var startDate = converter.Get(start);
if (converter.GetError)
var startDate = converter.ConvertBack(start);
if (startDate is null)
return false;
date = new DateRange(startDate, endDate);

@ -6,13 +6,13 @@
@code{
protected override RenderFragment InputContent=>
@<InputControl Label="@Label" Variant="@Variant" HelperText="@HelperText" Error="@Error"
@<InputControl Label="@Label" Variant="@Variant" HelperText="@HelperText" Error="@HasError"
ErrorText="@ErrorText" Disabled="@Disabled" Margin="@Margin" Required="@Required"
@onclick="() => { if (!Editable) ToggleState(); }" ForId="@FieldId">
<InputContent>
<RangeInput @ref="_rangeInput" @attributes="UserAttributes" InputType="@InputType.Text" Class="@PickerInputClass" Style="@Style" Variant="@Variant" ReadOnly="@(!Editable)"
@bind-Value="@RangeText" Disabled="@Disabled" Adornment="@Adornment" AdornmentIcon="@AdornmentIcon" AdornmentColor="@AdornmentColor" IconSize="@IconSize" OnAdornmentClick="ToggleState"
Required="@Required" RequiredError="@RequiredError" Error="@Error" ErrorText="@ErrorText" Margin="@Margin" AdornmentAriaLabel="@AdornmentAriaLabel"/>
Required="@Required" RequiredError="@RequiredError" Error="@HasError" ErrorText="@ErrorText" Margin="@Margin" AdornmentAriaLabel="@AdornmentAriaLabel"/>
</InputContent>
</InputControl>;

@ -57,7 +57,6 @@ public partial class DateRangePicker : DatePickerBase
if (updateValue)
{
Converter.GetError = false;
if (_dateRange == null)
{
_rangeText = null;
@ -66,8 +65,8 @@ public partial class DateRangePicker : DatePickerBase
else
{
_rangeText = new Range<string>(
Converter.Set(_dateRange.Start),
Converter.Set(_dateRange.End));
Converter.Convert(_dateRange.Start),
Converter.Convert(_dateRange.End));
await SetTextAsync(_dateRange.ToString(Converter), false);
}
}
@ -85,7 +84,7 @@ public partial class DateRangePicker : DatePickerBase
if (_rangeText?.Equals(value) ?? value == null)
return;
Touched = true;
Modified = true;
_rangeText = value;
SetDateRangeAsync(ParseDateRangeValue(value?.Start, value?.End), false).AndForget();
}
@ -135,13 +134,13 @@ public partial class DateRangePicker : DatePickerBase
protected override Task DateFormatChanged(string newFormat)
{
Touched = true;
Modified = true;
return SetTextAsync(_dateRange?.ToString(Converter), false);
}
protected override Task StringValueChanged(string value)
{
Touched = true;
Modified = true;
// Update the daterange property (without updating back the Value property)
return SetDateRangeAsync(ParseDateRangeValue(value), false);
}

@ -109,14 +109,14 @@ public partial class FileUpload<T> : FormComponent<T, string>
await FilesChanged.InvokeAsync(_value);
BeginValidate();
FieldChanged(_value);
if (!Error || !SuppressOnChangeWhenInvalid) //only trigger FilesChanged if validation passes or SuppressOnChangeWhenInvalid is false
if (!HasError || !SuppressOnChangeWhenInvalid) //only trigger FilesChanged if validation passes or SuppressOnChangeWhenInvalid is false
await OnFilesChanged.InvokeAsync(args);
}
protected override void OnInitialized()
{
if (!(typeof(T) == typeof(IReadOnlyList<IBrowserFile>) || typeof(T) == typeof(IBrowserFile)))
Logger.LogWarning("T must be of type {type1} or {type2}", typeof(IReadOnlyList<IBrowserFile>), typeof(IBrowserFile));
//if (!(typeof(T) == typeof(IReadOnlyList<IBrowserFile>) || typeof(T) == typeof(IBrowserFile)))
// Logger.LogWarning("T must be of type {type1} or {type2}", typeof(IReadOnlyList<IBrowserFile>), typeof(IBrowserFile));
base.OnInitialized();
}

@ -206,11 +206,11 @@ public partial class Form : UIComponent, IDisposable, IForm
// - none have an error
// - all required fields have been touched (and thus validated)
var no_errors = _formControls.All(x => x.HasErrors == false);
var required_all_touched = _formControls.Where(x => x.Required).All(x => x.Touched);
var required_all_touched = _formControls.Where(x => x.Required).All(x => x.Modified);
var valid = no_errors && required_all_touched;
var old_touched = _touched;
_touched = _formControls.Any(x => x.Touched);
_touched = _formControls.Any(x => x.Modified);
try
{
_shouldRender = false;

File diff suppressed because it is too large Load Diff

@ -3,9 +3,9 @@
public interface IFormComponent
{
public bool Required { get; set; }
public bool Error { get; set; }
public bool HasError { get; set; }
public bool HasErrors { get; }
public bool Touched { get; }
public bool Modified { get; }
public object Validation { get; set; }
public bool IsForNull { get; }
public List<string> ValidationErrors { get; set; }

@ -41,7 +41,7 @@
@onkeyup:preventDefault="@KeyUpPreventDefault"
@onmousewheel="@OnMouseWheel"
@onwheel="@OnMouseWheel"
aria-invalid="@Error.ToString().ToLower()"
aria-invalid="@HasError.ToString().ToLower()"
aria-describedby="@ErrorId"
>
@Text
@ -73,7 +73,7 @@
@onkeyup:preventDefault="@KeyUpPreventDefault"
@onmousewheel="@OnMouseWheel"
@onwheel="@OnMouseWheel"
aria-invalid="@Error.ToString().ToLower()"
aria-invalid="@HasError.ToString().ToLower()"
aria-describedby="@ErrorId"
/>
@*Note: double mouse wheel handlers needed for Firefox because it doesn't know onmousewheel*@

@ -215,7 +215,7 @@ public abstract class InputBase<T> : FormComponent<T, string>
{
Text = text;
if (!string.IsNullOrWhiteSpace(Text))
Touched = true;
Modified = true;
if (updateValue)
await UpdateValuePropertyAsync(false);
await TextChanged.InvokeAsync(Text);
@ -227,7 +227,7 @@ public abstract class InputBase<T> : FormComponent<T, string>
/// </summary>
protected virtual Task UpdateTextPropertyAsync(bool updateValue)
{
return SetTextAsync(Converter.Set(Value), updateValue);
return SetTextAsync(Converter.Convert(Value), updateValue);
}
/// <summary>
@ -266,7 +266,7 @@ public abstract class InputBase<T> : FormComponent<T, string>
if (!OnlyValidateIfDirty || _isDirty)
{
Touched = true;
Modified = true;
BeginValidateAfter(OnBlur.InvokeAsync(obj));
}
}
@ -361,7 +361,7 @@ public abstract class InputBase<T> : FormComponent<T, string>
/// </summary>
protected virtual Task UpdateValuePropertyAsync(bool updateText)
{
return SetValueAsync(Converter.Get(Text), updateText);
return SetValueAsync(Converter.ConvertBack(Text), updateText);
}
protected override bool SetConverter(Converter<T, string> value)
@ -389,7 +389,7 @@ public abstract class InputBase<T> : FormComponent<T, string>
[Category(CategoryTypes.FormComponent.Behavior)]
public string Format
{
get => ((Converter<T>)Converter).Format;
get => ((ToStringConverter<T>)Converter).Format;
set => SetFormat(value);
}
@ -398,7 +398,7 @@ public abstract class InputBase<T> : FormComponent<T, string>
var changed = Format != value;
if (changed)
{
((Converter<T>)Converter).Format = value;
((ToStringConverter<T>)Converter).Format = value;
UpdateTextPropertyAsync(false).AndForget(); // refresh only Text property from current Value
}
return changed;

@ -238,7 +238,7 @@ public partial class Mask : InputBase<string>, IDisposable
await base.SetTextAsync(text, updateValue: false);
if (Clearable)
UpdateClearable(Text);
var v = Converter.Get(cleanText);
var v = Converter.ConvertBack(cleanText);
Value = v;
await ValueChanged.InvokeAsync(v);
SetCaretPosition(caret, selection);
@ -262,7 +262,7 @@ public partial class Mask : InputBase<string>, IDisposable
// allow this only via changes from the outside
if (_updating)
return;
var text = Converter.Set(Value);
var text = Converter.Convert(Value);
var cleanText = MaskKind.GetCleanText();
if (cleanText == text || string.IsNullOrEmpty(cleanText) && string.IsNullOrEmpty(text))
return;

@ -39,7 +39,7 @@
AdornmentIcon="@AdornmentIcon"
AdornmentColor="@AdornmentColor"
IconSize="@IconSize"
Error="@Error"
Error="@HasError"
Immediate="@(Immediate)"
Margin="@Margin"
MaxLength="@MaxLength"

@ -31,7 +31,7 @@
Margin="@Margin"
Required="@Required"
RequiredError="@RequiredError"
Error="@Error"
Error="@HasError"
ErrorText="@ErrorText"
Clearable="@(ReadOnly ? false : Clearable)"
OnClearButtonClick="@(() => Clear())"

@ -81,7 +81,7 @@ public partial class RadioGroup<T> : FormComponent<T, T>, IRadioGroup
internal Task SetSelectedRadioAsync(Radio<T> radio)
{
Touched = true;
Modified = true;
return SetSelectedRadioAsync(radio, true);
}

@ -5,14 +5,14 @@
<CascadingValue Name="SubscribeToParentForm" Value="false" IsFixed="true">
<div class="mud-select" id="@_elementId">
<InputControl Label="@Label" Variant="@Variant" HelperText="@HelperText" HelperTextOnFocus="@HelperTextOnFocus" FullWidth="@FullWidth" Margin="@Margin" Class="@Classname" Style="@Style"
Error="@Error" ErrorText="@ErrorText" ErrorId="@ErrorId" Disabled="@Disabled" @onclick="@ToggleMenu" Required="@Required" ForId="@FieldId">
Error="@HasError" ErrorText="@ErrorText" ErrorId="@ErrorId" Disabled="@Disabled" @onclick="@ToggleMenu" Required="@Required" ForId="@FieldId">
<InputContent>
<Input @ref="_elementReference" InputType="@(CanRenderValue || (Strict && !IsValueInList) ? InputType.Hidden : InputType.Text)"
Class="mud-select-input" Margin="@Margin" Placeholder="@Placeholder"
Variant="@Variant"
TextUpdateSuppression="false"
Value="@(Strict && !IsValueInList ? null : Text)" DisableUnderLine="@DisableUnderLine"
Disabled="@Disabled" ReadOnly="true" Error="@Error" ErrorId="@ErrorId"
Disabled="@Disabled" ReadOnly="true" Error="@HasError" ErrorId="@ErrorId"
OnAdornmentClick="@OnAdornmentClick" AdornmentIcon="@_currentIcon" Adornment="@Adornment"
AdornmentColor="@AdornmentColor" IconSize="@IconSize" AdornmentText="@AdornmentText"
Clearable="@Clearable" OnClearButtonClick="(async (e) => await SelectClearButtonClickHandlerAsync(e))"

File diff suppressed because it is too large Load Diff

@ -129,7 +129,7 @@ public partial class SelectItem<T> : SelectItemBase, IDisposable
var converter = Select?.Converter;
if (converter == null)
return $"{Value}";
return converter.Set(Value);
return converter.Convert(Value);
}
}

@ -28,8 +28,8 @@ public partial class Slider<T> : UIComponent
[Category(CategoryTypes.Slider.Validation)]
public T Min
{
get => Converter.Get(_min);
set => _min = Converter.Set(value);
get => Converter.ConvertBack(_min);
set => _min = Converter.Convert(value);
}
/// <summary>
@ -40,8 +40,8 @@ public partial class Slider<T> : UIComponent
[Category(CategoryTypes.Slider.Validation)]
public T Max
{
get => Converter.Get(_max);
set => _max = Converter.Set(value);
get => Converter.ConvertBack(_max);
set => _max = Converter.Convert(value);
}
/// <summary>
@ -52,8 +52,8 @@ public partial class Slider<T> : UIComponent
[Category(CategoryTypes.Slider.Validation)]
public T Step
{
get => Converter.Get(_step);
set => _step = Converter.Set(value);
get => Converter.ConvertBack(_step);
set => _step = Converter.Convert(value);
}
/// <summary>
@ -73,7 +73,7 @@ public partial class Slider<T> : UIComponent
[Parameter]
[Category(CategoryTypes.Slider.Behavior)]
public Converter<T> Converter { get; set; } = new DefaultConverter<T>() { Culture = CultureInfo.InvariantCulture };
public ToStringConverter<T> Converter { get; set; } = new DefaultConverter<T>() { Culture = CultureInfo.InvariantCulture };
[Parameter] public EventCallback<T> ValueChanged { get; set; }
@ -81,10 +81,10 @@ public partial class Slider<T> : UIComponent
[Category(CategoryTypes.Slider.Data)]
public T Value
{
get => Converter.Get(_value);
get => Converter.ConvertBack(_value);
set
{
var d = Converter.Set(value);
var d = Converter.Convert(value);
if (_value == d)
return;
_value = d;

@ -9,7 +9,7 @@
HelperTextOnFocus="@HelperTextOnFocus"
CounterText="@GetCounterText()"
FullWidth="@FullWidth"
Class="@Classname"
Class="@ClassList"
Error="@HasErrors"
ErrorText="@GetErrorText()"
ErrorId="@ErrorId"
@ -43,7 +43,7 @@
AdornmentAriaLabel="@AdornmentAriaLabel"
IconSize="@IconSize"
OnAdornmentClick="@OnAdornmentClick"
Error="@Error"
Error="@HasError"
ErrorId="@ErrorId"
Immediate="@Immediate"
Margin="@Margin"
@ -83,7 +83,7 @@
AdornmentColor="@AdornmentColor"
IconSize="@IconSize"
OnAdornmentClick="@OnAdornmentClick"
Error="@Error"
Error="@HasError"
Immediate="@Immediate"
Margin="@Margin" OnBlur="@OnBlurred"
Clearable="@Clearable"

@ -7,13 +7,9 @@ namespace Connected.Components;
public partial class TextField<T> : DebouncedInput<T>
{
protected string Classname =>
new CssBuilder("mud-input-input-control")
.AddClass(Class)
.Build();
private Mask? _maskReference;
public Input<string> InputReference { get; private set; }
private Mask _maskReference;
/// <summary>
/// Type of the input element. It should be a valid HTML5 input type.
@ -38,6 +34,11 @@ public partial class TextField<T> : DebouncedInput<T>
/// </summary>
[Parameter] public EventCallback<MouseEventArgs> OnClearButtonClick { get; set; }
protected string ClassList =>
new CssBuilder("mud-input-input-control")
.AddClass(Class)
.Build();
public override ValueTask FocusAsync()
{
if (_mask == null)
@ -130,10 +131,10 @@ public partial class TextField<T> : DebouncedInput<T>
{
if (_mask != null)
{
var textValue = Converter.Set(value);
var textValue = Converter.Convert(value);
_mask.SetText(textValue);
textValue = Mask.GetCleanText();
value = Converter.Get(textValue);
value = Converter.ConvertBack(textValue);
}
return base.SetValueAsync(value, updateText);
}

@ -1,4 +1,5 @@
using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Globalization;
using System.Text.RegularExpressions;
using Connected.Annotations;
@ -14,11 +15,13 @@ public partial class TimePicker : Picker<TimeSpan?>
private const string format24Hours = "HH:mm";
private const string format12Hours = "hh:mm tt";
public TimePicker() : base(new DefaultConverter<TimeSpan?>())
public TimePicker() : base()
{
Converter.GetFunc = OnGet;
Converter.SetFunc = OnSet;
((DefaultConverter<TimeSpan?>)Converter).Format = format24Hours;
_timeFormat = format24Hours;
Converter = new LambdaConverter<TimeSpan?, string>((e) => OnSet(e), (e) => OnGet(e));
AdornmentIcon = Icons.Material.Filled.AccessTime;
AdornmentAriaLabel = "Open Time Picker";
}
@ -30,7 +33,7 @@ public partial class TimePicker : Picker<TimeSpan?>
var time = DateTime.Today.Add(timespan.Value);
return time.ToString(((DefaultConverter<TimeSpan?>)Converter).Format, Culture);
return time.ToString(_timeFormat, Culture);
}
private TimeSpan? OnGet(string value)
@ -38,7 +41,7 @@ public partial class TimePicker : Picker<TimeSpan?>
if (string.IsNullOrEmpty(value))
return null;
if (DateTime.TryParseExact(value, ((DefaultConverter<TimeSpan?>)Converter).Format, Culture, DateTimeStyles.None, out var time))
if (DateTime.TryParseExact(value, _timeFormat, Culture, DateTimeStyles.None, out var time))
{
return time.TimeOfDay;
}
@ -105,13 +108,10 @@ public partial class TimePicker : Picker<TimeSpan?>
_amPm = value;
if (Converter is DefaultConverter<TimeSpan?> defaultConverter && string.IsNullOrWhiteSpace(_timeFormat))
{
defaultConverter.Format = AmPm ? format12Hours : format24Hours;
}
_timeFormat = AmPm ? format12Hours : format24Hours;
Touched = true;
SetTextAsync(Converter.Set(_value), false).AndForget();
Modified = true;
SetTextAsync(Converter.Convert(_value), false).AndForget();
}
}
@ -129,11 +129,9 @@ public partial class TimePicker : Picker<TimeSpan?>
return;
_timeFormat = value;
if (Converter is DefaultConverter<TimeSpan?> defaultConverter)
defaultConverter.Format = _timeFormat;
Touched = true;
SetTextAsync(Converter.Set(_value), false).AndForget();
Modified = true;
SetTextAsync(Converter.Convert(_value), false).AndForget();
}
}
@ -155,7 +153,7 @@ public partial class TimePicker : Picker<TimeSpan?>
TimeIntermediate = time;
_value = time;
if (updateValue)
await SetTextAsync(Converter.Set(_value), false);
await SetTextAsync(Converter.Convert(_value), false);
UpdateTimeSetFromTime();
await TimeChanged.InvokeAsync(_value);
BeginValidate();
@ -170,9 +168,9 @@ public partial class TimePicker : Picker<TimeSpan?>
protected override Task StringValueChanged(string value)
{
Touched = true;
Modified = true;
// Update the time property (without updating back the Value property)
return SetTimeAsync(Converter.Get(value), false);
return SetTimeAsync(Converter.ConvertBack(value), false);
}
//The last line cannot be tested

@ -12,7 +12,7 @@ public partial class TreeViewItem<T> : UIComponent
private string _text;
private bool _disabled;
private bool _isChecked, _isSelected, _isServerLoaded;
private Converter<T> _converter = new DefaultConverter<T>();
private ToStringConverter<T> _converter = new DefaultConverter<T>();
private readonly List<TreeViewItem<T>> _childItems = new();
protected string Classname =>
@ -68,7 +68,7 @@ public partial class TreeViewItem<T> : UIComponent
[Category(CategoryTypes.TreeView.Behavior)]
public string Text
{
get => string.IsNullOrEmpty(_text) ? _converter.Set(Value) : _text;
get => string.IsNullOrEmpty(_text) ? _converter.Convert(Value) : _text;
set => _text = value;
}

Loading…
Cancel
Save