Skip to content

fix: Form validation happens before FluentSelect's bind-SelectedOption sets a new value #3443

@AntonZhernosek

Description

@AntonZhernosek

🐛 Bug Report

When part of an edit form with validation, if the edit form contains a FluentSelect with bind-SelectedOption provided, property validation is triggered before being updated by the fluent select, potentially causing validation failure

💻 Repro or Code Sample

Here's a simple code repo:

  1. Create a new blazor project
  2. Package dependencies are
    • Microsoft.FluentUI.AspNetCore.Components >= 4.11.4
    • Blazored.FluentValidation - latest (2.2.0)
  3. Program.cs includes standard FluentUI config

Code sample for Home.razor

@page "/"
@rendermode InteractiveServer

@using Blazored.FluentValidation
@using FluentValidation
@using Microsoft.FluentUI.AspNetCore.Components

<EditForm Model="@EditModel">
    <FluentValidationValidator />

    <FluentSelect TOption="Property1"
                    Required=@true
                    Label="Property 1"
                    Items=@property1Choices
                    Placeholder="Select..."
                    Appearance="Appearance.Filled"
                    Position="SelectPosition.Below"
                    OptionValue="@(x => x.Id.ToString())"
                    OptionText="@(x => x.Name)"
                    @bind-SelectedOption=@EditModel.Property1>
    </FluentSelect>

    <FluentValidationMessage For="@(() => EditModel.Property1)" />

    <FluentSelect TOption="Property2"
                    Required=@true
                    Label="Property 2"
                    Items=@property2Choices
                    Placeholder="Select..."
                    Appearance="Appearance.Filled"
                    Position="SelectPosition.Below"
                    OptionValue="@(x => x.Id.ToString())"
                    OptionText="@(x => x.Name)"
                    @bind-SelectedOption=@EditModel.Property2>
    </FluentSelect>

    <FluentValidationMessage For="@(() => EditModel.Property2)" />
</EditForm>

@code {
    private Model EditModel { get; set; } = new();

    private List<Property1> property1Choices =
    [
        new()
        {
            Id = 1,
            Name = "First"
        },
        new()
        {
            Id = 2,
            Name = "Second"
        },
    ];

    private List<Property2> property2Choices =
    [
        new()
        {
            Id = 1,
            Name = "First"
        },
        new()
        {
            Id = 2,
            Name = "Second"
        },
    ];

    public sealed class Model
    {
        public Property1? Property1 { get; set; }
        public Property2? Property2 { get; set; } 
    }

    public sealed class Property1
    {
        public required int Id { get; set; }
        public required string Name { get; set; }
    }

    public sealed class Property2
    {
        public required int Id { get; set; }
        public required string Name { get; set; }
    }

    public sealed class ModelValidator : AbstractValidator<Model>
    {
        public ModelValidator()
        {
            RuleFor(x => x.Property1)
                .NotNull()
                .WithMessage("Property 1 should not be null!");

            RuleFor(x => x.Property2)
                .NotNull()
                .WithMessage("Property 2 should not be null!");
        }
    }
}

🤔 Expected Behavior

I select a new option, the field has a green outline and the model is valid.

😯 Current Behavior

If I select one of the options in a fluent select, the field will turn red and a validation failure message will appear. If I keep selecting again, the message will disappear.

If I get access to the edit context and debug from OnValidationStateChanged event handler, you'll see that validation occurs on the previously selected value, not the current one. In this case, validation occurs on a null value, even if I set a new value from the select dropdown

💁 Possible Solution

Didn't have time to look into the source code or recent changes. The issue does not happen with package version 4.11.3 and happens with 4.11.4 or greater.

🌍 Your Environment

Happens on windows and in standard aspnet debian container, Net9, library version 4.11.4+

Metadata

Metadata

Assignees

No one assigned

    Labels

    triageNew issue. Needs to be looked at

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions