Here's how I accomplished it. I'm using OnInvalidSubmit on the EditForm. My ValidationMessage control adds the class 'validation-message' so I'm scrolling to the parent element of the first error message found, you may want to go an extra node up depending on your HTML.
I created a class for my Blazor page to inherit from
public class FormBase : ComponentBase
{
[Inject]
protected IJSRuntime JSRuntime { get; set; } = null!;
internal async Task HandleInvalidSubmit()
{
await JSRuntime.InvokeVoidAsync("scrollToFirstError");
}
}
Then inherit that in the razor page and add the OnInvalidSubmit to EditForm
@inherits FormBase
<EditForm EditContext="editContext" OnInvalidSubmit="@HandleInvalidSubmit">
My JavaScript is as follows. I added a 500ms delay so the page has time to add the error messages before getElementsByClassName is called
function scrollToFirstError() {
delay(500).then(() => {
var element = document.getElementsByClassName("validation-message")[0];
if (element != null) {
element.parentNode.scrollIntoView();
}
});
}
function delay(time) {
return new Promise(resolve => setTimeout(resolve, time));
}