havit / Havit.Blazor

Free Bootstrap 5 components for ASP.NET Blazor + optional enterprise-level stack for Blazor development (gRPC code-first, layered architecture, localization, auth, ...)
https://havit.blazor.eu
MIT License
475 stars 66 forks source link

[HxInputDate] [HxInputDateRange] Changing value causes two calls of EditContext.OnFieldChanged #787

Open jirikanda opened 4 months ago

jirikanda commented 4 months ago

Reprosteps

Why?

(both HxInputDate<TValue> and also HxInputDateInternal<TValue> inherit from InputBase<TValue>)

First call

Second call

Posible solutions (not sure right now)

(I guess this occurs also in HxInputDateRange while it uses the same code structure.)

hakenr commented 4 months ago

only HxInputDate should derive from InputBase

My preference (same in other similar components).

jirikanda commented 4 months ago

@hakenr, I am not familiar with the current code structure, there for I am not able to fix the issue (until someone explains me the thoughts behind). ie.

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

        if (HxInputDate<DateTime>.TryParseDateTimeOffsetFromString(newInputValue, null, out var date))
        {
            parsingFailed = false;
            CurrentValue = GetValueFromDateTimeOffset(date);
        }
        else
        {
            parsingFailed = true;
            _validationMessageStore.Add(FieldIdentifier, ParsingErrorMessageEffective);
        }

        // We can skip the validation notification if we were previously valid and still are
        if (parsingFailed || _previousParsingAttemptFailed)
        {
            EditContext.NotifyValidationStateChanged();
            _previousParsingAttemptFailed = parsingFailed;
        }
#endif
    }

Why are the so different NET8 vs pre-NET8?

hakenr commented 4 months ago

@jirikanda Before .NET 8, the SetUpdatesAttributeName() method was missing, and some of our components, such as HxInputDate, compensated it by using our own logic. In .NET 8, the new InputBase implementation incorporates SetUpdatesAttributeName() along with _incomingValueBeforeParsing and other stuff from my pull request, making our custom logic obsolete. Now, the InputBase already addresses the issue we were compensating for, simplifying the process to just CurrentValueAsString = newInputValue;.

https://github.com/dotnet/aspnetcore/pull/46434

hakenr commented 4 months ago

We should be able to drop all these pre-net8 "branches" in November 2024: https://dotnet.microsoft.com/en-us/platform/support/policy/dotnet-core