最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

blazor - FluentEditForm says that there is no data, despite data entered being there - Stack Overflow

matteradmin5PV0评论

My code, below, is a fluenteditform form. After I submit, it says that the fields still need to be filled out even though I filled them out. What is wrong with my code?

@page "/movieform" 
@using Assignment10.Entities
@using System.ComponentModel.DataAnnotations

<h3>MovieForm</h3>

<FluentCard>
    <FluentEditForm FormName="MovieForm" Model="@movie">
        <DataAnnotationsValidator />
        <FluentValidationSummary />
        <FluentGrid>
            <FluentGridItem xs="12">
                <FluentTextField Name="MovieNameField" Id="movieNameField" @bind-Value="movie.MovieName" Label="Name: " Required/>
                <ValidationMessage For="@(() => movie.MovieName)" />
            </FluentGridItem>
            <FluentGridItem xs="12">
                <FluentTextField Name="MoviePublisherField" Id="moviePublisherField" @bind-Value="movie.Publisher" Label="Publisher: " Required/>
                <ValidationMessage For="@(() => movie.Publisher)" />

            </FluentGridItem>
            <FluentGridItem xs="12" >
                <FluentTextField Name="MovieDescriptionField" Id="movieDescriptionField" @bind-Value="movie.MovieDescription" Label="Description: " Required/>
                <ValidationMessage For="@(() => movie.MovieDescription)" />
            </FluentGridItem>
            <FluentGridItem xs="12" >
                <FluentButton Type="ButtonType.Submit" Appearance="Appearance.Accent">Submit</FluentButton>
            </FluentGridItem>
        </FluentGrid>
    </FluentEditForm>
</FluentCard>

@code {
    private Movie movie = new Movie(); 

}

My code, below, is a fluenteditform form. After I submit, it says that the fields still need to be filled out even though I filled them out. What is wrong with my code?

@page "/movieform" 
@using Assignment10.Entities
@using System.ComponentModel.DataAnnotations

<h3>MovieForm</h3>

<FluentCard>
    <FluentEditForm FormName="MovieForm" Model="@movie">
        <DataAnnotationsValidator />
        <FluentValidationSummary />
        <FluentGrid>
            <FluentGridItem xs="12">
                <FluentTextField Name="MovieNameField" Id="movieNameField" @bind-Value="movie.MovieName" Label="Name: " Required/>
                <ValidationMessage For="@(() => movie.MovieName)" />
            </FluentGridItem>
            <FluentGridItem xs="12">
                <FluentTextField Name="MoviePublisherField" Id="moviePublisherField" @bind-Value="movie.Publisher" Label="Publisher: " Required/>
                <ValidationMessage For="@(() => movie.Publisher)" />

            </FluentGridItem>
            <FluentGridItem xs="12" >
                <FluentTextField Name="MovieDescriptionField" Id="movieDescriptionField" @bind-Value="movie.MovieDescription" Label="Description: " Required/>
                <ValidationMessage For="@(() => movie.MovieDescription)" />
            </FluentGridItem>
            <FluentGridItem xs="12" >
                <FluentButton Type="ButtonType.Submit" Appearance="Appearance.Accent">Submit</FluentButton>
            </FluentGridItem>
        </FluentGrid>
    </FluentEditForm>
</FluentCard>

@code {
    private Movie movie = new Movie(); 

}
Share Improve this question edited Nov 18, 2024 at 16:19 Mike Brind 30.2k6 gold badges64 silver badges92 bronze badges asked Nov 16, 2024 at 20:27 user3776241user3776241 5439 silver badges21 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

you use <DataAnnotationsValidator /> - that's the reason your validator haven't receive data - it try to pass data to DataAnnotations infrastructure.

In my project I don't use libraries. Instead I use custom implementation of FluentValidationValidator component, and code looks like that:

<EditForm Model="Model" OnValidSubmit="OnValidSubmit">
    <FluentValidationValidator TValidator="MyModelValidator" />
    <ValidationSummary />

    // your inputs, with validation messages, like below:
    <ValidationMessage For="@(() => Model.Thought)" />
</EditForm>

@code{
    private EditContext editContext;
    private ValidationMessageStore messageStore;

    protected override void OnInitialized()
    {
        Model = new MyModel();

        editContext = new EditContext(Model);
        messageStore = new(editContext);

        base.OnInitialized();
    }

    private async Task OnValidSubmit()
    {
        // your save logic here
    }
}

And component itself (code found on stackoverflow):

public class FluentValidationValidator<TValidator> : ComponentBase where TValidator : IValidator, new()
{
    private readonly static char[] separators = new[] { '.', '[' };
    private TValidator validator;

    [CascadingParameter]
    private EditContext EditContext { get; set; }

    protected override void OnInitialized()
    {
        validator = new TValidator();
        var messages = new ValidationMessageStore(EditContext);

        /* Re-validate when any field changes or when the entire form   requests validation.*/
        EditContext.OnFieldChanged += (sender, eventArgs)
            => ValidateModel((EditContext)sender!, messages, false);

        EditContext.OnValidationRequested += (sender, eventArgs)
            => ValidateModel((EditContext)sender!, messages, true);
    }

    private void ValidateModel(EditContext editContext, ValidationMessageStore messages, bool submit)
    {
        if (submit)
            editContext.Properties["submitted"] = true;

        if (!editContext.Properties.TryGetValue("submitted", out _))
            return;

        var context = new ValidationContext<object>(editContext.Model);
        var validationResult = validator.Validate(context);
        messages.Clear();
        foreach (var error in validationResult.Errors)
        {
            var fieldIdentifier = ToFieldIdentifier(editContext, error.PropertyName);
            messages.Add(fieldIdentifier, error.ErrorMessage);
        }
        editContext.NotifyValidationStateChanged();
    }

    private static FieldIdentifier ToFieldIdentifier(EditContext editContext, string propertyPath)
    {
        var obj = editContext.Model;

        while (true)
        {
            var nextTokenEnd = propertyPath.IndexOfAny(separators);
            if (nextTokenEnd < 0)
            {
                return new FieldIdentifier(obj, propertyPath);
            }

            var nextToken = propertyPath.Substring(0, nextTokenEnd);
            propertyPath = propertyPath.Substring(nextTokenEnd + 1);

            object? newObj;
            if (nextToken.EndsWith("]"))
            {
                nextToken = nextToken.Substring(0, nextToken.Length - 1);
                var prop = obj.GetType().GetProperty("Item");
                var indexerType = prop!.GetIndexParameters()[0].ParameterType;
                var indexerValue = Convert.ChangeType(nextToken, indexerType);
                newObj = prop.GetValue(obj, [indexerValue]);
            }
            else
            {
                var prop = obj.GetType().GetProperty(nextToken);
                if (prop == null)
                {
                    throw new InvalidOperationException($"Could not find property named {nextToken} in object of type {obj.GetType().FullName}.");
                }
                newObj = prop.GetValue(obj);
            }

            if (newObj == null)
            {
                return new FieldIdentifier(obj, nextToken);
            }

            obj = newObj;
        }
    }
}

It works for me on several projects. Pros is you can extend component and add some custom logic, if necessary. Cons is you need to support it in your project. So if you decide to not support, you can try to use something from this link.

Hope it helpful.

Post a comment

comment list (0)

  1. No comments so far