I'm trying to create a register account page in Blazor Web App. I need the form submission callback to run on the client as it needs to set the authentication cookie, but I can't manage to achieve this.
This is my current component code:
@using ClassLibrary.Models.Auth@using ClassLibrary.Models.Database@using ClassLibrary.Localization.Shared.Forms@using IDFW.Models.HttpClients@rendermode InteractiveWebAssembly@page "/auth/register"@inject IStringLocalizer<Register> localizer@inject ApiHttpClient api<HeadContent><link rel="stylesheet" href="/css/auth/login.css" /><link rel="stylesheet" href="/css/components/loader.css" /></HeadContent><div class="content-container"><EditForm FormName="LoginForm" EditContext="editContext" class="data-form" OnValidSubmit="HandleOnValidSubmit"><DataAnnotationsValidator /><h1>@localizer["PageTitle"]</h1><fieldset disabled="@isProcessing"><label><p>@FormLocalization.FirstName<span class="danger">*</span></p><InputText DisplayName="@FormLocalization.FirstName" @bind-Value="RegisterModel.FirstName" /><ValidationMessage For="() => RegisterModel.FirstName" class="danger" /></label><label><p>@FormLocalization.LastName<span class="danger">*</span></p><InputText DisplayName="@FormLocalization.LastName" @bind-Value="RegisterModel.LastName" /><ValidationMessage For="() => RegisterModel.LastName" class="danger" /></label><label><p>Email<span class="danger">*</span></p><InputText DisplayName="Email" @bind-Value="RegisterModel.Email" type="email" /><ValidationMessage For="() => RegisterModel.Email" class="danger" /></label><label><p>Password<span class="danger">*</span></p><div class="form-password"><InputText DisplayName="Password" @bind-Value="RegisterModel.Password" type="password" autocomplete="new-password" /><span class="fluent-icon icon-ic_fluent_eye_16_filled password-toggle"></span></div><ValidationMessage For="() => RegisterModel.Password" class="danger" /></label><label><p>@AuthFormLocalization.ConfirmPassword<span class="danger">*</span></p><div class="form-password"><InputText DisplayName="@AuthFormLocalization.ConfirmPassword" @bind-Value="RegisterModel.ConfirmPassword" type="password" autocomplete="new-password" /><span class="fluent-icon icon-ic_fluent_eye_16_filled password-toggle"></span></div><ValidationMessage For="() => RegisterModel.ConfirmPassword" class="danger" /></label></fieldset><fieldset class="form-checkbox-area" disabled="@isProcessing"><label><InputCheckbox @bind-Value="RegisterModel.KeepLogin" /> @AuthFormLocalization.KeepLogin</label><label><InputCheckbox @bind-Value="RegisterModel.AgreeLegal" /> @((MarkupString)FormLocalization.LegalNote)<ValidationMessage For="() => RegisterModel.AgreeLegal" class="danger" /></label></fieldset><button type="submit" class="cta-btn primary-cta-btn" disabled="@isProcessing"> @if (!isProcessing) { @localizer["Register"] } else {<span class="loader"></span> }</button><p class="form-hint">@((MarkupString)localizer["FormHint"].Value)</p></EditForm></div><script src="/js/form.js"></script>@code { private RegisterModel RegisterModel { get; set; } = null!; private EditContext editContext = null!; private ValidationMessageStore validationMessageStore = null!; private bool isProcessing = false; [Inject] private NavigationManager navigation { get; set; } = null!; protected override void OnInitialized() { RegisterModel ??= new(); editContext = new(RegisterModel); validationMessageStore = new(editContext); editContext.OnFieldChanged += (_, args) => { validationMessageStore.Clear(args.FieldIdentifier); editContext.NotifyValidationStateChanged(); }; } private async Task HandleOnValidSubmit() { isProcessing = true; validationMessageStore.Clear(); // Try register account HttpResponseMessage res = await api.HttpClient.PostAsJsonAsync("auth/register", RegisterModel); if (res.IsSuccessStatusCode) { navigation.NavigateTo("/"); } else if (res.StatusCode == System.Net.HttpStatusCode.BadRequest) { HttpValidationProblemDetails problemDetails = (await res.Content.ReadFromJsonAsync<HttpValidationProblemDetails>())!; if (problemDetails.Errors != null) { foreach (KeyValuePair<string, string[]> message in problemDetails.Errors) { FieldIdentifier fieldIdentifier = new(RegisterModel, message.Key); validationMessageStore.Add(fieldIdentifier, message.Value); } editContext.NotifyValidationStateChanged(); } } isProcessing = false; }}I want everything in the page to be rendered on the server as well as realtime data validation, except HandleOnValidSubmit() to run on the client. I tried using the InteractiveWebAssembly rendermode, but apparently it's not the right approach or I'm doing something wrong.