Blazor Tree Grid의 Ignite UI for Blazor 하면 IgbTreeGrid 내에서 직접 데이터를 편집할 수 있습니다. 데이터를 조작하는 이 편리한 방법 외에도 전체 CRUD 작업을 위한 강력한 API가 있습니다. 행을 클릭하고 Enter 키를 눌러 그리드 행 편집을 수행할 수 있습니다. 또 다른 빠른 방법은 수정해야 하는 행을 마우스로 두 번 클릭하는 것입니다.
다음 샘플은 IgbTreeGrid에서 행 편집을 활성화하는 방법을 보여줍니다. 셀 값을 변경한 다음 동일한 행의 다른 셀을 클릭하거나 탐색하면 완료 버튼을 사용하여 확인하거나 취소 버튼을 사용하여 삭제될 때까지 행 값이 업데이트되지 않습니다.
EXAMPLE
DATA
MODULES
RAZOR
CSS
using System;
using System.Collections.Generic;
publicclassEmployeesNestedTreeDataItem
{
publicdouble Age { get; set; }
publicstring HireDate { get; set; }
publicdouble ID { get; set; }
publicstring Name { get; set; }
publicstring Phone { get; set; }
publicbool OnPTO { get; set; }
publicdouble ParentID { get; set; }
publicstring Title { get; set; }
}
publicclassEmployeesNestedTreeData
: List<EmployeesNestedTreeDataItem>
{
publicEmployeesNestedTreeData()
{
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 55,
HireDate = @"2008-03-20",
ID = 1,
Name = @"Johnathan Winchester",
Phone = @"0251-031259",
OnPTO = false,
ParentID = -1,
Title = @"Development Manager"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 42,
HireDate = @"2014-01-22",
ID = 4,
Name = @"Ana Sanders",
Phone = @"(21) 555-0091",
OnPTO = true,
ParentID = -1,
Title = @"CEO"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 49,
HireDate = @"2014-01-22",
ID = 18,
Name = @"Victoria Lincoln",
Phone = @"(071) 23 67 22 20",
OnPTO = true,
ParentID = -1,
Title = @"Accounting Manager"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 61,
HireDate = @"2010-01-01",
ID = 10,
Name = @"Yang Wang",
Phone = @"(21) 555-0091",
OnPTO = false,
ParentID = -1,
Title = @"Localization Manager"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 43,
HireDate = @"2011-06-03",
ID = 3,
Name = @"Michael Burke",
Phone = @"0452-076545",
OnPTO = true,
ParentID = 1,
Title = @"Senior Software Developer"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 29,
HireDate = @"2009-06-19",
ID = 2,
Name = @"Thomas Anderson",
Phone = @"(14) 555-8122",
OnPTO = false,
ParentID = 1,
Title = @"Senior Software Developer"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 31,
HireDate = @"2014-08-18",
ID = 11,
Name = @"Monica Reyes",
Phone = @"7675-3425",
OnPTO = false,
ParentID = 1,
Title = @"Software Development Team Lead"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 35,
HireDate = @"2015-09-17",
ID = 6,
Name = @"Roland Mendel",
Phone = @"(505) 555-5939",
OnPTO = false,
ParentID = 11,
Title = @"Senior Software Developer"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 44,
HireDate = @"2009-10-11",
ID = 12,
Name = @"Sven Cooper",
Phone = @"0695-34 67 21",
OnPTO = true,
ParentID = 11,
Title = @"Senior Software Developer"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 44,
HireDate = @"2014-04-04",
ID = 14,
Name = @"Laurence Johnson",
Phone = @"981-443655",
OnPTO = false,
ParentID = 4,
Title = @"Director"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 25,
HireDate = @"2017-11-09",
ID = 5,
Name = @"Elizabeth Richards",
Phone = @"(2) 283-2951",
OnPTO = true,
ParentID = 4,
Title = @"Vice President"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 39,
HireDate = @"2010-03-22",
ID = 13,
Name = @"Trevor Ashworth",
Phone = @"981-443655",
OnPTO = true,
ParentID = 5,
Title = @"Director"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 44,
HireDate = @"2014-04-04",
ID = 17,
Name = @"Antonio Moreno",
Phone = @"(505) 555-5939",
OnPTO = false,
ParentID = 18,
Title = @"Senior Accountant"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 50,
HireDate = @"2007-11-18",
ID = 7,
Name = @"Pedro Rodriguez",
Phone = @"035-640230",
OnPTO = false,
ParentID = 10,
Title = @"Senior Localization Developer"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 27,
HireDate = @"2016-02-19",
ID = 8,
Name = @"Casey Harper",
Phone = @"0342-023176",
OnPTO = true,
ParentID = 10,
Title = @"Senior Localization"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 25,
HireDate = @"2017-11-09",
ID = 15,
Name = @"Patricia Simpson",
Phone = @"069-0245984",
OnPTO = false,
ParentID = 7,
Title = @"Localization Intern"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 39,
HireDate = @"2010-03-22",
ID = 9,
Name = @"Francisco Chang",
Phone = @"(91) 745 6200",
OnPTO = false,
ParentID = 7,
Title = @"Localization Intern"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 25,
HireDate = @"2018-03-18",
ID = 16,
Name = @"Peter Lewis",
Phone = @"069-0245984",
OnPTO = true,
ParentID = 7,
Title = @"Localization Intern"
});
}
}cs
using System;
using System.Net.Http;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Text;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using IgniteUI.Blazor.Controls; // for registering Ignite UI modulesnamespaceInfragistics.Samples
{
publicclassProgram
{
publicstaticasync Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("app");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
// registering Ignite UI modules
builder.Services.AddIgniteUIBlazor(
typeof(IgbInputModule),
typeof(IgbTreeGridModule)
);
await builder.Build().RunAsync();
}
}
}cs
@using IgniteUI.Blazor.Controls<divclass="container vertical ig-typography"><divclass="container vertical fill"><IgbTreeGridAutoGenerate="false"Name="treeGrid"
@ref="treeGrid"Id="treeGrid"Data="EmployeesNestedTreeData"PrimaryKey="ID"ForeignKey="ParentID"Moving="true"RowEditable="true"RowSelection="GridSelectionMode.Multiple"><IgbColumnField="Name"Header="Full Name"DataType="GridColumnDataType.String"Resizable="true"Sortable="true"Filterable="true"Editable="true"></IgbColumn><IgbColumnField="Age"DataType="GridColumnDataType.Number"Resizable="false"Sortable="false"Filterable="false"Editable="true"></IgbColumn><IgbColumnField="Title"DataType="GridColumnDataType.String"Resizable="true"Sortable="true"Filterable="true"Editable="true"></IgbColumn><IgbColumnField="HireDate"Header="Hire Date"DataType="GridColumnDataType.Date"Resizable="true"Sortable="true"Filterable="true"Editable="true"></IgbColumn></IgbTreeGrid></div></div>@code {protectedoverrideasync Task OnAfterRenderAsync(bool firstRender)
{
var treeGrid = this.treeGrid;
}
private IgbTreeGrid treeGrid;
private EmployeesNestedTreeData _employeesNestedTreeData = null;
public EmployeesNestedTreeData EmployeesNestedTreeData
{
get
{
if (_employeesNestedTreeData == null)
{
_employeesNestedTreeData = new EmployeesNestedTreeData();
}
return _employeesNestedTreeData;
}
}
}razor
/*
CSS styles are loaded from the shared CSS file located at:
https://static.infragistics.com/xplatform/css/samples/
*/css
Like this sample? Get access to our complete Ignite UI for Blazor toolkit and start building your own apps in minutes. Download it for free.
When a row is in edit mode, clicking on a cell in another row will act like the "Done" button is pressed, submitting all changes made in the previous row. If the newly focused cell is editable, the new row enters edit mode as well. However, if the cell is not editable, only the previous row exits edit mode.
Setting primary key is mandatory for row editing operations.
Enabling editing for individual columns is not necessary. Using the RowEditable property in the IgbTreeGrid, all rows, with defined Field property (excluding the primary row) will be editable. If you want to disable editing for a specific column, simply set the Editable input of that column to false.
The IgbTreeGrid utilizes BaseTransactionService - an internal provider that holds pending cell changes until the row state is either submitted or cancelled.
Positioning
오버레이의 기본 위치는 편집 모드에 있는 행 아래에 있습니다.
행 아래에 공간이 없으면 행 위에 오버레이가 나타납니다.
상단 또는 하단에 표시된 오버레이는 오버레이가 닫힐 때까지 스크롤하는 동안 이 위치를 유지합니다.
Behavior
행이 편집 모드인 경우 동일한 행의 셀을 클릭하면 편집이 계속됩니다.
"완료" 버튼을 클릭하면 행 편집이 완료되고 데이터 소스 또는 가능한 경우 트랜잭션에 변경 사항이 제출됩니다. 또한 행은 편집 모드를 종료합니다.
"취소" 버튼을 클릭하면 행의 현재 변경 사항이 모두 되돌려지고 행은 편집 모드를 종료합니다.
행이 편집 모드인 경우 다른 행의 셀을 클릭하면 현재 행 편집이 완료되고 새 행 변경 사항이 제출됩니다("완료" 버튼을 클릭하는 것과 동일한 동작). 포커스를 받은 새 셀이 편집 가능하면 새 행도 편집 모드로 들어가고, 셀을 편집할 수 없으면 이전 행만 편집 모드에서 나갑니다.
행이 편집 모드에 있고 IgbTreeGrid 스크롤되어 행이 가시 영역 밖으로 나가면 후자는 여전히 편집 모드에 있습니다. IgbTreeGrid 스크롤되어 행이 다시 표시되면 행은 여전히 편집 모드에 있습니다. IgbTreeGrid 외부를 클릭하면 셀도 편집 모드로 유지됩니다.
정렬, 필터링, 검색 및 숨기기 작업을 수행하면 행의 모든 현재 변경 사항이 되돌려지고 행은 편집 모드를 종료합니다.
페이징, 크기 조정, 고정 및 이동 작업을 수행하면 편집 모드가 종료되고 최신 값이 제출됩니다.
수정된 각 셀은 행 편집이 완료될 때까지 편집된 스타일을 갖습니다. IgbTreeGrid에 트랜잭션이 제공되지 않을 때의 동작입니다. 트랜잭션을 사용할 수 있는 경우 모든 변경 사항이 커밋될 때까지 셀 편집 스타일이 적용됩니다.
Keyboard Navigation
Enter를 누르고 F2를 누르면 행 편집 모드로 들어갑니다.
Esc는 행 편집 모드를 종료하고 행이 편집 모드에 있는 동안 수행된 셀 변경 사항을 제출하지 않습니다.
Tab을 사용 하여 행의 편집 가능한 한 셀에서 다음 셀로, 가장 오른쪽의 편집 가능한 셀에서 CANCEL 및 DONE 버튼으로 초점을 이동합니다. 완료 버튼을 통한 탐색은 현재 편집된 행 내에서 편집 가능한 가장 왼쪽 셀로 이동합니다.
Feature Integration
모든 데이터 변경 작업은 행 편집 작업을 종료하고 현재 행 변경 사항을 제출합니다. 여기에는 정렬, 그룹화 및 필터링 기준 변경, 페이징 등과 같은 작업이 포함됩니다.
행 편집이 완료된 후 요약이 업데이트됩니다. 정렬, 필터링 등과 같은 다른 기능에도 동일하게 적용됩니다.
Customizing Row Editing Overlay
Customizing Text
템플릿을 사용하여 행 편집 오버레이의 텍스트를 사용자 정의할 수 있습니다.
RowChangesCount 속성이 노출되고 변경된 셀 수를 보유합니다.
igRegisterScript("RowEditTextTemplate", (ctx) => {
var html = window.igTemplating.html;
return html`<div>
Changes: ${ctx.implicit}
</div>`;
}, false);
razor
using System;
using System.Collections.Generic;
publicclassEmployeesNestedTreeDataItem
{
publicdouble Age { get; set; }
publicstring HireDate { get; set; }
publicdouble ID { get; set; }
publicstring Name { get; set; }
publicstring Phone { get; set; }
publicbool OnPTO { get; set; }
publicdouble ParentID { get; set; }
publicstring Title { get; set; }
}
publicclassEmployeesNestedTreeData
: List<EmployeesNestedTreeDataItem>
{
publicEmployeesNestedTreeData()
{
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 55,
HireDate = @"2008-03-20",
ID = 1,
Name = @"Johnathan Winchester",
Phone = @"0251-031259",
OnPTO = false,
ParentID = -1,
Title = @"Development Manager"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 42,
HireDate = @"2014-01-22",
ID = 4,
Name = @"Ana Sanders",
Phone = @"(21) 555-0091",
OnPTO = true,
ParentID = -1,
Title = @"CEO"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 49,
HireDate = @"2014-01-22",
ID = 18,
Name = @"Victoria Lincoln",
Phone = @"(071) 23 67 22 20",
OnPTO = true,
ParentID = -1,
Title = @"Accounting Manager"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 61,
HireDate = @"2010-01-01",
ID = 10,
Name = @"Yang Wang",
Phone = @"(21) 555-0091",
OnPTO = false,
ParentID = -1,
Title = @"Localization Manager"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 43,
HireDate = @"2011-06-03",
ID = 3,
Name = @"Michael Burke",
Phone = @"0452-076545",
OnPTO = true,
ParentID = 1,
Title = @"Senior Software Developer"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 29,
HireDate = @"2009-06-19",
ID = 2,
Name = @"Thomas Anderson",
Phone = @"(14) 555-8122",
OnPTO = false,
ParentID = 1,
Title = @"Senior Software Developer"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 31,
HireDate = @"2014-08-18",
ID = 11,
Name = @"Monica Reyes",
Phone = @"7675-3425",
OnPTO = false,
ParentID = 1,
Title = @"Software Development Team Lead"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 35,
HireDate = @"2015-09-17",
ID = 6,
Name = @"Roland Mendel",
Phone = @"(505) 555-5939",
OnPTO = false,
ParentID = 11,
Title = @"Senior Software Developer"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 44,
HireDate = @"2009-10-11",
ID = 12,
Name = @"Sven Cooper",
Phone = @"0695-34 67 21",
OnPTO = true,
ParentID = 11,
Title = @"Senior Software Developer"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 44,
HireDate = @"2014-04-04",
ID = 14,
Name = @"Laurence Johnson",
Phone = @"981-443655",
OnPTO = false,
ParentID = 4,
Title = @"Director"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 25,
HireDate = @"2017-11-09",
ID = 5,
Name = @"Elizabeth Richards",
Phone = @"(2) 283-2951",
OnPTO = true,
ParentID = 4,
Title = @"Vice President"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 39,
HireDate = @"2010-03-22",
ID = 13,
Name = @"Trevor Ashworth",
Phone = @"981-443655",
OnPTO = true,
ParentID = 5,
Title = @"Director"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 44,
HireDate = @"2014-04-04",
ID = 17,
Name = @"Antonio Moreno",
Phone = @"(505) 555-5939",
OnPTO = false,
ParentID = 18,
Title = @"Senior Accountant"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 50,
HireDate = @"2007-11-18",
ID = 7,
Name = @"Pedro Rodriguez",
Phone = @"035-640230",
OnPTO = false,
ParentID = 10,
Title = @"Senior Localization Developer"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 27,
HireDate = @"2016-02-19",
ID = 8,
Name = @"Casey Harper",
Phone = @"0342-023176",
OnPTO = true,
ParentID = 10,
Title = @"Senior Localization"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 25,
HireDate = @"2017-11-09",
ID = 15,
Name = @"Patricia Simpson",
Phone = @"069-0245984",
OnPTO = false,
ParentID = 7,
Title = @"Localization Intern"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 39,
HireDate = @"2010-03-22",
ID = 9,
Name = @"Francisco Chang",
Phone = @"(91) 745 6200",
OnPTO = false,
ParentID = 7,
Title = @"Localization Intern"
});
this.Add(new EmployeesNestedTreeDataItem()
{
Age = 25,
HireDate = @"2018-03-18",
ID = 16,
Name = @"Peter Lewis",
Phone = @"069-0245984",
OnPTO = true,
ParentID = 7,
Title = @"Localization Intern"
});
}
}cs
using System;
using System.Net.Http;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Text;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using IgniteUI.Blazor.Controls; // for registering Ignite UI modulesnamespaceInfragistics.Samples
{
publicclassProgram
{
publicstaticasync Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("app");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
// registering Ignite UI modules
builder.Services.AddIgniteUIBlazor(
typeof(IgbInputModule),
typeof(IgbTreeGridModule)
);
await builder.Build().RunAsync();
}
}
}cs
@using IgniteUI.Blazor.Controls<style>/*
CSS styles are loaded from the shared CSS file located at:
https://static.infragistics.com/xplatform/css/samples/
*/#grid {
--ig-banner-banner-background: #292826;
--ig-banner-banner-message-color: #ffcd0f;
--ig-button-foreground: #ffcd0f;
--ig-button-hover-foreground: white;
--ig-button-font-weight: 600;
}
</style><divclass="container vertical ig-typography"><divclass="container vertical fill"><IgbTreeGridAutoGenerate="false"Name="grid"
@ref="grid"Id="grid"Data="EmployeesNestedTreeData"PrimaryKey="ID"ForeignKey="ParentID"Moving="true"RowEditable="true"RowSelection="GridSelectionMode.Multiple"><IgbColumnField="Name"Header="Full Name"DataType="GridColumnDataType.String"Resizable="true"Sortable="true"Filterable="true"Editable="true"></IgbColumn><IgbColumnField="Age"DataType="GridColumnDataType.Number"Resizable="false"Sortable="false"Filterable="false"Editable="true"></IgbColumn><IgbColumnField="Title"DataType="GridColumnDataType.String"Resizable="true"Sortable="true"Filterable="true"Editable="true"></IgbColumn><IgbColumnField="HireDate"Header="Hire Date"DataType="GridColumnDataType.Date"Resizable="true"Sortable="true"Filterable="true"Editable="true"></IgbColumn></IgbTreeGrid></div></div>@code {protectedoverrideasync Task OnAfterRenderAsync(bool firstRender)
{
var grid = this.grid;
}
private IgbTreeGrid grid;
private EmployeesNestedTreeData _employeesNestedTreeData = null;
public EmployeesNestedTreeData EmployeesNestedTreeData
{
get
{
if (_employeesNestedTreeData == null)
{
_employeesNestedTreeData = new EmployeesNestedTreeData();
}
return _employeesNestedTreeData;
}
}
}razor
/*
CSS styles are loaded from the shared CSS file located at:
https://static.infragistics.com/xplatform/css/samples/
*/#grid {
--ig-banner-banner-background: #292826;
--ig-banner-banner-message-color: #ffcd0f;
--ig-button-foreground: #ffcd0f;
--ig-button-hover-foreground: white;
--ig-button-font-weight: 600;
}
css
Known Issues and Limitations
그리드에 PrimaryKey 설정되어 있지 않고 원격 데이터 시나리오가 활성화된 경우(그리드에 표시할 데이터를 검색하기 위해 원격 서버에 대한 페이징, 정렬, 필터링, 스크롤 트리거 요청 시) 행은 데이터 이후 다음 상태를 잃게 됩니다. 요청이 완료되었습니다: