Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#468 [HxInputBase] Incorporate two-way input binding (SetUpdatesAttri… #672

Merged
merged 2 commits into from
Dec 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion BlazorAppTest/BlazorAppTest.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFrameworks>net8.0;net7.0;net6.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

Expand Down
3 changes: 3 additions & 0 deletions Havit.Blazor.Components.Web.Bootstrap/Forms/HxCheckbox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ protected override void BuildRenderInput(RenderTreeBuilder builder)
BuildRenderInput_AddCommonAttributes(builder, "checkbox");
builder.AddAttribute(1000, "checked", BindConverter.FormatValue(CurrentValue));
builder.AddAttribute(1001, "onchange", value: EventCallback.Factory.CreateBinder<bool>(this, value => CurrentValue = value, CurrentValue));
#if NET8_0_OR_GREATER
builder.SetUpdatesAttributeName("checked");
#endif
builder.AddEventStopPropagationAttribute(1002, "onclick", true);
builder.AddElementReferenceCapture(1003, elementReference => InputElement = elementReference);
builder.CloseElement(); // input
Expand Down
4 changes: 3 additions & 1 deletion Havit.Blazor.Components.Web.Bootstrap/Forms/HxInputNumber.cs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,9 @@ protected override void BuildRenderInput(RenderTreeBuilder builder)

builder.AddAttribute(1002, "onfocus", "this.select();"); // source: https://stackoverflow.com/questions/4067469/selecting-all-text-in-html-text-input-when-clicked
builder.AddAttribute(1003, "onchange", EventCallback.Factory.CreateBinder<string>(this, value => CurrentValueAsString = value, CurrentValueAsString));

#if NET8_0_OR_GREATER
builder.SetUpdatesAttributeName("value");
#endif
// normalize pasted value
builder.AddAttribute(1004, "onpaste", @"this.value = event.clipboardData.getData('text/plain').replace(/[^\d.,\-eE]/g, ''); this.dispatchEvent(new Event('change')); return false;");

Expand Down
4 changes: 3 additions & 1 deletion Havit.Blazor.Components.Web.Bootstrap/Forms/HxInputRange.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,9 @@ protected override void BuildRenderInput(RenderTreeBuilder builder)

builder.AddAttribute(4, "value", BindConverter.FormatValue(Value));
builder.AddAttribute(5, BindEventEffective.ToEventName(), EventCallback.Factory.CreateBinder(this, async value => await HandleValueChanged(value), Value));

#if NET8_0_OR_GREATER
builder.SetUpdatesAttributeName("value");
#endif
builder.AddAttribute(10, "min", Min);
builder.AddAttribute(11, "max", Max);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ protected override void BuildRenderInput(RenderTreeBuilder builder)

builder.AddAttribute(1002, "value", FormatValueAsString(Value));
builder.AddAttribute(1003, BindEvent.ToEventName(), EventCallback.Factory.CreateBinder<string>(this, value => CurrentValueAsString = value, CurrentValueAsString));

#if NET8_0_OR_GREATER
builder.SetUpdatesAttributeName("value");
if (!String.IsNullOrEmpty(this.NameAttributeValue))
{
builder.AddAttribute(1004, "name", NameAttributeValue);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,9 @@ protected void BuildRenderInput_RenderRadioItem(RenderTreeBuilder builder, int i
builder.AddAttribute(207, "disabled", !CascadeEnabledComponent.EnabledEffective(this));
int j = index;
builder.AddAttribute(208, "onclick", EventCallback.Factory.Create(this, () => HandleInputClick(j)));
#if NET8_0_OR_GREATER
builder.SetUpdatesAttributeName("checked");
#endif
builder.AddEventStopPropagationAttribute(209, "onclick", true);
builder.AddMultipleAttributes(250, this.AdditionalAttributes);
builder.CloseElement(); // input
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,16 +73,18 @@ public partial class HxInputDateInternal<TValue> : InputBase<TValue>, IAsyncDisp

protected DateTime GetCalendarDisplayMonthEffective => GetDateTimeFromValue(CurrentValue) ?? CalendarDisplayMonth;

#if !NET8_0_OR_GREATER
private TValue previousValue;

private bool previousParsingAttemptFailed;
private ValidationMessageStore validationMessageStore;
#endif

private HxDropdownToggleElement hxDropdownToggleElement;
private ElementReference iconWrapperElement;
private IJSObjectReference jsModule;
private bool firstRenderCompleted;

#if !NET8_0_OR_GREATER
protected override void OnParametersSet()
{
base.OnParametersSet();
Expand All @@ -96,13 +98,17 @@ protected override void OnParametersSet()
previousValue = Value;
}
}
#endif

protected override string FormatValueAsString(TValue value) => HxInputDate<TValue>.FormatValue(value);

private void HandleValueChanged(ChangeEventArgs changeEventArgs)
{
#if NET8_0_OR_GREATER
CurrentValueAsString = changeEventArgs.Value.ToString();
#else
// HandleValueChanged is used instead of TryParseValueFromString
// When TryParseValueFromString is used, invalid input is replaced by previous value.
// When TryParseValueFromString is used (pre net8), invalid input is replaced by previous value.
bool parsingFailed;
validationMessageStore.Clear(FieldIdentifier);

Expand All @@ -123,12 +129,27 @@ private void HandleValueChanged(ChangeEventArgs changeEventArgs)
EditContext.NotifyValidationStateChanged();
previousParsingAttemptFailed = parsingFailed;
}

#endif
}

protected override bool TryParseValueFromString(string value, out TValue result, out string validationErrorMessage)
{
#if NET8_0_OR_GREATER
if (HxInputDate<DateTime>.TryParseDateTimeOffsetFromString(value, null, out var date))
{
result = GetValueFromDateTimeOffset(date);
validationErrorMessage = null;
return true;
}
else
{
result = default;
validationErrorMessage = ParsingErrorMessageEffective;
return false;
}
#else
throw new NotSupportedException();
#endif
}

protected override async Task OnAfterRenderAsync(bool firstRender)
Expand All @@ -148,11 +169,10 @@ private CalendarDateCustomizationResult GetCalendarDateCustomization(CalendarDat
{
return CalendarDateCustomizationProviderEffective?.Invoke(request with { Target = CalendarDateCustomizationTarget.InputDate }) ?? null;
}

private async Task HandleClearClickAsync()
{
CurrentValue = default;
ClearPreviousParsingMessage();

SetCurrentDate(null);
await CloseDropdownAsync();
}

Expand All @@ -164,26 +184,43 @@ private async Task CloseDropdownAsync()

private async Task HandleCalendarValueChangedAsync(DateTime? date)
{
CurrentValue = GetValueFromDateTimeOffset((date != null) ? new DateTimeOffset(date.Value) : null);
SetCurrentDate(date);
await CloseDropdownAsync();
}

protected async Task HandleCustomDateClick(DateTime value)
{
CurrentValue = GetValueFromDateTimeOffset(new DateTimeOffset(DateTime.SpecifyKind(value, DateTimeKind.Unspecified), TimeSpan.Zero));
ClearPreviousParsingMessage();
SetCurrentDate(value);
await CloseDropdownAsync();
}

protected void SetCurrentDate(DateTime? date)
{
#if NET8_0_OR_GREATER
CurrentValueAsString = date?.ToShortDateString(); // we need to trigger the logic in CurrentValueAsString setter
#else
if (date == null)
{
CurrentValue = default;
}
else
{
CurrentValue = GetValueFromDateTimeOffset(new DateTimeOffset(DateTime.SpecifyKind(date.Value, DateTimeKind.Unspecified), TimeSpan.Zero));
}
ClearPreviousParsingMessage();
#endif
}

#if !NET8_0_OR_GREATER
private void ClearPreviousParsingMessage()
{
if (previousParsingAttemptFailed)
{
previousParsingAttemptFailed = false;
validationMessageStore.Clear(FieldIdentifier);
EditContext.NotifyValidationStateChanged();
}
}
#endif

private string GetNameAttributeValue()
{
Expand Down Expand Up @@ -246,7 +283,9 @@ public async ValueTask DisposeAsync()

protected virtual async ValueTask DisposeAsyncCore()
{
#if !NET8_0_OR_GREATER
validationMessageStore?.Clear();
#endif

try
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ protected override GridCellTemplate GetHeaderCellTemplate(GridHeaderCellContext

builder.AddAttribute(103, "checked", AllDataItemsSelected);
builder.AddAttribute(104, "onchange", EventCallback.Factory.Create<ChangeEventArgs>(this, HandleSelectAllOrNoneClick));
#if NET8_0_OR_GREATER
builder.SetUpdatesAttributeName("checked");
#endif
builder.AddEventStopPropagationAttribute(105, "onclick", true);

builder.CloseElement(); // input
Expand All @@ -51,6 +54,9 @@ protected override GridCellTemplate GetItemCellTemplate(TItem item)
bool selected = SelectedDataItems?.Contains(item) ?? false;
builder.AddAttribute(103, "checked", selected);
builder.AddAttribute(104, "onchange", EventCallback.Factory.Create<ChangeEventArgs>(this, HandleSelectDataItemClick(item, selected)));
#if NET8_0_OR_GREATER
builder.SetUpdatesAttributeName("checked");
#endif
builder.AddEventStopPropagationAttribute(105, "onclick", true);

builder.CloseElement(); // input
Expand Down