I'm learning Blazor and I'm adapting Fluent UI because they are both made by Microsoft and I think they will work well.
So I'm changing the html editform below to a fluent editform. I'm applying it by looking at the form description on the Blazor Fluent UI site, and when I press the Login button, it says "EditForm requires either a Model parameter, or an EditContext parameter, please provide one of these." I get this error.
This works fine.
<EditForm Model="@loginModel" OnValidSubmit="Authenticate" FormName="LoginForm">
<DataAnnotationsValidator />
<div class="mb-3 text-center flex-cloumn">
<h3>LOGIN</h3>
</div>
<div class="mb-3">
<label for="userName" class="form-label">User Name:</label>
<InputText id="userName" @bind-Value="loginModel.UserName" class="form-control" />
<ValidationMessage For="() => loginModel.UserName" class="text-danger" />
</div>
<div class="mb-3">
<label for="password" class="form-label">Password:</label>
<InputText id="password" @bind-Value="loginModel.Password" class="form-control" />
<ValidationMessage For="() => loginModel.Password" class="text-danger" />
</div>
<div class="mb-3 text-center">
<span class="text-danger">@errorMessage</span>
</div>
<button type="submit" class="btn btn-primary">Login</button>
</EditForm>
@code {
[SupplyParameterFromForm]
public LoginViewModel loginModel { get; set; } = new();
private string? errorMessage;
private async Task Authenticate()
{
Console.WriteLine("Authenticate called");
}
}
but it's not
<FluentEditForm Model="@loginModel" OnValidSubmit="Authenticate" FormName="LoginForm" novalidate>
<DataAnnotationsValidator />
<FluentStack Orientation="Orientation.Vertical">
<h3>LOGIN</h3>
<div>
<FluentTextField Name="userName" @bind-Value="loginModel.UserName" Label="User Name" Required />
<FluentValidationMessage For="@(() => loginModel.UserName)"/>
</div>
<div>
<FluentTextField Name="password" @bind-Value="loginModel.Password" TextFieldType="TextFieldType.Password" Label="Password" Required />
<FluentValidationMessage For="@(() => loginModel.Password)"/>
</div>
<FluentButton Type="ButtonType.Submit" Appearance="Appearance.Accent">Login</FluentButton>
</FluentStack>
</FluentEditForm>
@code {
[SupplyParameterFromForm]
public LoginViewModel loginModel { get; set; } = new();
private string? errorMessage;
private async Task Authenticate()
{
Console.WriteLine("Authenticate called");
}
}
I'm already providing a Model parameter in the FluentEditform tag, but I'm getting this error, so it doesn't make a lot of sense.
InvalidOperationException: EditForm requires either a Model parameter, or an EditContext parameter, please provide one of these.
Microsoft.AspNetCore.Components.Forms.EditForm.OnParametersSet()
Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()
Microsoft.AspNetCore.Components.Rendering.ComponentState.SupplyCombinedParameters(ParameterView directAndCascadingParameters)
Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewSubtree(ref DiffContext diffContext, int frameIndex)
Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InsertNewFrame(ref DiffContext diffContext, int newFrameIndex)
Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(ref DiffContext diffContext, int oldStartIndex, int oldEndIndexExcl, int newStartIndex, int newEndIndexExcl)
Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment, out Exception renderFragmentException)
Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()
Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()
Microsoft.AspNetCore.Components.ComponentBase.StateHasChanged()
Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()
Microsoft.AspNetCore.Components.Rendering.ComponentState.SupplyCombinedParameters(ParameterView directAndCascadingParameters)
Microsoft.AspNetCore.Components.Rendering.ComponentState.SetDirectParameters(ParameterView parameters)
Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderRootComponentAsync(int componentId, ParameterView initialParameters)
Microsoft.AspNetCore.Components.HtmlRendering.Infrastructure.StaticHtmlRenderer.BeginRenderingComponent(IComponent component, ParameterView initialParameters)
Microsoft.AspNetCore.Components.Endpoints.EndpointHtmlRenderer.RenderEndpointComponent(HttpContext httpContext, Type rootComponentType, ParameterView parameters, bool waitForQuiescence)
System.Threading.Tasks.ValueTask<TResult>.get_Result()
Microsoft.AspNetCore.Components.Endpoints.RazorComponentEndpointInvoker.RenderComponentCore(HttpContext context)
Microsoft.AspNetCore.Components.Endpoints.RazorComponentEndpointInvoker.RenderComponentCore(HttpContext context)
Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContext+<>c+<<InvokeAsync>b__10_0>d.MoveNext()
Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Antiforgery.Internal.AntiforgeryMiddleware.InvokeAwaited(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
Most of the answers I've found are just to make sure you've provided a Model or initialized the Model you provide, which I think is a pretty simple task and nothing more than a modification to the tutorial, but I don't know why.
I tried following this post, but I want to use httpcontext on static pages, so I was hoping there was another workaround.
There is a litte difference when using FluentTextField in SSR. You have to set the "Name" property from the model, such as Name="loginModel.UserName"
.
...
<FluentTextField Name="loginModel.UserName" @bind-Value="loginModel.UserName" Label="User Name" Required />
...
<FluentTextField Name="loginModel.Password" @bind-Value="loginModel.Password" TextFieldType="TextFieldType.Password" Label="Password" Required />
...
Then the editform will work.