Custom Button for Adding Rows in TreeGrid

Hello,

When using TreeGrid, I want to use a custom button to add rows. My specific requirement is as follows:
Image_7425_1736408057926

Requirement:

  • Clicking the "Add" button for a node should create a new child row under that node. For example, clicking the "Add" button on the "root" node should create a new child node at the same level as "result." Similarly, the functionality should work for all hierarchical levels.

What I Have Tried:
 - I attempted to use the Command Editing feature (link to documentation), but it does not provide an "Add" option.

Expected Result:

- A customizable "Add" button for each row that allows dynamically adding a child row under the corresponding node.

Question:

Is there a way to customize the "Add Row" button to achieve this functionality? (This could involve customizing the existing command or using any other approach that works best for this scenario)

My Code (Please Use This Code for Updates):

@using Syncfusion.Blazor.Grids
@using Syncfusion.Blazor.TreeGrid

<SfTreeGrid @ref="TreeGrid" IdMapping="TaskId" ParentIdMapping="ParentId"
DataSource="@TreeData" TreeColumnIndex="1"
AutoCheckHierarchy="true">
<TreeGridEvents CommandClicked="OnCommandClicked" TValue="BusinessObject"></TreeGridEvents>
<TreeGridEditSettings AllowAdding="true" AllowEditing="true" AllowDeleting="true" Mode="Syncfusion.Blazor.TreeGrid.EditMode.Row"></TreeGridEditSettings>
<TreeGridColumns>
<TreeGridColumn Field="TaskId" HeaderText="Task ID" Width="80" TextAlign="Syncfusion.Blazor.Grids.TextAlign.Right"></TreeGridColumn>
<TreeGridColumn Field="TaskName" HeaderText="Task Name" Width="90"></TreeGridColumn>
<TreeGridColumn HeaderText="Manage Records" Width="180">
<TreeGridCommandColumns>
<TreeGridCommandColumn ButtonOption="@(new CommandButtonOptions() { Content = "Add", CssClass = "e-flat" })"></TreeGridCommandColumn>
<TreeGridCommandColumn Type="CommandButtonType.Edit" ButtonOption="@(new CommandButtonOptions() { IconCss = "e-icons e-edit", CssClass = "e-flat" })"></TreeGridCommandColumn>
<TreeGridCommandColumn Type="CommandButtonType.Delete" ButtonOption="@(new CommandButtonOptions() { IconCss = "e-icons e-delete", CssClass = "e-flat" })"></TreeGridCommandColumn>
<TreeGridCommandColumn Type="CommandButtonType.Save" ButtonOption="@(new CommandButtonOptions() { IconCss = "e-icons e-save", CssClass = "e-flat" })"></TreeGridCommandColumn>
<TreeGridCommandColumn Type="CommandButtonType.Cancel" ButtonOption="@(new CommandButtonOptions() { IconCss = "e-icons e-cancel-icon", CssClass = "e-flat" })"></TreeGridCommandColumn>
</TreeGridCommandColumns>
</TreeGridColumn>
</TreeGridColumns>
</SfTreeGrid>

@code{
public class BusinessObject
{
public int TaskId { get; set; }
public string TaskName { get; set; }
public DateOnly? StartDate { get; set; }
public TimeOnly? StartTime { get; set; }
public int Duration { get; set; }
public int Progress { get; set; }
public string Priority { get; set; }
public int? ParentId { get; set; }
}

public List<BusinessObject> TreeData = new List<BusinessObject>();

SfTreeGrid<BusinessObject> TreeGrid;

protected override void OnInitialized()
{
TreeData.Add(new BusinessObject() { TaskId = 1, TaskName = "Parent Task 1", StartDate = new DateOnly(2021, 03, 02), StartTime = new TimeOnly(10, 00, 00), Duration = 10, Progress = 70, ParentId = null, Priority = "High" });
TreeData.Add(new BusinessObject() { TaskId = 2, TaskName = "Child task 1", StartDate = new DateOnly(2021, 03, 04), StartTime = new TimeOnly(11, 30, 00), Duration = 4, Progress = 80, ParentId = 1, Priority = "Normal" });
TreeData.Add(new BusinessObject() { TaskId = 3, TaskName = "Child Task 2", StartDate = new DateOnly(2021, 03, 06), StartTime = new TimeOnly(12, 00, 00), Duration = 5, Progress = 65, ParentId = 1, Priority = "Critical" });
TreeData.Add(new BusinessObject() { TaskId = 4, TaskName = "Parent Task 2", StartDate = new DateOnly(2021, 03, 08), StartTime = new TimeOnly(13, 30, 00), Duration = 6, Progress = 77, ParentId = null, Priority = "Low" });
TreeData.Add(new BusinessObject() { TaskId = 5, TaskName = "Child Task 5", StartDate = new DateOnly(2021, 07, 10), StartTime = new TimeOnly(14, 00, 00), Duration = 9, Progress = 25, ParentId = 4, Priority = "Normal" });
TreeData.Add(new BusinessObject() { TaskId = 6, TaskName = "Child Task 6", StartDate = new DateOnly(2021, 10, 12), StartTime = new TimeOnly(16, 00, 00), Duration = 9, Progress = 7, ParentId = 5, Priority = "Normal" });
TreeData.Add(new BusinessObject() { TaskId = 7, TaskName = "Parent Task 3", StartDate = new DateOnly(2021, 10, 14), StartTime = new TimeOnly(17, 30, 00), Duration = 4, Progress = 45, ParentId = null, Priority = "High" });
TreeData.Add(new BusinessObject() { TaskId = 8, TaskName = "Child Task 7", StartDate = new DateOnly(2021, 10, 16), StartTime = new TimeOnly(18, 00, 00), Duration = 3, Progress = 38, ParentId = 7, Priority = "Critical" });
TreeData.Add(new BusinessObject() { TaskId = 9, TaskName = "Child Task 8", StartDate = new DateOnly(2021, 02, 18), StartTime = new TimeOnly(19, 30, 00), Duration = 7, Progress = 70, ParentId = 7, Priority = "Low" });
} }

7 Replies

SM Shek Mohammed Asiq Abdul Jabbar Syncfusion Team January 13, 2025 10:03 AM UTC

Hi Tien Pham,


Greetings from Syncfusion support.


Based on your query, we have rendered an "Add" icon using a button component in the TreeGrid's column template. When the icon is clicked, the AddTopic method is triggered, which dynamically adds a new child row under the selected parent node.


<TreeGridColumns>

    . . . . . 

    <TreeGridColumn Field="" HeaderText="" Width="50" TextAlign="Syncfusion.Blazor.Grids.TextAlign.Right">

        <Template>

            @{

                var data = context as BusinessObject;

                <span @onclick:stopPropagation="true">

                    <SfButton @onclick="() => AddTopic(data)" CssClass="e-flat" IconCss="e-icons e-circle-add"></SfButton>

                </span>

            }

        </Template>

    </TreeGridColumn>

</TreeGridColumns>

 

@code {

    public async Task AddTopic(BusinessObject args)

    {

        // Retrieve the index of the clicked row in the current view records

        var indexVal = this.TreeGrid.GetCurrentViewRecords().FindIndex(a => a.TaskId == args.TaskId);

 

        if (indexVal != -1)

        {

            await this.TreeGrid.SelectRowAsync(indexVal); // Select the clicked row

            await this.TreeGrid.AddRecordAsync(); // Add a row as a child to the selected row

        }

    }

}


Sample: https://blazorplayground.syncfusion.com/VjBIDWMUgMWehisv


If you have any queries on this, please contact us.


Regards,

Shek



TP Tien Pham January 14, 2025 01:25 PM UTC

Thank you for the support! I have successfully implemented the inline add functionality in the TreeGrid.

However, I have encountered a new issue while using the inline add feature.

Currently, as shown in the image below:

Image_5666_1736860461181

The Cancel button for the inline add row appears in a separate column, specifically in the column for TreeGridCommandColumns.

What I have tried:

To address this, I attempted to merge the column containing the Add button with the column that holds the TreeGridCommandColumns (which includes buttons like Edit, Delete, Save, and Cancel).

My goal is to have:

  • A single action column that contains all buttons, including Add, Edit, Delete, Save, and Cancel.
  • The Cancel button for the inline add row placed in the same cell as the Add button, within the same unified column.

As shown in the following image (Expected):

Image_5705_1736860662982

Could you provide guidance on how to customize the action column to meet this requirement?

Thank you for your assistance!

Best regards,



TP Tien Pham January 15, 2025 11:08 AM UTC

I have an additional question regarding editing functionality. I would like to enable single-click editing in EditMode.Row.

While going through the documentation, I found a similar example that allows single-click editing in EditMode.Batch, but I couldn’t find a way to customize it for EditMode.Row.



SM Shek Mohammed Asiq Abdul Jabbar Syncfusion Team January 16, 2025 01:34 PM UTC

Hi Tien Pham,


Based on your requirement, we have removed the column template and customized the same logic in the command column. Please refer to the following code snippet:


<SfTreeGrid . . . . . >

    . . . . .

    <TreeGridColumns>

        . . . . .

        <TreeGridColumn HeaderText="Manage Records" Width="60">

            <TreeGridCommandColumns>

                <TreeGridCommandColumn Type="CommandButtonType.None" Title="Add" ButtonOption="@(new CommandButtonOptions() { IconCss = "e-icons e-circle-add", CssClass = "e-flat" })"></TreeGridCommandColumn>

                . . . . .

            </TreeGridCommandColumns>

        </TreeGridColumn>

    </TreeGridColumns>

    <TreeGridEvents RecordClicked="RecordClick" CommandClicked="CmdClick" TValue="BusinessObject"></TreeGridEvents>

</SfTreeGrid>

 

 

@code {

    . . . .

    public async Task CmdClick(CommandClickEventArgs<BusinessObject> args)

    {

        if (args.CommandColumn.Title == "Add")

        {

            var indexVal = this.TreeGrid.GetCurrentViewRecords().FindIndex(a => a.TaskId == args.RowData.TaskId);

            if (indexVal != -1)

            {

                await this.TreeGrid.SelectRowAsync(indexVal); // select the clicked row

                await this.TreeGrid.AddRecordAsync(); // add row to the selected row as child

            }

        }

    }

    . . . . . . .

}

 


Removing the Add Icon During Add/Edit

By default, the add icon is displayed while adding and editing a row. To remove it, use the following CSS styles:


<style>

    tr.e-addedrow span.e-circle-add {

    display: none !important;

    }

 

    tr.e-editedrow span.e-circle-add {

    display: none !important;

    }

</style>

 


Single-Click Editing on Row Click

To enable single-click editing when a row is clicked, we use the RecordClicked event in the TreeGrid. Based on the row index obtained from the event, we select the row using the SelectRowAsync method and start editing with the StartEditAsync method.


<SfTreeGrid . . . . . >

     . . . . .

    <TreeGridEvents RecordClicked="RecordClick" CommandClicked="CmdClick" TValue="BusinessObject"></TreeGridEvents>

</SfTreeGrid>

 

@code {

    . . . . . .

    private int? CurrentRowIndex { get; set; } = null;

    public async Task RecordClick(Syncfusion.Blazor.TreeGrid.RecordClickEventArgs<BusinessObject> args)

    {

        if (CurrentRowIndex != args.RowIndex)

        {

            // End editing for the previously edited row

            await TreeGrid.EndEditAsync();

        }

        // Update the currently selected row index

        CurrentRowIndex = args.RowIndex;

        await TreeGrid.SelectRowAsync(args.RowIndex);

        // Start editing the clicked row

        await TreeGrid.StartEditAsync();

    }

    . . . . .

}

 

 


Sample: https://blazorplayground.syncfusion.com/htVSDiiRAQPoTfmK


Let us know if you need further assistance.


Regards,
Shek



TP Tien Pham January 16, 2025 02:27 PM UTC

Thank you for your support so far!

I have another question regarding the editing functionality. Currently, double-clicking a row triggers inline editing. However, I want to prevent the double-click event from entering edit mode.I want the editing to only be triggered when clicking the button with CommandButtonType.Edit in the TreeGridCommandColumns.



TP Tien Pham January 20, 2025 10:17 AM UTC

Adding another question to the above: I want to use logic to disable double click editing for some rows that satisfy certain conditions.



SM Shek Mohammed Asiq Abdul Jabbar Syncfusion Team January 20, 2025 02:37 PM UTC

Hi Tien Pham,


We can conditionally disable the editing on double click using OnRecordDoubleClick event and OnActionBegin event. Please refer to the following code snippet.

    <TreeGridEvents OnRecordDoubleClick="DblClick" OnActionBegin="RowEdit" CommandClicked="CmdClick" TValue="BusinessObject"></TreeGridEvents>

 

@code {

    . . . .

 

    public async Task CmdClick(CommandClickEventArgs<BusinessObject> args)

    {

        IsEdit = true;

        . . . .

    }

 

    public bool IsEdit = true;

 

    public void RowEdit(Syncfusion.Blazor.Grids.ActionEventArgs<BusinessObject> args)

    {

        if (args.RequestType == Syncfusion.Blazor.Grids.Action.BeginEdit && !IsEdit)

        {

            args.Cancel = true;

            IsEdit = false;

        }

    }

 

    public void DblClick(RecordDoubleClickEventArgs<BusinessObject> args)

    {

        if (args.RowData.TaskName == "Child Task 2")

        {

            IsEdit = false;

        }

        else

        {

            IsEdit = true;

        }

    }

}

 



To disable editing on double-click on initial rendering, you can use the AllowEditOnDblClick property in the TreeGrid edit settings. Please refer to the following code snippet:

    <TreeGridEditSettings AllowAdding="true" AllowEditing="true" AllowEditOnDblClick="false " AllowDeleting="true" NewRowPosition="Syncfusion.Blazor.TreeGrid.RowPosition.Child" Mode="Syncfusion.Blazor.TreeGrid.EditMode.Row"></TreeGridEditSettings>

 


Sample: https://blazorplayground.syncfusion.com/LZhoDshXoWNQUyiS


Looking forward to your response.


Regards,
Shek


Loader.
Up arrow icon