Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ValidationSummary not updating on messagestore.add

I checked the login remote by a api and adding the validation-errors to ValidationMessageStore, but they don't appers in ValidationSummary. I want to use the same process in another complex szenarios, where i change migrate the frontend.

If i change the input and a "normal" error comes up, like a required-message appear, all errors appear in the summary. The required-Error and my credential errors. I think the only problem is: that the validation summary don't checked, that there is a new error Message inside. But i don' t know, how i can poke the ValidationSummary.

Here is the LogIn.razor.

<EditForm OnValidSubmit="ExecuteLogin" class="card card-body bg-light mt-5" EditContext="editContext">
    <p>DataAnnotationsValidator</p>
    <DataAnnotationsValidator />
    <p>ValidationSummary</p>
    <ValidationSummary />

    <div class="form-group row">
        <label for="email" class="col-md-2 col-form-label">Email:</label>
        <div class="col-md-10">
            <InputText id="email" class="form-control" @bind-Value="model.Email" />
            <ValidationMessage For="@(() => model.Email)" />
        </div>
    </div>

    <div class="form-group row">
        <label for="password" class="col-md-2 col-form-label">Password:</label>
        <div class="col-md-10">
            <InputText type="password" id="password" class="form-control" @bind-Value="model.Password" />
            <ValidationMessage For="@(() => model.Password)" />
        </div>
    </div>

    <div class="row justify-content-md-center">
        <div class="col-md-3">
            <button type="submit" class="btn btn-success">Log In</button>
        </div>
    </div>
</EditForm>

And here the Login.razor.cs

  public partial class LogIn
    {

        private EditContext? editContext;
        private ValidationMessageStore? _messageStore;

        private AuthenticationUserRequest model = new();

        protected override void OnInitialized()
        {
            editContext = new(model);
            editContext.OnValidationRequested += OnValidationRequested;
            _messageStore = new(editContext);
        }

        public void Dispose()
        {
            editContext.OnValidationRequested -= OnValidationRequested;
        }

        protected override async Task OnInitializedAsync()
        {
            var state = await _stateProvider.GetAuthenticationStateAsync();
            if (state.User.Identity.IsAuthenticated)
            {
                _navigationManager.NavigateTo("/");
            }
        }


        private void OnValidationRequested(object? sender, ValidationRequestedEventArgs e)
        {
            _messageStore?.Clear();
        }


        private async Task ExecuteLogin()
        {

            var result = await _authenticationManager.Login(model);
            if (result.Succeeded)
            {
                // Notify User and navigate to home
            }
            else
            {
                
                foreach (var message in result.Messages)
                {
                    if (message == "Invalid Credentials.")
                    {
                        _messageStore.Add(() => model.Email, "Invalid Credentials");
                        _messageStore.Add(() => model.Password, "Invalid Credentials");
                        _messageStore.Add(() => model.Password, "Another Error for testing");
                        StateHasChanged();

                    }
                    else
                    {
                        // Notify User
                    }
                }
            }
        }
    }
like image 790
Taladan Avatar asked Oct 13 '25 10:10

Taladan


1 Answers

I've simplified your code a little to create a single component. You see the code below.

To answer your question "adding the validation-errors to ValidationMessageStore, but they don't appers in ValidationSummary".

THEY DON'T, because of the slightly different behaviour of the ValidationSummary and ValidationMessage.

These are the important changes to make things happen:

  1. I've removed your ValidationStateChanged registration as I don't think you need it.
  2. I've added clearing the message storebvto ExecuteLogIn before adding the custom messages
  3. Called editContext!.NotifyValidationStateChanged(); after adding the messages.

Step 3 is the important bit for ValidationSummary. As ExecuteLogIn yields, EditContext get thread time to run the OnValidationStateChanged registered event handlers. ValidationSummary is one of these. It reads the "empty" validation store and re-renders long before you have added the custom messages. Nothing has changed for ValidationSummary when you finally re-render your main page, so no final re-render. Calling NotifyValidationStateChanged triggers that re-render.

using Microsoft.AspNetCore.Components.Forms;

namespace StackOverflow.Server.Pages
{
    public partial class LogIn
    {
        private EditContext? editContext;
        private ValidationMessageStore? _messageStore;

        private AuthenticationUserRequest model = new();

        protected override Task OnInitializedAsync()
        {
            editContext = new(model);
            _messageStore = new(editContext);
            return Task.CompletedTask;
        }

        private async Task ExecuteLogin()
        {
            var result =  await this.ValidateLogin();
            if (result)
            {
                // Notify User and navigate to home
            }
            else
            {
                _messageStore?.Clear();
                _messageStore!.Add(() => model.Email, "Invalid Email");
                _messageStore!.Add(() => model.Password, "Invalid Password");
                _messageStore!.Add(() => model.Message, "Invalid Credentials");
                editContext!.NotifyValidationStateChanged();
                await this.InvokeAsync(StateHasChanged);
            }
        }

        private async Task<bool> ValidateLogin()
        {
             await Task.Delay(1000);
            return false;
        }
    }

    public class AuthenticationUserRequest
    {
        public string Email { get; set; } = String.Empty;
        public string Password { get; set; } = String.Empty;
        public string Message { get; set; } = string.Empty;
    }

}
like image 176
MrC aka Shaun Curtis Avatar answered Oct 15 '25 17:10

MrC aka Shaun Curtis