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

Re-Select a Row Checkbox using the Primary Key of the Record and not the RowIndex

Is it possible to have the grid automatically select the checkbox when the grid is displayed, for instance, I have a the current grid in a div, but when you select records and press the process button, it hides the div and shows a new grid with just the selected records, now if the user decides to press the 'Back' option, this un-hides the original div and re-shows the 1st grid, but the selected records are no longer selected.

This is my Grid Code, as you can see I enable Persistance and also PersistSelection on the Checkbox, but I cannot keep the checkbox selected when I hide and then re-show the grid.

<SfGrid @ref="TGrid" DataSource="@Timesheets"

        EnablePersistence="true"
        ID="grdTimesheets"
        AllowPaging="true"
        AllowSorting="true"
        Toolbar="ToolbarItems">
    <GridAggregates>
        <GridAggregate>
            <GridAggregateColumns>
                <GridAggregateColumn Field="GetTotalHours" Type="AggregateType.Custom">
                    <FooterTemplate>
                        @{
                            var tHours = @GetSelectedRecords("H").Result;
                            <div>
                                <p>@tHours</p>
                            </div>
                        }
                    </FooterTemplate>
                </GridAggregateColumn>
                <GridAggregateColumn Field="BuyRateCost" Type="AggregateType.Custom">
                    <FooterTemplate>
                        @{
                            var bCost = @GetSelectedRecords("B").Result;
                            <div>
                                <p>£@bCost</p>
                            </div>
                        }
                    </FooterTemplate>
                </GridAggregateColumn>
                <GridAggregateColumn Field="SaleRateCost" Type="AggregateType.Custom">
                    <FooterTemplate>
                        @{
                            var sCost = @GetSelectedRecords("S").Result;
                            <div>
                                <p>£@sCost</p>
                            </div>
                        }
                    </FooterTemplate>
                </GridAggregateColumn>
            </GridAggregateColumns>
        </GridAggregate>
    </GridAggregates>
    <GridSelectionSettings CheckboxOnly="true" PersistSelection="true" />
    <GridPageSettings PageSizes="@pageSizes" PageSize="15" />
    <GridEvents RowDataBound="OnRowBound"
                RowSelected="OnRowSelected"
                RowDeselected="OnRowDeselected"
                CommandClicked="OnGridCommandClicked"
                TValue="ApplicantsWeekTimesheetDto"></GridEvents>
    <GridColumns>
        <GridColumn Field="Id" Visible="false" IsPrimaryKey="true" />
        <GridColumn Field="ApplicantName" HeaderText="Applicant" />
        <GridColumn Field="GetClientAndSite" HeaderText="Client" />
        <GridColumn Field="RoleName" HeaderText="Role Name" Width="150" />
        <GridColumn Field="RateDesc" HeaderText="Pay Rate Name" Width="200" />
        <GridColumn Field="GetBuyRate" Format="N2" HeaderText="Pay Rate" TextAlign="TextAlign.Right" Width="100" />
        <GridColumn Field="GetSaleRate" Format="N2" HeaderText="Charge Rate" TextAlign="TextAlign.Right" Width="100" />
        <GridColumn Field="GetTotalHours" HeaderText="Total Hours" Format="N1" TextAlign="TextAlign.Right" Width="100" />
        <GridColumn Field="BuyRateCost" HeaderText="Buy Cost" Format="N2" TextAlign="TextAlign.Right" Width="100" />
        <GridColumn Field="SaleRateCost" HeaderText="Charge Cost" Format="N2" TextAlign="TextAlign.Right" Width="100" />
        <GridColumn Type="ColumnType.CheckBox" TextAlign="TextAlign.Right" Width="100"></GridColumn>


        <GridColumn HeaderText="Options">
            <GridCommandColumns>
                <GridCommandColumn Type="CommandButtonType.Delete" ButtonOption="@(new CommandButtonOptions() {IconCss="fa-solid fa-clock-rotate-left", CssClass="e-flat grid-delete-btn"})" Title="Reset Hours" ID="btnResetHours" />
                <GridCommandColumn Type="CommandButtonType.None" ButtonOption="@(new CommandButtonOptions() {IconCss="fa-regular fa-clock", CssClass="e-flat grid-add-btn"})" Title="Edit Hours" ID="edtHours" />
                <GridCommandColumn Type="CommandButtonType.Edit" ButtonOption="@(new CommandButtonOptions() {IconCss="fa-solid fa-rotate-left", CssClass="e-flat grid-delete-btn"})" Title="Reset Rates" ID="btnResetRates" />
                <GridCommandColumn Type="CommandButtonType.None" ButtonOption="@(new CommandButtonOptions() {IconCss="fa-solid fa-sterling-sign", CssClass="e-flat grid-edit-btn"})" Title="Edit Rates" ID="edtRate" />
            </GridCommandColumns>
        </GridColumn>
    </GridColumns>
</SfGrid>

13 Replies

SP Sarveswaran Palani Syncfusion Team October 5, 2022 11:25 PM

Hi Simon,

Greetings from Syncfusion support.

We have analyzed your query and facing some complexities while preparing a sample based on your requirement. We'll prepare and update the further details within tomorrow.

Until then we appreciate your patience.

Regards,

Sarveswaran PK



SP Sarveswaran Palani Syncfusion Team October 9, 2022 10:08 PM

Hi Simon,


Sorry for the delay and inconvenience caused.


Query: Is it possible to have the grid automatically select the checkbox when the grid is displayed?


Yes, From your query we suspect that you have different grid with same div, but you need to maintain different persistence state for each Grid by using EnablePersistence.  In DataGrid it is not possible for us to maintain different persisted state for the Grid with same div using persistence.


So, we suggest you to use our inbuilt methods GetPersistData and SetPersistData to get a current grid state and use the state to set in Grid. We have prepared a sample based on your requirement. Kindly refer the attached code snippet and sample for your reference.


Here we have saved the existing grid row index value before it is destroyed by using Destroy method and whenever the Grid loads the data will be bind to grid by using DataBound method from the public variable. Likewise, you can use a service or database to store the data. In our sample we have handled for single Grid instance. By using different services/database we can handle the same for multiple grids.


Note: We should not enable EnablePersistence when using the above methods.


public async Task DataBoundHandler()

    {

        List<double> GridData = GetGridState();

        if (value != null)

        {

            await Grid.SelectRowsAsync(GridData.ToArray());

        }

    }

 

    public async Task DestroyHandler()

    {

       value = await Grid.GetSelectedRowIndexesAsync();

       setGridState(value);

    }


Kindly get back to us if you have any further queries.


Regards,

Sarveswaran PK


Attachment: SfGridPersistValue_2c5432c4.zip


SA Simon Arnold October 10, 2022 03:34 AM

Sorry this does not work for me, as this process does not work with Paging, it also does not keep the state of the grid like the order selected, and current page.


The issue with paging is that if you go to page 5 and you selected the 1st 5 records on page 1, then the 1st 5 records on page 5 get selected.

My Parent Page has this grid component in a single div and this is the only grid with Persistence enabled, and depending on if the user has selected the appropriate button, the code hides the div and then displays a different grid with just the selected records, but this grid does not have persistence enabled.

This is the Parent Page that holds the component, with the Grid Component code after this block:

@page "/process"

@page "/process/{clientId:int}"
@page "/process/{clientId:int}/{siteId:int}"
@inject ITimesheetService ts
@inject SweetAlertService swal
@inject HttpClient httpClient


<div class="card shadow mt-3">
    <div class="card-header bg-primary text-white">
        <h6 class="card-title">Timsheet Wizard</h6>
    </div>
    <div class="card-body">
        <div class="row">
            <div class="col-md-4">
                <div class="alert alert-success">
                    Step 1<br />
                    <small>Select Timesheets</small>
                    @if(ShowStep1) {
                        <span class="float-end">Current Step</span>
                    } else {
                        <span class="float-end">
                            <SfButton IconCss="fa-solid fa-backward-step"
                            CssClass="e-btn e-secondary" Content="Back"
                            OnClick="@BackToStep1">
                        </SfButton></span>
                    }


                </div>
            </div>
            <div class="col-md-4" style="@displayStep2">
                <div class="alert alert-warning">
                    Step 2<br />
                    <small>Save Timesheets</small>
                    @if(!ShowStep1) {
                        <span class="float-end">Current Step</span>
                    }
                </div>
            </div>
        </div>
        <div class="card-text">
            <div class="col-12">
                @if (ShowStep1)
                {
                    <div class="row">
                        <EditForm EditContext="@editContext" OnValidSubmit="SetFilters" OnInvalidSubmit="ShowErrors">
                            <DataAnnotationsValidator />
                            <div class="form-group row">
                                <label for="searchDates" class="col-sm-2 col-form-label full-text">Bookings From/To</label>
                                <div class="col-sm-3">
                                    <SfDateRangePicker @bind-StartDate="Search.BookingsFrom"
                                                   @bind-EndDate="Search.BookingsTo"
                                                   Placeholder="Select Bookings From and To Dates"
                                                   ID="searchDates">
                                    </SfDateRangePicker>
                                </div>
                            </div>
                            <div class="form-group row">
                                <label for="clients" class="col-sm-2 col-form-label">Client</label>
                                <div class="col-sm-3">
                                    <SfDropDownList TValue="int"
                                                ShowClearButton="true"
                                                AllowFiltering="true"
                                                TItem="ClientSelectDto"
                                                @bind-Value="Search.Client"
                                                PopupHeight="230px"
                                                Placeholder="Select Client"
                                                DataSource="@ClientList"
                                                ID="ddlClients">
                                        <DropDownListEvents TValue="int" TItem="ClientSelectDto" ValueChange="ChangeSite"></DropDownListEvents>
                                        <DropDownListFieldSettings Text="Name" Value="Id" />
                                    </SfDropDownList>
                                </div>
                                <label for="clientsites" class="col-sm-2 col-form-label">Client Site</label>
                                <div class="col-sm-3">
                                    <SfDropDownList Enabled="@EnableSiteDropdown"
                                                TValue="int"
                                                ShowClearButton="true"
                                                AllowFiltering="true"
                                                TItem="ClientSiteSelectDto"
                                                @bind-Value="Search.ClientSite"
                                                PopupHeight="230px"
                                                Placeholder="Select Client Site"
                                                DataSource="@ClientSites"
                                                ID="ddlClientsSites">
                                        <DropDownListTemplates TItem="ClientSiteSelectDto">
                                            <NoRecordsTemplate>
                                                <span class="norecord">Client does not have any sites</span>
                                            </NoRecordsTemplate>
                                        </DropDownListTemplates>
                                        <DropDownListFieldSettings Text="Name" Value="Id" />
                                    </SfDropDownList>
                                </div>
                            </div>




                            <div class="form-group row mt-3">
                                <div class="text-center">
                                    <SfButton CssClass="e-btn e-success" style="width: 200px;">Search</SfButton>
                                    <SfButton CssClass="e-btn e-primary" style="width: 200px;"
                                        type="button"
                                        @onclick="btnReviewClicked"
                                        Disabled="@(!AnySelected)">Review Selected Timesheets</SfButton>
                                </div>
                            </div>
                        </EditForm>
                    </div>
                    <div class="row mt-3">
                        <TimesheetGrid Timesheets="@TimesheetRecords"
                                   SelectedItemsEvent="@SelectedItems" />
                    </div>
                } else {
                    <div class="row">
                        <SelectedTimesheetGrid Timesheets="SelectedTimesheets" />
                   </div>
                }
            </div>
        </div>
    </div>
</div>




<Spinner IsProcessing="@IsProcessing"
         Size="50"
         SpinType="@SpinnerType.Fabric"
         Message="Obtaining Timesheets, Please Wait...">
</Spinner>




@code {
    [Parameter] public int ClientId { get; set; } = 0;
    [Parameter] public int SiteId { get; set; } = 0;
    private DateTime MinDate { get; set; } = DateTime.Now;
    private EditContext editContext;
    private TimesheetFiltersDto Search { get; set; } = new TimesheetFiltersDto();
    private List<ClientSelectDto> ClientList { get; set; }
    private List<ClientSiteSelectDto> ClientSites { get; set; }
    private List<ApplicantsWeekTimesheetDto> TimesheetRecords { get; set; }
    private List<TimesheetGroupModelDto> SelectedTimesheets { get; set; }
    private bool IsProcessing { get; set; } = false;
    private bool EnableSiteDropdown = false, AnySelected = false;
    private string displayStep2 = "visibility:hidden;";
    private List<ApplicantsWeekTimesheetDto> SelectedRecords { get; set; }
    public bool ShowStep1 { get; set; } = true;


    private async Task SetFilters() {
        TimesheetRecords = null;
        await GetTimesheetRecords();
    }
    private void ShowErrors() { }


    protected override async Task OnInitializedAsync() {
        SelectedTimesheets = new List<TimesheetGroupModelDto>();
        Search = new TimesheetFiltersDto();
        if (ClientId > 0) {
            Search.Client = ClientId;
            EnableSiteDropdown = true;
        }
        if (SiteId > 0) {
            Search.ClientSite = SiteId;
        }
        editContext = new EditContext(Search);
        await GetClientList();
    }


    public void SelectedItems(List<ApplicantsWeekTimesheetDto> items) {
        SelectedRecords = items;
        if (items.Count() > 0) {
            displayStep2 = "visibility:visible;";
            AnySelected = true;
        } else {
            displayStep2 = "visibility:hidden;";
            AnySelected = false;
            SelectedTimesheets = new List<TimesheetGroupModelDto>();
        }
    }


    private async Task ChangeSite(Syncfusion.Blazor.DropDowns.ChangeEventArgs<int, ClientSelectDto> args) {
        await GetClientSites(args.Value);
        EnableSiteDropdown = true;
    }


    private async Task GetClientList() {
        try {
            var apiResponse = await httpClient.GetFromJsonAsync<ApiResponseDto<List<ClientSelectDto>>>(BaseURLs.GetClients);
            if (apiResponse.IsSuccessStatusCode) {
                ClientList = apiResponse.Result;
                if (ClientId > 0) {
                    await GetClientSites(ClientId);
                }
            } else {
                await swal.FireAsync("Info", apiResponse.Message, SweetAlertIcon.Info);
            }
        } catch (Exception ex) {
            await swal.FireAsync("Error", ex.Message, SweetAlertIcon.Error);
        }
    }


    private async Task GetClientSites(int clientId) {
        try {
            var apiResponse = await httpClient.GetFromJsonAsync<ApiResponseDto<List<ClientSiteSelectDto>>>($"{BaseURLs.GetClientSites}/{clientId}");
            if (apiResponse.IsSuccessStatusCode) {
                ClientSites = apiResponse.Result;
            } else {
                if (clientId == 0) {
                    ClientSites = new List<ClientSiteSelectDto>();
                    Search.ClientSite = 0;
                    EnableSiteDropdown = false;
                } else {
                    await swal.FireAsync("Info", apiResponse.Message, SweetAlertIcon.Info);
                }
            }
        } catch (Exception ex) {
            await swal.FireAsync("Error", ex.Message, SweetAlertIcon.Error);
        }
    }


    private async Task GetTimesheetRecords() {
        IsProcessing = true;
        try {
            var apiResponse = await httpClient.PostJsonAsync<ApiResponseDto<List<ApplicantsWeekTimesheetDto>>>(BaseURLs.GetTimesheets, Search);
            if (apiResponse.IsSuccessStatusCode) {
                TimesheetRecords = apiResponse.Result;
            }


        } catch (Exception ex) {
            await swal.FireAsync("Error", ex.Message, SweetAlertIcon.Error);
        } finally {
            IsProcessing = false;
        }
    }


    private void btnReviewClicked() {
        SelectedTimesheets = ts.GetGroupedTimesheets(SelectedRecords);
        ShowStep1 = false;
    }


    private void BackToStep1() {
        var lookup = TimesheetRecords.ToLookup(x => new { x.Id });
        foreach(var s in SelectedRecords) {
            foreach(var t in lookup[new {s.Id}]) {
                t.IsSelected = s.IsSelected;
            }
        }


        SelectedItems(SelectedRecords);
        ShowStep1 = true;
    }
}

// This is the TimesheetGrid (Component)
@inject HttpClient httpClient
@inject SweetAlertService swal


<SfGrid @ref="TGrid" DataSource="@Timesheets"
        EnablePersistence="true"
        ID="grdTimesheets"
        AllowPaging="true"
        AllowSorting="true"
        Toolbar="ToolbarItems">
    <GridAggregates>
        <GridAggregate>
            <GridAggregateColumns>
                <GridAggregateColumn Field="GetTotalHours" Type="AggregateType.Custom">
                    <FooterTemplate>
                        @{
                            var tHours = @GetSelectedRecords("H").Result;
                            <div>
                                <p>@tHours</p>
                            </div>
                        }
                    </FooterTemplate>
                </GridAggregateColumn>
                <GridAggregateColumn Field="BuyRateCost" Type="AggregateType.Custom">
                    <FooterTemplate>
                        @{
                            var bCost = @GetSelectedRecords("B").Result;
                            <div>
                                <p>£@bCost</p>
                            </div>
                        }
                    </FooterTemplate>
                </GridAggregateColumn>
                <GridAggregateColumn Field="SaleRateCost" Type="AggregateType.Custom">
                    <FooterTemplate>
                        @{
                            var sCost = @GetSelectedRecords("S").Result;
                            <div>
                                <p>£@sCost</p>
                            </div>
                        }
                    </FooterTemplate>
                </GridAggregateColumn>
            </GridAggregateColumns>
        </GridAggregate>
    </GridAggregates>
    <GridSelectionSettings CheckboxOnly="true" PersistSelection="true" />
    <GridPageSettings PageSizes="@pageSizes" PageSize="15" />
    <GridEvents RowDataBound="OnRowBound"
                RowSelected="OnRowSelected"
                RowDeselected="OnRowDeselected"
                CommandClicked="OnGridCommandClicked"
                TValue="ApplicantsWeekTimesheetDto"></GridEvents>
    <GridColumns>
        <GridColumn Field="Id" Visible="false" IsPrimaryKey="true" />
        <GridColumn Field="ApplicantName" HeaderText="Applicant" />
        <GridColumn Field="GetClientAndSite" HeaderText="Client" />
        <GridColumn Field="RoleName" HeaderText="Role Name" Width="150" />
        <GridColumn Field="RateDesc" HeaderText="Pay Rate Name" Width="200" />
        <GridColumn Field="GetBuyRate" Format="N2" HeaderText="Pay Rate" TextAlign="TextAlign.Right" Width="100" />
        <GridColumn Field="GetSaleRate" Format="N2" HeaderText="Charge Rate" TextAlign="TextAlign.Right" Width="100" />
        <GridColumn Field="GetTotalHours" HeaderText="Total Hours" Format="N1" TextAlign="TextAlign.Right" Width="100" />
        <GridColumn Field="BuyRateCost" HeaderText="Buy Cost" Format="N2" TextAlign="TextAlign.Right" Width="100" />
        <GridColumn Field="SaleRateCost" HeaderText="Charge Cost" Format="N2" TextAlign="TextAlign.Right" Width="100" />
        <GridColumn Type="ColumnType.CheckBox" TextAlign="TextAlign.Right" Width="100"></GridColumn>


        <GridColumn HeaderText="Options">
            <GridCommandColumns>
                <GridCommandColumn Type="CommandButtonType.Delete" ButtonOption="@(new CommandButtonOptions() {IconCss="fa-solid fa-clock-rotate-left", CssClass="e-flat grid-delete-btn"})" Title="Reset Hours" ID="btnResetHours" />
                <GridCommandColumn Type="CommandButtonType.None" ButtonOption="@(new CommandButtonOptions() {IconCss="fa-regular fa-clock", CssClass="e-flat grid-add-btn"})" Title="Edit Hours" ID="edtHours" />
                <GridCommandColumn Type="CommandButtonType.Edit" ButtonOption="@(new CommandButtonOptions() {IconCss="fa-solid fa-rotate-left", CssClass="e-flat grid-delete-btn"})" Title="Reset Rates" ID="btnResetRates" />
                <GridCommandColumn Type="CommandButtonType.None" ButtonOption="@(new CommandButtonOptions() {IconCss="fa-solid fa-sterling-sign", CssClass="e-flat grid-edit-btn"})" Title="Edit Rates" ID="edtRate" />
            </GridCommandColumns>
        </GridColumn>
    </GridColumns>
</SfGrid>


<DialogComponent IsVisible="@bEditRateVisible"
                 Width="600px"
                 OnClose="CancelEditRateDialog"
                 ShowDialogButtons="false">
    <DialogHeader>
        @EditRateHeader
    </DialogHeader>
    <DialogContent>
        <EditPayRateForm RateOverride="@PayRate"
                         OnCancelSelected="CancelEditRateDialog"
                         OnValidSubmit="SaveEditRateDialog" />
    </DialogContent>
</DialogComponent>


<DialogComponent IsVisible="@bEditHoursVisible"
                 Width="750px"
                 OnClose="CancelHoursDialog"
                 ShowDialogButtons="false">
    <DialogHeader>
        @EditHoursDialogHeader
    </DialogHeader>
    <DialogContent>
        <EditBookingHours Booking="@Booking"
                          UpdateTimesheet="GetUpdatedTimesheet"
                          OnValidSubmit="SaveHoursDialog"
                          OnCancelSelected="CancelHoursDialog"/>
    </DialogContent>


</DialogComponent>


@code {
    [Parameter] public List<ApplicantsWeekTimesheetDto> Timesheets { get; set; }
    [Parameter] public int PageSize { get; set; } = 15;
    [Parameter] public EventCallback<List<ApplicantsWeekTimesheetDto>> SelectedItemsEvent { get; set; }


    SfGrid<ApplicantsWeekTimesheetDto> TGrid;
    private ApplicantsWeekTimesheetDto SelectedApplicant;
    private string EditRateHeader = string.Empty, EditHoursDialogHeader = string.Empty;


    private List<object> ToolbarItems;
    private readonly List<int> pageSizes = new List<int> { 5, 10, 15, 20, 25, 50 };
    private bool bEditRateVisible = false, bEditHoursVisible = false;
    private EditRateDto PayRate { get; set; }
    private EditHoursDto Booking { get; set; }
    private List<ApplicantsWeekTimesheetDto> SelectedRecords { get; set; } = new List<ApplicantsWeekTimesheetDto>();
    //private static List<double> GridState { get; set; }
    //private List<double> selectedNodes;


    protected override void OnInitialized() {
        ToolbarItems = new List<object>() { "Search" };
    }


    #region Grid Methods
    private async Task OnGridCommandClicked(CommandClickEventArgs<ApplicantsWeekTimesheetDto> args) {
        var button = args.CommandColumn.ID.ToString();
        var record = args.RowData;


        switch (button) {
            case "edtHours":
                await ShowEditHoursDialog(record);
                break;
            case "edtRate":
                ShowEditRateDialog(record);
                break;
            case "btnResetRates":
                await ResetOverrideRates(record);
                break;
            case "btnResetHours":
                await ResetOverrideHours(record);
                args.Cancel = true;
                break;
        }
    }
    private void OnRowSelected(RowSelectEventArgs<ApplicantsWeekTimesheetDto> args) {
        var items = TGrid.GetSelectedRecordsAsync().Result;
        items.ForEach(x => x.IsSelected = true);
        SelectedItemsEvent.InvokeAsync(items);
    }
    private void OnRowDeselected(RowDeselectEventArgs<ApplicantsWeekTimesheetDto> args) {
        var items = TGrid.GetSelectedRecordsAsync().Result;
        items.ForEach(x => x.IsSelected = false);
        SelectedItemsEvent.InvokeAsync(items);
    }


    //private async Task DataBoundHandler() {
    // List<double> GridData = GetGridState();
    // if(GridData != null) {
    // await TGrid.SelectRowsAsync(GridData.ToArray());


    // }
    //}


    //private async Task DestroyHandler() {
    // selectedNodes = await TGrid.GetSelectedRowIndexesAsync();
    // setGridState(selectedNodes);
    //}


    //private void setGridState(List<double> value) {
    // GridState = value;
    //}
    //private List<double> GetGridState() {
    // return GridState;


    //}


    private void OnRowBound(RowDataBoundEventArgs<ApplicantsWeekTimesheetDto> args) {
        // if no changes, do not show the Reset Button.
        if (!CheckForChanges(args.Data)) {
            args.Row.AddClass(new string[] { "e-removeEditcommand" });
        }
        if (!CheckForHourChanges(args.Data)) {
            args.Row.AddClass(new string[] { "e-removeDeletecommand" });
        }


        //if(args.Data.IsSelected) {
        // var dataSource = TGrid.DataSource;
        // var index = 0;
        // foreach(var data in dataSource) {
        // if(data.Id == args.Data.Id) {
        // SelectedNodeIndex.Add(index);
        // break;
        // }
        // index++;
        // }
        //}


    }
    private async Task<string> GetSelectedRecords(string which) {
        decimal total = 0;
        SelectedRecords = await TGrid.GetSelectedRecordsAsync();
        if (SelectedRecords.Count() > 0) {
            switch (which) {
                case "H":
                    total = SelectedRecords.Sum(a => a.TotalHoursOverride > 0 ? a.TotalHoursOverride : a.TotalHours);
                    break;
                case "B":
                    total = SelectedRecords.Sum(a => a.BuyRateCost);
                    break;
                case "S":
                    total = SelectedRecords.Sum(a => a.SaleRateCost);
                    break;
            }
        }
        return total.ToString("N2");
    }
    #endregion


    #region Dialog Methods
    private void CancelEditRateDialog() {
        bEditRateVisible = false;
    }
    private void CancelHoursDialog() {
        bEditHoursVisible = false;
    }
    private async Task SaveEditRateDialog() {
        if (PayRate.HasChanged) {
            await UpdateRatesAndRefresh();
        }
        bEditRateVisible = false;
    }
    private async Task SaveHoursDialog(List<EditBookingDto> records) {
        if(records != null && records.Any()) {
            await UpdateHours(records);
        }
        bEditHoursVisible = false;
    }
    private async Task ShowEditHoursDialog(ApplicantsWeekTimesheetDto record) {
        EditHoursDialogHeader = $"Editing Hours for {record.ApplicantName}";
        Booking = await SetHourModel(record);
        SelectedApplicant = record;
        bEditHoursVisible = true;
    }
    private void ShowEditRateDialog(ApplicantsWeekTimesheetDto record) {
        EditRateHeader = $"Editing Rates for {record.ApplicantName}";
        PayRate = SetRateModel(record);
        SelectedApplicant = record;
        bEditRateVisible = true;
    }
    #endregion


    private async Task UpdateHours(List<EditBookingDto> records) {
        try {
            var bError = false;
            foreach (var booking in records) {
                var apiResponse = await httpClient.PutJsonAsync<ApiResponseDto<EditBookingDto>>(BaseURLs.UpdateBooking, booking);
                if (apiResponse.IsSuccessStatusCode) continue;
                await swal.FireAsync("Info", apiResponse.Message, SweetAlertIcon.Info);
                bError = true;
                break; // Break the ForEach on error.
            }
            if (!bError) {
                await GetUpdatedTimesheet();
            }
        } catch (Exception ex) {
            await swal.FireAsync("Error", ex.Message, SweetAlertIcon.Error);
        }
    }
    private async Task GetUpdatedTimesheet(bool bShowToast = true) {
        // At this point all the Updates have been done, so Lets get the updated Timesheet Record.
        var apiResponse = await httpClient.GetFromJsonAsync<ApiResponseDto<ApplicantsWeekTimesheetDto>>($"{BaseURLs.GetUpdatedTimesheet}/{SelectedApplicant.Id}");
        if (apiResponse.IsSuccessStatusCode) {
            var record = apiResponse.Result;
            await TGrid.SetRowDataAsync(record.Id, record);
            if(bShowToast) {
                await swal.FireAsync(new SweetAlertOptions {
                        Title = "Hours Updated",
                        Text = "Hours have been updated",
                        Icon = SweetAlertIcon.Success,
                        TimerProgressBar = true,
                        Timer = 2000
                    });
            }
        } else {
            await swal.FireAsync("Info", apiResponse.Message, SweetAlertIcon.Info);
        }
    }
    private async Task UpdateRatesAndRefresh() {
        try {
            var apiResponse = await httpClient.PutJsonAsync<ApiResponseDto<ApplicantsWeekTimesheetDto>>(BaseURLs.UpdateRates, PayRate);
            if (apiResponse.IsSuccessStatusCode) {
                var record = apiResponse.Result;
                await TGrid.SetRowDataAsync(record.Id, record);
                await swal.FireAsync(new SweetAlertOptions {
                        Title = "Rates Updated",
                        Text = "Rates have been updated",
                        Icon = SweetAlertIcon.Success,
                        TimerProgressBar = true,
                        Timer = 2000
                    });
            } else {
                await swal.FireAsync("Info", apiResponse.Message, SweetAlertIcon.Info);
            }
        } catch (Exception ex) {
            await swal.FireAsync("Error", ex.Message, SweetAlertIcon.Error);
        }
    }
    private async Task ResetOverrideRates(ApplicantsWeekTimesheetDto record) {
        if (CheckForChanges(record)) {
            var options = new SweetAlertOptions {
                    Title = "Reset Rates",
                    Text = "Are you sure you want to reset the rates back to original values?",
                    Icon = SweetAlertIcon.Question,
                    ConfirmButtonText = "Yes",
                    ShowConfirmButton = true,
                    ShowCancelButton = true,
                    CancelButtonText = "No",
                    FocusCancel = true,
                    ConfirmButtonColor = "red"
                };
            var result = await swal.FireAsync(options);
            if (result.IsConfirmed) {
                await UpdateRecord(record.Id, "rates");
            }
        }
    }
    private async Task ResetOverrideHours(ApplicantsWeekTimesheetDto record) {
        if (CheckForHourChanges(record)) {
            var options = new SweetAlertOptions {
                    Title = "Reset Hours",
                    Text = "Are you sure you want to reset the hours back to original values?",
                    Icon = SweetAlertIcon.Question,
                    ConfirmButtonText = "Yes",
                    ShowConfirmButton = true,
                    ShowCancelButton = true,
                    CancelButtonText = "No",
                    FocusCancel = true,
                    ConfirmButtonColor = "red"
                };
            var result = await swal.FireAsync(options);
            if (result.IsConfirmed) {
                await UpdateRecord(record.Id, "hours");
            }
        }
    }
    private async Task UpdateRecord(int id, string which) {
        try {
            if (which.ToLower() == "rates")
            {
                var apiResponse = await httpClient.GetFromJsonAsync<ApiResponseDto<ApplicantsWeekTimesheetDto>>($"{BaseURLs.ResetOverrideRates}/{id}");
                if (apiResponse.IsSuccessStatusCode)
                {
                    var record = apiResponse.Result;
                    await TGrid.SetRowDataAsync(id, record);


                    await swal.FireAsync(new SweetAlertOptions
                        {
                            Title = "Rates Updated",
                            Text = "Rates have been Reset",
                            Icon = SweetAlertIcon.Success,
                            TimerProgressBar = true,
                            Timer = 2000
                        });
                }
            } else if(which.ToLower() == "hours") {
                var apiResponse = await httpClient.GetFromJsonAsync<ApiResponseDto<ApplicantsWeekTimesheetDto>>($"{BaseURLs.ResetOverrideHours}/{id}");
                if (apiResponse.IsSuccessStatusCode) {
                    var record = apiResponse.Result;
                    await TGrid.SetRowDataAsync(id, record);


                    await swal.FireAsync(new SweetAlertOptions {
                            Title = "Hours Updated",
                            Text = "Hours have been Reset",
                            Icon = SweetAlertIcon.Success,
                            TimerProgressBar = true,
                            Timer = 2000
                        });
                }
            }
        } catch (Exception ex) {
            await swal.FireAsync("Error", ex.Message, SweetAlertIcon.Error);
        }
    }
    private EditRateDto SetRateModel(ApplicantsWeekTimesheetDto record) {
        return new EditRateDto {
                Id = record.Id,
                BuyRate = record.BuyRateOverride == 0 ? record.BuyRate : record.BuyRateOverride,
                ChargeRate = record.SaleRateOverride == 0 ? record.SaleRate : record.SaleRateOverride,
                RateType = (int)record.RateTypeOverride == (int)ERateType.None ? (int)record.RateType : (int)record.RateTypeOverride,
                OriginalValues = new OriginalValues {
                    BuyRate = record.BuyRate,
                    ChargeRate = record.SaleRate,
                    RateType = (int)record.RateType
                }
            };
    }
    private async Task<EditHoursDto> SetHourModel(ApplicantsWeekTimesheetDto record) {
        var retVal = new EditHoursDto();
        var criteria = new GetBookingsDto {
                ApplicantId = record.ApplicantId,
                PayRateId = record.PayRateId,
                BuyCost = record.BuyRateOverride == 0 ? record.BuyRate : record.BuyRateOverride,
                SellCost = record.SaleRateOverride == 0 ? record.SaleRate : record.SaleRateOverride,
                Hours = record.GetTotalHours
            };


        try {
            var apiResponse = await httpClient.PostJsonAsync<ApiResponseDto<List<EditBookingDto>>>(BaseURLs.GetBookings, criteria);
            if (apiResponse.IsSuccessStatusCode) {
                var bookings = apiResponse.Result;
                retVal = new EditHoursDto {
                        Id = record.Id,
                        Applicant = record.ApplicantName,
                        Client = record.GetClientAndSite,
                        BuyRate = record.BuyRateOverride == 0 ? record.BuyRate : record.BuyRateOverride,
                        SaleRate = record.SaleRateOverride == 0 ? record.SaleRate : record.SaleRateOverride,
                        PayRateName = record.RateDesc,
                        Bookings = bookings
                    };
            } else {
                await swal.FireAsync("Info", apiResponse.Message, SweetAlertIcon.Info);
            }
        } catch (Exception ex) {
            await swal.FireAsync("Error", ex.Message, SweetAlertIcon.Error);
        }


        return retVal;
    }


    #region Functions
    private bool CheckForChanges(ApplicantsWeekTimesheetDto args) {
        if (args.BuyRateOverride > 0 || args.SaleRateOverride > 0 || args.RateTypeOverride != ERateType.None) {
            return true;
        }
        return false;
    }
    private bool CheckForHourChanges(ApplicantsWeekTimesheetDto args) {
        return (args.TotalHoursOverride > 0);
    }
    #endregion




}
<style>
    /*to remove the edit button alone*/
    .e-removeEditcommand .e-unboundcell .e-unboundcelldiv button.e-Editbutton {
        display: none;
    }


    /*to remove the delete button alone*/
    .e-removeDeletecommand .e-unboundcell .e-unboundcelldiv button.e-Deletebutton {
        display: none;
    }
</style>


SP Sarveswaran Palani Syncfusion Team October 11, 2022 10:57 PM

Hi Simon,


Thanks for contacting Syncfusion support.


We have analyzed your query and facing some complexities while evaluating the query. Before proceeding further kindly share the simple runnable sample and video demo of an issue. It’ll be more helpful for us to validate the query and provide the solution as early as possible.


Please get back to if you have any further queries.


Regards,

Sarveswaran PK




SA Simon Arnold October 12, 2022 02:20 AM

As from the the video, you can see I select a few records from the 1st page and then click the review, the next grid just shows the selected records from the 1st, but when you go back to the 1st grid, the records do not get re-selected.

You have a primary key field in the data for the grid, so why can you not have a select function that allows you to SelectRowByKey(key), this could then select the checkbox if using that method.


When I come back to the 1st grid, my SelectedRecords List still has the original records selected, but I cannot find a way to check the checkbox column, or even a way to get the index from the record, as it seems the index is always 0-(PageSize), which is no good when you have paging enabled.



Attachment: ATSPursuitImport__Google_Chrome_20221012_081043_a321aa9f.zip


SP Sarveswaran Palani Syncfusion Team October 13, 2022 12:50 PM

Hi Simon,

Thanks for an contacting Syncfusion support.


We have analyzed your query and would like to inform you that, we didn’t have support for selecting records based on the primarykey values. We suggest you to use GetRowIndexByPrimaryKey method to find the index value based on the you may select a record. Kindly refer the attached link for your reference.


Kindly get back to us if you have any further queries.


Regards,

Sarveswaran PK



SA Simon Arnold October 14, 2022 03:22 AM

I have now tried the GetRowIndexByPrimaryKey, but this does the same when using paging, if you select the first 5 records on the 1st page then select page 6, it reselects the first 5 records on page 6, due to it using only the index, which always starts at 0 when using paging, these functions do not work with paging, I will have to find an alternative way to try and keep the selection when moving back and forth.


Thanks



SP Sarveswaran Palani Syncfusion Team October 17, 2022 10:31 PM

Hi Simon,


Thanks for an update.


We have analyzed your query and suspect that you want to persist the selected records while navigating one page to another. We suggest you to use PersistSelection property of GridSelectionSettings to overcome the reported issue at you end. Kindly refer the attached documentation link for your reference.

Reference: https://blazor.syncfusion.com/documentation/datagrid/selection#checkbox-selection

Kindly get back to us if you have any further queries.


Regards,

Sarveswaran PK



SA Simon Arnold October 18, 2022 02:04 AM

From your reply, I noticed you have not even looked at the code I posted, because if you have you will have noticed that I have this setting set to true.




SP Sarveswaran Palani Syncfusion Team October 19, 2022 09:09 PM

Hi Simon,


Sorry for an inconvenience caused.


We have analyzed your query and reprepare a sample based on your requirement. We’ll update the further details within two business days.


Until then we appreciate your patience.


Regards,

Sarveswaran PK



SP Sarveswaran Palani Syncfusion Team November 3, 2022 12:26 PM

Hi Simon,

Sorry for the delay.

Based on your requirement, We created a sample based on your requirement using GetRowIndexByPrimaryKey method to overcome the reported issue. Kindly refer the attached sample for your reference.

Regards,

Sarvesh


Attachment: SfGridPagerModified_f1dcad3d.zip


SA Simon Arnold November 4, 2022 03:49 AM

Thanks, but this is still not acceptable, due to the fact I need to select records, then press hide & show before changing the page to select some more, and so on, plus when you have around 20+ pages this gets very slow.





SP Sarveswaran Palani Syncfusion Team November 17, 2022 12:22 AM

Hi Simon,

Sorry for the delay.

We have checked your query with loading 20+ pages in the provided sample. But we’re unable to found performance issue in the sample. And also, we used async method to improve performance. Kindly check the shared sample for your reference.

Regards,
Sarveswaran PK


Loader.
Live Chat Icon For mobile
Up arrow icon