We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date
close icon

Datasource does not refresh correctly after edit - reverts to old data

Here's a razor page using the Grid component and a datasource from a list of objects Person. Each person has amongst other things a list of Skills that are many-to-many related via a PersonToSkill table. Reading this data into the grid works fine. However, after editing the Skills field (a multi select), the changes are made to the database AND the List that is the datasource for the grid, yet what I get is a blank output in the grid. Here's the code:

@using MyNamespace.Data.Models
@using Syncfusion.EJ2.Blazor
@using Syncfusion.EJ2.Blazor.Data
@using Syncfusion.EJ2.Blazor.DropDowns
@using Syncfusion.EJ2.Blazor.Grids
@using Microsoft.Extensions.Logging

@page "/test3"

@inject ILogger<Program> logger
@inject Services.Helpers Helpers
@inject Services.PersonService PersonService
@inject Services.SkillService SkillService

<h1>People</h1>
<EjsButton @onclick="@FetchData">Button</EjsButton>
<EjsGrid DataSource="@Persons" ModelType="@Model" @ref="Grid" AllowPaging="true" Toolbar=@ToolbarItems AllowPdfExport="true" AllowExcelExport="true">
    <GridEvents OnActionBegin="ActionBegin" TValue="Person"></GridEvents>
    <GridPageSettings PageSizes="@PageSizes"></GridPageSettings>
    <GridEditSettings AllowAdding="true" AllowEditing="true" AllowDeleting="true" ShowDeleteConfirmDialog="true" Mode="@EditMode.Dialog"></GridEditSettings>
    <GridColumns>
        <GridColumn Field=@nameof(Person.Id) HeaderText="Person Id" IsPrimaryKey="true" Visible="false" TextAlign="TextAlign.Left" Width="50"></GridColumn>
        <GridColumn Field=@nameof(Person.Skills) HeaderText="Skills" TextAlign="TextAlign.Left">
            <Template>
                @{
                    var item = (context as Person);
                    var output = "";
                    if (item.Skills != null)
                    {
                        for (int i = 0i < item.Skills.Counti++)
                        {
                            if (item.Skills[i].Skill != null)
                            {
                                output += item.Skills[i].Skill.Name;
                                if (i < item.Skills.Count - 1output += ", ";
                            }
                        }
                        if (item.Id == 16) {
                            Helpers.Dump(item.Skills);
                        }
                        @output
                    }
                }
            </Template>
            <EditTemplate>
                @{
                    var item = (context as Person);
                    var skillIds = new List<int>();
                    if (item.Skills != null)
                    {
                        for (int i = 0i < item.Skills.Counti++)
                        {
                            skillIds.Add(item.Skills[i].SkillId);
                        }
                    }
                }
                @functions {
                    public void onSelect(Syncfusion.EJ2.Blazor.DropDowns.MultiSelectChangeEventArgs<List<int>> args)
                    {
                        EditMultiValSkills = args.Value;
                    }
                }
                <EjsMultiSelect TValue="List<int>" Value="@skillIds" DataSource="@SkillList" AllowFiltering=true>
                    <MultiSelectEvents TValue="List<int>" ValueChange="@((v)=>onSelect(v))"></MultiSelectEvents>
                    <MultiSelectFieldSettings Text="Name" Value="Id"></MultiSelectFieldSettings>
                </EjsMultiSelect>
            </EditTemplate>
        </GridColumn>
    </GridColumns>
</EjsGrid>

@code {
    EjsGrid<Person> Grid;
    public string[] ToolbarItems = new string[] { "Add", "Edit", "Delete", "Update", "Cancel", "ExcelExport", "Search" };
    public int[] PageSizes = new int[] { 1, 10, 25, 50, 100, 1000 };
    public Person Model = new Person();
    public List<Skill> SkillList { getset; }
    public List<Person> Persons { getset; }
    public List<int> EditMultiValSkills = new List<int>();

    protected override async Task OnInitializedAsync()
    {
        await FetchData();
    }

    protected async Task FetchData()
    {
        logger.LogInformation("FetchData()");
        SkillList = await SkillService.Get();
        Persons = await PersonService.GetAsync();
    }

    public void ActionBegin(ActionEventArgs<Personargs)
    {
        if (args.RequestType == Syncfusion.EJ2.Blazor.Grids.Action.Save)
        {
            Person p = PersonService.Get(args.Data.Id);
            Helpers.Dump(p.Skills, "Skills before edit");
            if (p == nullreturn;
            var skillOrig = p.Skills.Select(x => x.SkillId).Distinct();
            var newSkills = EditMultiValSkills.Except(skillOrig).ToList();
            var removedSkills = skillOrig.Except(EditMultiValSkills).ToList();

            // remove deselected and add new skills
            foreach (var s in newSkills)
            {
                p.Skills.Add(new PersonToSkill() { SkillId = s });
            }
            foreach (var s in removedSkills)
            {
                p.Skills.RemoveAll(x => x.SkillId == s);
            }

            var res = PersonService.Update(p);  // updates item in database

            // manually replace item in List to be extra sure that the data changed
            var indexOfPerson = Persons.IndexOf(Persons.Where(x => x.Id == res.Id).First());
            if (indexOfPerson != -1)
            {
                Persons[indexOfPerson= res;
                Helpers.Dump(Persons[indexOfPerson].Skills, "Skills after edit");
                this.Grid.DataSource = Persons;
                this.Grid.Refresh();
            }
        }
    }
}


As you can see I run some debug output. What happens is that the "Skills before edit" and "Skill after edit" show the changes correctly. Then the output in the <Template> shows up:
It runs through twice, showing the _correct_ changed data.
Then it runs through three times again! showing the _previous_ data.
And finally it displays nothing in that field.

Reloading the page then shows the correct data.





1 Reply

VN Vignesh Natarajan Syncfusion Team January 28, 2020 01:44 PM UTC

Hi Michael,  
 
Greetings from Syncfusion support.  
 
Query: “ the changes are made to the database AND the List that is the datasource for the grid, yet what I get is a blank output in the grid 
 
We have analyzed your query and we are able to reproduce the reported behavior at our end while preparing a sample using your code example. In your code example while inserting the new skills you have created new PersonToSkills object with only Id property. Now the value for Skill property will be null. Hence you have faced the reported issue.  
 
Refer the below code example for errors.  
 
public void ActionBegin(ActionEventArgs<Personargs) 
    { 
        if (args.RequestType == Syncfusion.EJ2.Blazor.Grids.Action.Save) 
        { 
. . . . . . .. .  
 
            // remove deselected and add new skills 
            foreach (var s in newSkills) 
            { 
                p.Skills.Add(new PersonToSkill() { SkillId = s }); 
            } 
            foreach (var s in removedSkills) 
            { 
                p.Skills.RemoveAll(x => x.SkillId == s); 
            } 
if (indexOfPerson != -1) 
            { 
                Persons[indexOfPerson= res; 
                Helpers.Dump(Persons[indexOfPerson].Skills, "Skills after edit"); 
                this.Grid.DataSource = Persons; 
                this.Grid.Refresh(); 
            } 
 
 
 
Kindly modify the above  highlighted codes like below  
 
public void OnBegin(ActionEventArgs<Person> Args) 
    { 
        if(Args.RequestType == Syncfusion.EJ2.Blazor.Grids.Action.Save) 
        { 
            . . . . . . . . .. . .  
            foreach (var s in newSkills) 
            { 
                //add the changes directly yo event arguments proeprty 
                Args.Data.Skills.Add(new PersonToSkill() { Id = s, Skill = SkillList.Where(X=>X.Id == s).FirstOrDefault().Skill }); 
            } 
            foreach (var s in removedSkills) 
            {                 
                //like wise while removing also modify the changes in argument proeprties  
                Args.Data.Skills.RemoveAll(x => x.SkillId == s);             
            } 
        } 
    } 
 
Note: Instead of changing the datasource and refresh, we suggest you to modify the value in event arguments itself.  
 
Kindly get back to us if you are still facing the issue.  
 
Regards, 
Vignesh Natarajan. 


Loader.
Live Chat Icon For mobile
Up arrow icon