Search code examples
blazor-server-sideserver-side-rendering

Blazor server, Static SSR page, Enhance forms not working


I build a test page with two forms:

@page "/ssr"
@layout StaticSSRMainLayout
@attribute [ExcludeFromInteractiveRouting]
@using BlazorPageScript
@using System.ComponentModel.DataAnnotations
@using System.Text
@using System.Text.Encodings.Web
@using Microsoft.AspNetCore.WebUtilities
@using BlazorApp9.Data
@implements IDisposable

<PageTitle>SSR Page</PageTitle>

<PageScript Src="./Pages/Tests/StaticSSR/StaticSSRPage.razor.js"></PageScript>

<div>
    <div class="row">
        <div class="col-md-4">
            <EditForm Model="Input" FormName="show-email1" id="showEmail1Input" OnValidSubmit="OnValidSubmitAsync" method="post" Enhance>
                <DataAnnotationsValidator />
                <ValidationSummary class="text-danger" role="alert" />
                <div class="form-floating mb-3">
                    <InputText @bind-Value="Input.Email" class="form-control" aria-required="true" placeholder="[email protected]" id="showEmail1Input" />
                    <label for="email" class="form-label">Email</label>
                    <ValidationMessage For="() => Input.Email" class="text-danger" />
                </div>
                <button type="submit" class="w-100 btn btn-lg btn-primary">Show1</button>
            </EditForm>
        </div>

        <div class="col-md-4">
            <EditForm Model="Input2" FormName="show-email12" id="showEmail2Input" OnValidSubmit="OnValidSubmitAsync2" method="post" Enhance>
                <DataAnnotationsValidator />
                <ValidationSummary class="text-danger" role="alert" />
                <div class="form-floating mb-3">
                    <InputText @bind-Value="Input2.Email" class="form-control" aria-required="true" placeholder="[email protected]" id="showEmail1Input2" />
                    <label for="email" class="form-label">Email</label>
                    <ValidationMessage For="() => Input2.Email" class="text-danger" />
                </div>
                <button type="submit" class="w-100 btn btn-lg btn-primary">Show1</button>
            </EditForm>
        </div>
    </div>
    <div>
        <RadzenAlert Variant="Variant.Filled" AlertStyle="@AlertStyle.Info" Size="@AlertSize.Medium" Shade="Shade.Light" AllowClose=true Text="Message">
            @message
        </RadzenAlert>
        <RadzenText TextStyle="TextStyle.DisplayH3" TagName="TagName.H3" class="rz-display-flex rz-mt-2 rz-my-0">
            Email: @email
        </RadzenText>            
    </div>
    <div>
        <RadzenAlert Variant="Variant.Filled" AlertStyle="@AlertStyle.Info" Size="@AlertSize.Medium" Shade="Shade.Light" AllowClose=true Text="Message">
            @message2
        </RadzenAlert>
        <RadzenText TextStyle="TextStyle.DisplayH3" TagName="TagName.H3" class="rz-display-flex rz-mt-2 rz-my-0">
            Email: @email2
        </RadzenText>            
    </div>
</div>

@code {
   
    string message = null;
    string email = null;    
    int id = 5;

    string message2 = null;
    string email2 = null;   
    int id2 = 5;


    [SupplyParameterFromForm(FormName = "show-email1")]
    private InputModel Input { get; set; } = new();

    [SupplyParameterFromForm(FormName = "show-email12")]
    private InputModel2 Input2 { get; set; } = new();

    protected override async Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();        
    }

    private async Task OnValidSubmitAsync()
    {
        email = Input.Email;
        message = "Verification email sent. Please check your email.";
        id = 114;
    }

    private sealed class InputModel
    {
        [Required]
        [EmailAddress]
        public string Email { get; set; } = "";
    }


    private async Task OnValidSubmitAsync2()
    {
        email2 = Input2.Email;
        message2 = "Verification email sent. Please check your email.";
        id2 = 114;
    }

    private sealed class InputModel2
    {
        [Required]
        [EmailAddress]
        public string Email { get; set; } = "";
    }


    public async void Dispose()
    {
    }
}

I use blazor.web.js in App.razor, but Enhance forms is not working. When send a form and part of the page is updated, when I send the second form, the first form and its update clear and vice versa.

So how to enable enhanced form updates in blazor?

EDIT: in the network tab I see a fetch request is made, so it is working, but when the entire @code{..} block is executed, what is the benefit?! every thing is reset again! the good way is: just the relevant OnValidSubmit() executes.


Solution

  • I solved this problem like this:

    <PageTitle>SSR Page</PageTitle>
        
        <PageScript Src="./Pages/Tests/StaticSSR/StaticSSRPage.razor.js"></PageScript>
        
        <div>
            <div class="row">
                <div class="col-md-4">
                    <EditForm Model="Input" FormName="show-email1"
                              OnValidSubmit="OnValidSubmitAsync1" method="post" Enhance>
                        <DataAnnotationsValidator />
                        <ValidationSummary class="text-danger" role="alert" />
                        <div class="form-floating mb-3" data-permanent>
                            <InputText @bind-Value="Input.Email" class="form-control" aria-required="true" placeholder="[email protected]" />
                            <label class="form-label">Email</label>
                            <ValidationMessage For="() => Input.Email" class="text-danger" />
                        </div>
                        <button type="submit" class="w-100 btn btn-lg btn-primary">Show1</button>
                    </EditForm>
                </div>
        
                <div class="col-md-4">
                    <EditForm Model="Input2" FormName="show-email2"
                              OnValidSubmit="OnValidSubmitAsync2" method="post" Enhance>   
                        <DataAnnotationsValidator />
                        <ValidationSummary class="text-danger" role="alert" />
                        <div class="form-floating mb-3" data-permanent>
                            <InputText @bind-Value="Input2.Email" class="form-control" aria-required="true" placeholder="[email protected]" />
                            <label class="form-label">Email</label>
                            <ValidationMessage For="() => Input2.Email" class="text-danger" />
                        </div>
                        <button type="submit" class="w-100 btn btn-lg btn-primary">Show2</button>
                    </EditForm>
                </div>
            </div>
        
            <div id="up1" data-permanent="@pu1">        
                <h4>@message</h4>
                <h4>Email: @email</h4>
            </div>
        
            <div id="up2" data-permanent="@pu2">        
                <h4>@message2</h4>
                <h4>Email: @email2</h4>
            </div>
        
        </div>
        
        @code {
        
            string message = null;
            string email = null;
        
            string message2 = null;
            string email2 = null;
        
            bool pu1 = true;
            bool pu2 = true;
        
            [SupplyParameterFromForm(FormName = "show-email1")]
            private InputModel Input { get; set; } = new();
        
            [SupplyParameterFromForm(FormName = "show-email2")]
            private InputModel Input2 { get; set; } = new();
        
            protected override async Task OnInitializedAsync()
            {
                await base.OnInitializedAsync();
                StateHasChanged();
            }
        
            private async Task OnValidSubmitAsync1()
            {        
                pu1 = false;
                email = Input.Email;
                message = "Verification email sent. Please check your email.";    
            }
        
            private async Task OnValidSubmitAsync2()
            {        
                pu2 = false;
                email2 = Input2.Email;
                message2 = "Verification email sent. Please check your email.";    
            }
        
            private sealed class InputModel
            {
                [Required]
                [EmailAddress]
                public string Email { get; set; } = "";
            }
        
            public void Dispose()
            {
            }
        }
    

    And in the PageScript file:

    export function onUpdate() {
        console.log('Page Updated'); 
    
        var up1 = document.getElementById("up1");
        var up2 = document.getElementById("up2");
        if (!up1.hasAttribute("data-permanent")) {
            $(up1).attr('data-permanent', '');
            // up1_OnSuccess code
        }
        if (!up2.hasAttribute("data-permanent")) {
            $(up2).attr('data-permanent', '');
            // up2_OnSuccess code
        }
    }
    

    Thanks to 'Ruikai Feng' for note on data-permanent attribute.