Radzen Validator popups lose anchoring on scroll

There is a positioning bug with the Radzen Validator in combination with the RadzenFormField when Popup="true". The validation tooltips do not "stick" to their associated RadzenFormField when the container or page is scrolled.

Steps to Reproduce:

  1. Create a long form where the "Submit" button is below the fold.

  2. Trigger validation (e.g., click Submit while fields are empty).

  3. Scroll the page/container up or down.

Actual Result:
The validation popups remain fixed to their original coordinates on the screen, effectively "floating" away from the input fields they are supposed to validate.

Expected Result:
The popups should be anchored to the FormField and move dynamically with the field during a scroll event.

Reproducibility:

This effect is consistently reproducible within the Radzen Blazor Playground.

This is the script I used in the playground

@using Radzen
@using System.Text.Json

<div class="rz-p-0 rz-p-md-12">
    <RadzenStack Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center" Gap="0.5rem" class="rz-p-4 rz-mb-6 rz-border-radius-1" Style="border: var(--rz-grid-cell-border);">
        <RadzenLabel Text="Variant:" />
        <RadzenSelectBar @bind-Value="@variant" TextProperty="Text" ValueProperty="Value" Data="@(Enum.GetValues(typeof(Variant)).Cast<Variant>().Select(t => new { Text = $"{t}", Value = t }))" Size="ButtonSize.Small" class="rz-display-none rz-display-xl-flex" />
        <RadzenDropDown @bind-Value="@variant" TextProperty="Text" ValueProperty="Value" Data="@(Enum.GetValues(typeof(Variant)).Cast<Variant>().Select(t => new { Text = $"{t}", Value = t }))" class="rz-display-inline-flex rz-display-xl-none" />
    </RadzenStack>
    <RadzenTemplateForm TItem="Model" Data=@model Submit=@OnSubmit InvalidSubmit=@OnInvalidSubmit>
        <RadzenStack Gap="1rem" class="rz-p-sm-12">
            <RadzenFormField Text="First Name" Variant="@variant">
                <ChildContent>
                    <RadzenTextBox Name="FirstName" @bind-Value=@model.FirstName />
                </ChildContent>
                <Helper>
                    <RadzenRequiredValidator Component="FirstName" Text="First name is required." Popup="true"
                />
                </Helper>
            </RadzenFormField>
            <RadzenFormField Text="Last Name" Variant="@variant">
                <ChildContent>
                    <RadzenTextBox Name="LastName" @bind-Value=@model.LastName />
                </ChildContent>
                <Helper>
                    <RadzenRequiredValidator Component="LastName" Text="Last name is required." Popup="true" />
                </Helper>
            </RadzenFormField>
            <RadzenFormField Text="First Name" Variant="@variant">
                <ChildContent>
                    <RadzenTextBox Name="FirstName" @bind-Value=@model.FirstName />
                </ChildContent>
                <Helper>
                    <RadzenRequiredValidator Component="FirstName" Text="First name is required." Popup="true"
                />
                </Helper>
            </RadzenFormField>
            <RadzenFormField Text="Last Name" Variant="@variant">
                <ChildContent>
                    <RadzenTextBox Name="LastName" @bind-Value=@model.LastName />
                </ChildContent>
                <Helper>
                    <RadzenRequiredValidator Component="LastName" Text="Last name is required." Popup="true" />
                </Helper>
            </RadzenFormField>
            <RadzenFormField Text="First Name" Variant="@variant">
                <ChildContent>
                    <RadzenTextBox Name="FirstName" @bind-Value=@model.FirstName />
                </ChildContent>
                <Helper>
                    <RadzenRequiredValidator Component="FirstName" Text="First name is required." Popup="true"
                />
                </Helper>
            </RadzenFormField>
            <RadzenFormField Text="Last Name" Variant="@variant">
                <ChildContent>
                    <RadzenTextBox Name="LastName" @bind-Value=@model.LastName />
                </ChildContent>
                <Helper>
                    <RadzenRequiredValidator Component="LastName" Text="Last name is required." Popup="true" />
                </Helper>
            </RadzenFormField>
            <RadzenFormField Text="First Name" Variant="@variant">
                <ChildContent>
                    <RadzenTextBox Name="FirstName" @bind-Value=@model.FirstName />
                </ChildContent>
                <Helper>
                    <RadzenRequiredValidator Component="FirstName" Text="First name is required." Popup="true"
                />
                </Helper>
            </RadzenFormField>
            <RadzenFormField Text="Last Name" Variant="@variant">
                <ChildContent>
                    <RadzenTextBox Name="LastName" @bind-Value=@model.LastName />
                </ChildContent>
                <Helper>
                    <RadzenRequiredValidator Component="LastName" Text="Last name is required." Popup="true" />
                </Helper>
            </RadzenFormField>
            <RadzenFormField Text="First Name" Variant="@variant">
                <ChildContent>
                    <RadzenTextBox Name="FirstName" @bind-Value=@model.FirstName />
                </ChildContent>
                <Helper>
                    <RadzenRequiredValidator Component="FirstName" Text="First name is required." Popup="true"
                />
                </Helper>
            </RadzenFormField>
            <RadzenFormField Text="Last Name" Variant="@variant">
                <ChildContent>
                    <RadzenTextBox Name="LastName" @bind-Value=@model.LastName />
                </ChildContent>
                <Helper>
                    <RadzenRequiredValidator Component="LastName" Text="Last name is required." Popup="true" />
                </Helper>
            </RadzenFormField>
            <RadzenButton ButtonType="ButtonType.Submit" Text="Submit" ></RadzenButton>
        </RadzenStack>
    </RadzenTemplateForm>
    <EventConsole @ref=@console />
</div>

@code {
    Variant variant = Variant.Outlined;

    class Model
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }

    Model model = new Model();
    EventConsole console;

    void OnSubmit(Model model)
    {
        console.Log($"Submit: {JsonSerializer.Serialize(model, new JsonSerializerOptions() {  WriteIndented = true })}");
    }

    void OnInvalidSubmit(FormInvalidSubmitEventArgs args)
    {
        console.Log($"InvalidSubmit: {JsonSerializer.Serialize(args, new JsonSerializerOptions() {  WriteIndented = true })}");
    }
}

The result

Thanks for looking into the matter,

David

Additional Observations on Workarounds:
I attempted to move the RadzenValidator from the Helper template directly into the ChildContent of the RadzenFormField.

  • Result: This resolves the scrolling "drift" (the popup now sticks to the field).

  • New Issue: However, the positioning is now offset/incorrect. The popup no longer aligns properly with the bottom of the input.

This will fix it Radzen Validator popups lose anchoring on scroll ยท radzenhq/radzen-blazor@f23732c ยท GitHub

It will be released early next week.

1 Like