Grid Unexpected Auto-Focus When Selecting a Row Programmatically

We have an application where we always select the first row of a grid automatically.  The grid is positioned in the document flow below other content.

In Syncfusion, the recommendation is to use SelectRowAsync().

The problem is, SelectRowAsync() automatically scrolls the grid into focus.  This is not an acceptable outcome.  The user needs to start at the top of the content and read downwards, instead of jumping to the first grid.

Is there a way to change the row selection programmatically without scrolling?

The following solutions would not work for our use case:

Unsatisfactory Solution
Reason
Change the scroll back afterward.
Would cause widespread screen jitter
Use SelectedRowIndex to set the row index at initial rendering.Our grid loads and reloads lazily, data is unavailable at initial rendering


The following solutions would be acceptable:

Satisfactory SolutionReason
Add new parameter "noScroll" to SelectRowAsync() call.Allows caller to decide if scroll is needed
Other?


Minimal example to reproduce is attached.


Attachment: Minimal_Sample_4ba001df.zip


6 Replies 1 reply marked as answer

NP Naveen Palanivel Syncfusion Team August 31, 2025 01:29 PM UTC

Hi Stephen Green,

We reviewed your query and it seems that when the grid is positioned at the bottom of the page, calling the SelectRowAsync() method causes auto-scrolling, which interferes with the user's intended reading flow. To avoid this unwanted scrolling, instead of calling the SelectRowAsync() method in the DataBound event, please move the method call to the OnAfterRender lifecycle method. Kindly refer the code snippet and the modified sample provided below:

   private SfGrid<RowData>? grid;

   private RowData[] testData = [];

 

   protected override void OnAfterRender(bool firstRender)

   {

       if (firstRender)

       {

           _ = LoadData();

           grid.SelectRowAsync(0);

       }

   

   }

 

   private async Task LoadData()

   {

       testData = await FetchDataAsync();

       StateHasChanged();

   }

 

   private Task<RowData[]> FetchDataAsync()

   {

       return Task.FromResult(new RowData[] { new RowData() { Value1 = "Row #1" } });

   }

 

   private async Task AutoSelectFirstRow()

   {

     

   }



Regards,
Naveen


Attachment: Minimal_Sample_d4b0601b.zip


SG Stephen Green September 5, 2025 04:13 PM UTC

Testing found the proposed solution is dependent on timing and doesn't work in the general case.

Adjusting Minimal Sample to Mimic Real-World Performance

The solution only works if FetchDataAsync() takes no time to execute, as in the minimal example.  However, a real-world implementation would take time to load from an API (or other data source):

private async Task<RowData[]> FetchDataAsync()
{
    await Task.Delay(5000); // Mimic real-world delay fetching data
    return new RowData[] { new RowData() { Value1 = "Row #1" } };
}

Proposed Solution Selects Row Too Early

With this modification in place, the proposed solution now attempts to select the row too early.  The result is that no row is selected:

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender)
    {
        _ = LoadData();
        await grid.SelectRowAsync(0); // No effect, selects too early
    }
}

Waiting for Data Reverts to Original Problem

On the other hand, if we wait for the data to load, then we're right back where we started.  The original auto-scroll problem recurs.

Testing found auto-scroll still occurs regardless if we await within the same OnAfterRender loop, a subsequent OnAfterRender, or via the DataBound handler.  It occurs in all these cases:

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender)
    {
        await LoadData();
        await grid.SelectRowAsync(0); // Still auto-scrolls
    }
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender)
        await LoadData();
    await grid.SelectRowAsync(0); // Still auto-scrolls
}

Conclusion

Testing showed the proposed solution does not work in a real-world use case.

Is there another solution to avoid the auto-scroll?



NP Naveen Palanivel Syncfusion Team September 10, 2025 03:56 PM UTC

Hi Stephen ,

We checked and it seems that in your real-time application, data takes some time to load and bind to the grid. Because of this delay, the solution using SelectRowAsync in OnAfterRender does not work as expected.

We would like to inform you that by default, when using the SelectRowAsync method to select a row programmatically, the grid automatically receives focus. This focus behavior causes the page to scroll to the grid, as the scroll position is determined by where the focus is applied.

In your previous update, you mentioned that using the SelectedRowIndex property of the SfGrid did not work because the data is not available initially—it loads with a delay. We tested this scenario by setting a delay of 5000ms and then applying SelectedRowIndex. In this case, the row was selected without causing a scroll.

If the reported issue still occurs when using SelectedRowIndex, we suggest rendering the grid only after the data is fully loaded. You can control this using a boolean flag and render the grid conditionally after the data is available, along with setting the SelectedRowIndex property.

 

    <SfGrid @ref="grid" TValue="RowData" SelectedRowIndex="0" DataSource=@testData>

        <GridEvents TValue="RowData" DataBound=@AutoSelectFirstRow />

    </SfGrid>

 

    <div style="width: 600px; height: 1000px;" />

</div>

 

@code {

    public class RowData

    {

        public string Value1 { get; set; } = "";

    }

 

    private SfGrid<RowData>? grid;

    private RowData[] testData = [];

 

    protected override async Task OnAfterRenderAsync(bool firstRender)

    {

        if (firstRender)

        {

 

            await LoadData();

            //await grid.SelectRowAsync(0); // Still auto-scrolls

        }

    }

 

    private async Task LoadData()

    {

        testData = await FetchDataAsync();

        StateHasChanged();

    }

 

 

    private async Task<RowData[]> FetchDataAsync()

    {

        await Task.Delay(5000); // Simulates delay when fetching data

        return new RowData[] { new RowData() { Value1 = "Row #1" } };

    }

 

 

    private async Task AutoSelectFirstRow()

    {

     

    }



Regards,
Naveen


Attachment: Minimal_Sample_ca24ad5.zip

Marked as answer

SG Stephen Green September 19, 2025 09:44 PM UTC

We spent about a day trying to get SelectedRowIndex to work with both initial loads and reloads, but we found it difficult to get it to work consistently in all cases.

Only our best attempt worked consistently, but it depended on a complex sequence of events.  For future reference, our pseudocode was as follows:

// Refresh is required to display the new grid data and row selection.
dataBind = grid.StartDataBind();
grid.Items = list;
grid.SelectedRowIndex = 0;
grid.ForceGridRefresh(); // Hard refresh of the grid is required. Calling StateHasChanged() on the grid did not work consistently in testing.
await CompleteDataBind();
dataBind = grid.StartDataBind();
grid.ForceGridRefresh(); // Second refresh is also required! It is the only way to get autofit and row selection to work consistently.
await CompleteDataBind();
await grid.AutoFit(); // We use auto-fit in our application, unrelated.

The data bind is a TaskCompletionSource, completed when the DataBound event fires.  ForceGridRefresh is our own implementation that uses an if statement to force a hard refresh when StateHasChanged() seems to have no effect.

This was the only ordering of actions that produced a consistent result for us.  Various simpler implementations failed under various circumstances.

In the end, we decided against this approach as too elaborate and unpredictable.  We used JavaScript instead to disconnect the scrollIntoView() function so Syncfusion can't use it, and then restored it a short time later.  We also captured and restored all the scroll positions and active focus.

I will mark the prior post as the answer because it seems to be the official approach supported by Syncfusion, and works in simple use cases.  It did not work consistently in our application, however.



SG Stephen Green September 19, 2025 09:45 PM UTC

In the end, we decided against this approach as too elaborate and unpredictable.

Instead, we used JavaScript to disconnect the scrollIntoView() function so Syncfusion can't use it, and then restored it a short time later.  We also captured and restored all the scroll positions and active focus.

I will mark the prior post as the answer because it seems to be the official approach supported by Syncfusion, and works in simple use cases.  However, it did not work consistently in our application.



PS Prathap Senthil Syncfusion Team September 22, 2025 01:50 PM UTC

Thank you for the update.


Regarding the reported problem, to avoid this issue, we suggest rendering the grid only after the data is fully loaded. You can control this by checking if the list count is greater than 0, or you can use any other condition based on your requirements to render the grid conditionally once the data is available. Additionally, you can set the SelectedRowIndex property at this time.


Kindly refer to the code snippet and sample below for your reference.

    @if(testData.Count()>0)

    {

        <SfGrid @ref="grid" TValue="RowData" SelectedRowIndex="0" DataSource=@testData>

            <GridEvents TValue="RowData" DataBound=@AutoSelectFirstRow />

        </SfGrid>

    }

 


Could you please try the above solution and let us know if the issue still persists? If so, to further investigate, we need additional clarification from your side. Please provide the following details to help us proceed:

  • To help us analyze the issue, could you provide a simple, reproducible sample that demonstrates the problem? This will allow us to identify the issue more effectively and provide a resolution.
  • Could you please share with us your attempt to replicate the issue using the attached sample?

The information you provide will be very helpful in validating the reported query on our end and in providing a solution as quickly as possible. Thank you for your understanding.


Attachment: Minimal_Sample_Modified_76caca29.zip

Loader.
Up arrow icon