Grid not saving on enter

I have a SfGrid object that is not firing the updated/updating events when I press the enter key.  I have searched for help on this topic, but all I can find is a reminder to make sure that one of the columns is set as the primary key.  I have done this.


I'm not sure if there's something simple that I've missed, but I would appreciate some help, I'm not sure what the problem is.  I've tested by adding a toolbar, and manually pressing the 'Update' button didn't work either.  I've experimented with adding Edited/Editing handlers to the grid, and THOSE fired, but the Update/Updated ones do not.


I'd appreciate any help you can offer.


Edited for details:  Syncfusion version 30.2.7.


<SfGrid @ref="Grid" TValue="Parcel" AllowPaging="true" AllowSorting="true" AllowFiltering="true" AllowResizing="true">
    <SfDataManager Adaptor="Adaptors.CustomAdaptor">
        <ParcelDataComponent></ParcelDataComponent>
    </SfDataManager>
    <GridEditSettings Mode="EditMode.Normal" AllowEditing="true"></GridEditSettings>
    <GridFilterSettings Type="Syncfusion.Blazor.Grids.FilterType.Excel"></GridFilterSettings>
    <GridEvents TValue="Parcel" RowUpdating="RowUpdatingHandler"></GridEvents>
    <GridTemplates>
        <EmptyRecordTemplate>
            <span>There are no parcels currenty stored in the database.</span>
        </EmptyRecordTemplate>
    </GridTemplates>
    <GridColumns>
        <GridColumn Field="@nameof(Parcel.Id)" HeaderText="Id" TextAlign="TextAlign.Center" IsPrimaryKey="true" Visible="false"></GridColumn>
        <GridColumn HeaderText="Link" AllowFiltering="false" AllowSorting="false" AllowSearching="false" TextAlign="TextAlign.Center" Width="70">
            <Template>
                @{
                    var parcel = (context as Parcel);
                    <SfButton CssClass="e-link" IconCss="e-icons e-circle-info" OnClick="@((args) => NavigateToParcel(parcel))"></SfButton>
                }
            </Template>
        </GridColumn>
        <GridColumn Field="@nameof(Parcel.AccountNumber)" HeaderText="Account Number" TextAlign="TextAlign.Right" Width="50"></GridColumn>
        <GridColumn Field="@nameof(Parcel.AddressLine1)" HeaderText="Address" TextAlign="TextAlign.Right">
            <Template>
                @{
                    var parcel = (context as Parcel);
                    var displayText = parcel?.AddressLine1;
                    if (!String.IsNullOrEmpty(parcel?.AddressLine2))
                    {
                        displayText += " (" + parcel.AddressLine2 + ")";
                    }
                    <span>@displayText</span>
                }
            </Template>
        </GridColumn>
        <GridColumn Field="Phase.Label" HeaderText="Phase" TextAlign="TextAlign.Right" Width="120">
            <EditTemplate>
                <SfDropDownList TValue="int?" TItem="Phase" DataSource="Phases" Placeholder="Select Phase" @bind-Value="((context as Parcel).PhaseId)">
                    <DropDownListFieldSettings Value="Id" Text="Label"></DropDownListFieldSettings>
                </SfDropDownList>
            </EditTemplate>
        </GridColumn>
        <GridColumn Field="@nameof(Parcel.Block)" HeaderText="Block" TextAlign="TextAlign.Right" Width="100"></GridColumn>
        <GridColumn Field="@nameof(Parcel.Lot)" HeaderText="Lot" TextAlign="TextAlign.Right" Width="100"></GridColumn>
        <GridColumn Field="@nameof(Parcel.Latitude)" HeaderText="Latitude" TextAlign="TextAlign.Right" Width="110"></GridColumn>
        <GridColumn Field="@nameof(Parcel.Longitude)" HeaderText="Longitude" TextAlign="TextAlign.Right" Width="110"></GridColumn>
    </GridColumns>


@code {


public SfGrid<Parcel> Grid { get; set; } = default!;
    public List<Phase> Phases { get; set; } = new List<Phase>();
public async Task RowUpdatingHandler(RowUpdatingEventArgs<Parcel> args)
    {
        try
        {
            using (var context = UFactory.CreateDbContext())
            {
                Parcel updatedParcel = await context.UpdateParcelTableRow(args.Data, CurrentUser);
                this.ToastService.ShowToast(new ToastOption()
                {
                    Title = "Success",
                    Content = $"Parcel {updatedParcel.DisplayName} has been successfully updated.",
                    CssStyle = ToastStyle.Success
                });
            }


            await RefreshGrid();
        }
        catch (Exception ex)
        {
            args.Cancel = true;
            this.ToastService.ShowToast(new ToastOption()
            {
                Title = "Error",
                Content = Helper.FormatException(ex),
                CssStyle = ToastStyle.Error
            });
        }
    }


protected override async void OnInitialized()
    {
        using (var context = UFactory.CreateDbContext())
        {
            Phases = await context.Phases.ToListAsync();
        }
    }




}



4 Replies

PS Prathap Senthil Syncfusion Team September 8, 2025 09:35 AM UTC

Hi Christopher,

We reviewed your query and found that the issue occurs when editing and updating a record — the update does not work, and the update event is not triggered either. To investigate further, we created a simple sample and tested the scenario on our end. However, we were unable to reproduce the issue. We suspect that CRUD operations are not handled in the CustomAdaptor component. For your reference, please find the sample attached below.


To further investigate and validate the issue you're facing, we kindly request that you share the following details:


  1. Please provide the code snippet of the Grid and the custom adaptor used in the component (i.e., the ParcelDataComponent).
  2. Share with us the video demonstration of the issue in elaborately, it will be more useful to us.
  3. Share with us a simple issue replicating sample, or try to modify the mentioned sample.


The above-requested details will be very helpful for us to validate the reported query at our end and provide the solution as early as possible.

Regards,
prathap s


Attachment: BlazorApp11_(1)_764cfb87.zip


CH Christopher September 8, 2025 12:33 PM UTC

I have already provided the snippet of the grid object in my first message.  I will provide a snippet of the data adaptor below, but you're correct, I have not handled all CRUD operations in the CustomAdaptor.   I would like to use the RowUpdate / RowUpdated handler on the grid

Creating a video of this behaviour is a time commitment I cannot make at this time; I don't know how to do that, and I don't have time to learn.

Does using a Custom Adaptor cancel out the the handlers on the grid?  Why would it cancel the Updated/Updating handlers (which are not reached when I set a breakpoint) but not the Edited/Editing handlers (which ARE reached when I set a breakpoint.)  Is this behaviour documented somewhere?  For what it's worth, I HAVE attempted to incorporate the Update/UpdateAsync handlers in the CustomAdaptor, but those breakpoints were not reached either:  pressing Enter while editing a row gave no response at all.

Below is the the copy of my CustomAdaptor.

@using Syncfusion.Blazor

@using Syncfusion.Blazor.Data
@using Utiliville.Data
@using Utiliville.Models
@using Newtonsoft.Json
@using Microsoft.EntityFrameworkCore
@using Utiliville.Managers


@inject ToastService ToastService
@inject IDbContextFactory<ApplicationDbContext> UFactory
@inherits DataAdaptor<Parcel>


    <CascadingValue Value="@this">
        @ChildContent
    </CascadingValue>


@code {
    [Parameter]
    [JsonIgnore]
    public RenderFragment ChildContent { get; set; }


    public override object Read(DataManagerRequest dm, string additionalParam = null)
    {
        var context = UFactory.CreateDbContext();


        IEnumerable<Parcel> DataSource = context.Parcels.Include(x=> x.Phase).AsEnumerable<Parcel>();
        if (dm.Search != null && dm.Search.Count > 0)
        {
            //Searching
            DataSource = DataOperations.PerformSearching(DataSource, dm.Search);
        }
        if (dm.Sorted != null && dm.Sorted.Count > 0)
        {
            // Sorting
            DataSource = DataOperations.PerformSorting(DataSource, dm.Sorted);
        }
        if (dm.Where != null && dm.Where.Count > 0)
        {
            // Filtering
            DataSource = DataOperations.PerformFiltering(DataSource, dm.Where, dm.Where[0].Operator);
        }


        int count = DataSource.Cast<Parcel>().Count();


        if (dm.Skip != 0)
        {
            //Paging
            DataSource = DataOperations.PerformSkip(DataSource, dm.Skip);
        }
        if (dm.Take != 0)
        {
            DataSource = DataOperations.PerformTake(DataSource, dm.Take);
        }
        return dm.RequiresCounts
            ? new DataResult() { Result = DataSource, Count = count }
            : (object)DataSource;
    }




    public override object Update(DataManager dataManager, object record, string primaryColumnName, string additionalParam)
    {
        return base.Update(dataManager, record, primaryColumnName, additionalParam);
    }


    public override Task<object> UpdateAsync(DataManager dataManager, object record, string primaryColumnName, string additionalParam)
    {
        return base.UpdateAsync(dataManager, record, primaryColumnName, additionalParam);
    }
}






CH Christopher September 8, 2025 07:14 PM UTC

An update:


One of the fields - "City" is marked as required at the class level, but it's not included in the table.  The affected records were those that didn't have an entry for this field, but there was no place for the table to show the validation, as that happens in a tooltip.


Thank you for looking into this.  I wish there'd been a way to know that this was a validation error, but as far as I know, there's no built in hook for 'OnValidate' for a record.



NP Naveen Palanivel Syncfusion Team September 11, 2025 04:57 AM UTC

Hi Christopher,

We reviewed your query and found that the reported issue occurs when a column in the model class has the [Required] validation attribute, but this column is not defined in the grid. During editing and saving, if the value for this field is null, the model validation fails. However, since the column is not present in the grid UI, the validation message is not displayed, making it impossible for the user to correct the error and save the row. When editing the grid, the RowEditing event is triggered. In this event, we pass the EditContext, which help us to determine whether the validation was successful.

To handle this scenario, we implemented a JavaScript-based solution. When the grid is in edit mode and the Enter key is pressed, we detect the keydown event and check whether the grid is currently in edit state. If it is, we manually trigger form validation using FormSubmit, passing the EditContext to verify whether the form is valid.

Please refer to the provided code snippet for more details.

@using Syncfusion.Blazor.Grids

@using System.ComponentModel.DataAnnotations;

@inject IJSRuntime JSRuntime

@using System.Text.RegularExpressions;

 

<SfGrid TValue="Parcel" @ref="Grid" AllowPaging="true" AllowSorting="true" AllowFiltering="true"  AllowResizing="true">

    <SfDataManager Adaptor="Adaptors.CustomAdaptor">

        <CustomAdaptorComponent></CustomAdaptorComponent>

    </SfDataManager>

    <GridEditSettings Mode="EditMode.Normal" AllowEditing="true"></GridEditSettings>

    <GridFilterSettings Type="Syncfusion.Blazor.Grids.FilterType.Excel"></GridFilterSettings>

    <GridEvents TValue="Parcel" RowUpdating="RowUpdatingHandler" RowEditing="RowEditingHandler"></GridEvents>

    <GridTemplates>

        <EmptyRecordTemplate>

            <span>There are no parcels currenty stored in the database.</span>

        </EmptyRecordTemplate>

    </GridTemplates>

    <GridColumns>

        <GridColumn Field=@nameof(Parcel.Id) HeaderText="ID" IsPrimaryKey="true" TextAlign="@TextAlign.Center" Width="140"></GridColumn>

        <GridColumn Field=@nameof(Parcel.CustomerID) HeaderText="Customer Name" Width="150"></GridColumn>

    </GridColumns>

</SfGrid>

<script>

 

    window.gridKeydownInterop = {

    initialize: function (dotNetHelper) {

    this.dotNetReference = dotNetHelper;

    this.handleDocumentKeyDown = this.handleDocumentKeyDown.bind(this);

    document.addEventListener('keydown', this.handleDocumentKeyDown);

    },

 

    handleDocumentKeyDown: function (event) {

    if (event.key === 'Enter') {

    this.dotNetReference.invokeMethodAsync('HandleEnterKey');

    }

    }

    };

 

</script>

 

<h3>@message</h3>

@code {

 

    public static List<Parcel> Orders { get; set; }

    private SfGrid<Parcel> Grid;

    private EditContext editContext;

 

 

    protected override async Task OnAfterRenderAsync(bool firstRender)

    {

        if (firstRender)

        {

            await JSRuntime.InvokeVoidAsync("gridKeydownInterop.initialize", DotNetObjectReference.Create(this));

        }

    }

 

 

    [JSInvokable]

    public async Task HandleEnterKey()

    {

 

        if (Grid?.IsEdit == true)

        {

            FormSubmit(editContext);

        }

    }

    public void RowEditingHandler(RowEditingEventArgs<Parcel> args)

    {

        this.editContext = args.EditContext;

    }

 

    string message;

    private void FormSubmit(EditContext context)

    {

        // Validates the EditContext and returns bool to indicate whether it has valid or invalid input values.

        bool isValid = context.Validate();

        if (isValid)

        {

            message = "Form has valid inputs";

        }

        else

        {

            message = "Form has Invalid inputs, clear the validation";

        }

    }


Please get back to us if you have any concerns.


Regards,

Naveen


Loader.
Up arrow icon