React Tree Grid에서 행 드래그
React Tree Grid의 Ignite UI for React 쉽게 구성할 수 있으며, 마우스를 사용하여 새 위치로 드래그 앤 드롭하여 그리드 내에서 행을 재정렬하는 데 사용됩니다. 루트 IgrTreeGrid
구성 요소에서 초기화되며 rowDraggable
입력을 통해 구성할 수 있습니다.
React Tree Grid Row Drag 예제
export class EmployeesNestedTreeDataItem {
public constructor(init: Partial<EmployeesNestedTreeDataItem>) {
Object.assign(this, init);
}
public Age: number;
public HireDate: string;
public ID: number;
public Name: string;
public Phone: string;
public OnPTO: boolean;
public ParentID: number;
public Title: string;
}
export class EmployeesNestedTreeData extends Array<EmployeesNestedTreeDataItem> {
public constructor(items: Array<EmployeesNestedTreeDataItem> | number = -1) {
if (Array.isArray(items)) {
super(...items);
} else {
const newItems = [
new EmployeesNestedTreeDataItem(
{
Age: 55,
HireDate: `2008-03-20`,
ID: 1,
Name: `Johnathan Winchester`,
Phone: `0251-031259`,
OnPTO: false,
ParentID: -1,
Title: `Development Manager`
}),
new EmployeesNestedTreeDataItem(
{
Age: 42,
HireDate: `2014-01-22`,
ID: 4,
Name: `Ana Sanders`,
Phone: `(21) 555-0091`,
OnPTO: true,
ParentID: -1,
Title: `CEO`
}),
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`
}),
new EmployeesNestedTreeDataItem(
{
Age: 61,
HireDate: `2010-01-01`,
ID: 10,
Name: `Yang Wang`,
Phone: `(21) 555-0091`,
OnPTO: false,
ParentID: -1,
Title: `Localization Manager`
}),
new EmployeesNestedTreeDataItem(
{
Age: 43,
HireDate: `2011-06-03`,
ID: 3,
Name: `Michael Burke`,
Phone: `0452-076545`,
OnPTO: true,
ParentID: 1,
Title: `Senior Software Developer`
}),
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`
}),
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`
}),
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`
}),
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`
}),
new EmployeesNestedTreeDataItem(
{
Age: 44,
HireDate: `2014-04-04`,
ID: 14,
Name: `Laurence Johnson`,
Phone: `981-443655`,
OnPTO: false,
ParentID: 4,
Title: `Director`
}),
new EmployeesNestedTreeDataItem(
{
Age: 25,
HireDate: `2017-11-09`,
ID: 5,
Name: `Elizabeth Richards`,
Phone: `(2) 283-2951`,
OnPTO: true,
ParentID: 4,
Title: `Vice President`
}),
new EmployeesNestedTreeDataItem(
{
Age: 39,
HireDate: `2010-03-22`,
ID: 13,
Name: `Trevor Ashworth`,
Phone: `981-443655`,
OnPTO: true,
ParentID: 5,
Title: `Director`
}),
new EmployeesNestedTreeDataItem(
{
Age: 44,
HireDate: `2014-04-04`,
ID: 17,
Name: `Antonio Moreno`,
Phone: `(505) 555-5939`,
OnPTO: false,
ParentID: 18,
Title: `Senior Accountant`
}),
new EmployeesNestedTreeDataItem(
{
Age: 50,
HireDate: `2007-11-18`,
ID: 7,
Name: `Pedro Rodriguez`,
Phone: `035-640230`,
OnPTO: false,
ParentID: 10,
Title: `Senior Localization Developer`
}),
new EmployeesNestedTreeDataItem(
{
Age: 27,
HireDate: `2016-02-19`,
ID: 8,
Name: `Casey Harper`,
Phone: `0342-023176`,
OnPTO: true,
ParentID: 10,
Title: `Senior Localization`
}),
new EmployeesNestedTreeDataItem(
{
Age: 25,
HireDate: `2017-11-09`,
ID: 15,
Name: `Patricia Simpson`,
Phone: `069-0245984`,
OnPTO: false,
ParentID: 7,
Title: `Localization Intern`
}),
new EmployeesNestedTreeDataItem(
{
Age: 39,
HireDate: `2010-03-22`,
ID: 9,
Name: `Francisco Chang`,
Phone: `(91) 745 6200`,
OnPTO: false,
ParentID: 7,
Title: `Localization Intern`
}),
new EmployeesNestedTreeDataItem(
{
Age: 25,
HireDate: `2018-03-18`,
ID: 16,
Name: `Peter Lewis`,
Phone: `069-0245984`,
OnPTO: true,
ParentID: 7,
Title: `Localization Intern`
}),
];
super(...(newItems.slice(0, items)));
}
}
}
tsimport React, { useRef } from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import {
IgrTreeGridModule,
} from "@infragistics/igniteui-react-grids";
import {
IgrTreeGrid,
IgrColumn,
} from "@infragistics/igniteui-react-grids";
import { EmployeesNestedTreeData, EmployeesNestedTreeDataItem } from "./EmployeesNestedTreeData";
import "@infragistics/igniteui-react-grids/grids/themes/light/bootstrap.css";
IgrTreeGridModule.register();
export default function App() {
const employeesData = new EmployeesNestedTreeData();
const treeGridRef = useRef<IgrTreeGrid>(null);
const treeGridRef2 = useRef<IgrTreeGrid>(null);
// Recursive function to add the row and its children
function addRowAndChildren(row:EmployeesNestedTreeDataItem, newData:EmployeesNestedTreeDataItem[]) {
if(newData.includes(row)){
return;
}
newData.push(row);
const children = employeesData.filter(emp => emp.ParentID === row.ID);
children.forEach(child => addRowAndChildren(child, newData));
}
function RowDragEnd(evt: any) {
const grid2 = treeGridRef2.current;
const ghostElement = evt.detail.dragDirective.ghostElement;
if (ghostElement != null) {
const dragElementPos = ghostElement.getBoundingClientRect();
const gridPosition = document.getElementById("treeGrid2").getElementsByTagName("igc-tree-grid")[0].getBoundingClientRect();
const withinXBounds = dragElementPos.x >= gridPosition.x && dragElementPos.x <= gridPosition.x + gridPosition.width;
const withinYBounds = dragElementPos.y >= gridPosition.y && dragElementPos.y <= gridPosition.y + gridPosition.height;
if (withinXBounds && withinYBounds) {
const newData = [...grid2.data];
const draggedRowData = evt.detail.dragData.data;
addRowAndChildren(draggedRowData, newData);
grid2.data = newData;
}
}
}
return (
<div className="container sample ig-typography">
<div className="container fill">
<div className="container horizontal wrapper">
<IgrTreeGrid
autoGenerate={false}
data={employeesData}
primaryKey="ID"
foreignKey="ParentID"
id="treeGrid"
width="40%"
ref={treeGridRef}
rowDraggable={true}
onRowDragEnd={RowDragEnd}
>
<IgrColumn
field="Name"
header="Full Name"
dataType="string"
resizable={true}
sortable={true}
editable={true}>
</IgrColumn>
<IgrColumn
field="Age"
dataType="number"
resizable={false}
sortable={false}
filterable={false}
editable={true}>
</IgrColumn>
<IgrColumn
field="Title"
dataType="string"
resizable={true}
sortable={true}
editable={true}>
</IgrColumn>
<IgrColumn
field="HireDate"
header="Hire Date"
dataType="date"
resizable={true}
sortable={true}
editable={true}>
</IgrColumn>
</IgrTreeGrid>
<IgrTreeGrid
autoGenerate={false}
data={[]}
primaryKey="ID"
foreignKey="ParentID"
ref={treeGridRef2}
id="treeGrid2"
width="40%"
emptyGridMessage="Drag and Drop a row from the left grid to this grid"
>
<IgrColumn
field="Name"
header="Full Name"
dataType="string"
resizable={true}
sortable={true}
editable={true}>
</IgrColumn>
<IgrColumn
field="Age"
dataType="number"
resizable={false}
sortable={false}
filterable={false}
editable={true}>
</IgrColumn>
<IgrColumn
field="Title"
dataType="string"
resizable={true}
sortable={true}
editable={true}>
</IgrColumn>
<IgrColumn
field="HireDate"
header="Hire Date"
dataType="date"
resizable={true}
sortable={true}
editable={true}>
</IgrColumn>
</IgrTreeGrid>
</div>
</div>
</div>
);
}
// rendering above component in the React DOM
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
tsx/* shared styles are loaded from: */
/* https://static.infragistics.com/xplatform/css/samples */
.wrapper {
justify-content: space-evenly;
margin: 1rem;
}
css
이 샘플이 마음에 드시나요? Ignite UI for React 전체에 액세스하고 몇 분 만에 나만의 앱을 빌드하기 시작하세요. 무료로 다운로드하세요.
구성
행 드래그를 IgrTreeGrid
활성화하려면 그리드를 rowDraggable
true로 설정하기만 하면 됩니다. 이 기능이 활성화되면 각 행에 행 드래그 핸들이 표시됩니다. 이 핸들은 행 드래그를 시작하는 데 사용할 수 있습니다. 드래그 핸들을 클릭하고 버튼을 누른 상태에서 커서를 움직이 면 그리드의 RowDragStart
이벤트가 발생합니다. 언제든지 클릭을 해제하면 RowDragEnd
이벤트가 발생합니다.
<IgrTreeGrid rowDraggable={true}>
</IgrTreeGrid>
tsx
드래그 아이콘 템플릿 만들기
드래그 핸들 아이콘은 그리드의 dragIndicatorIconTemplate
사용하여 템플릿화할 수 있습니다. 우리가 만들고 있는 예제에서 아이콘을 기본 아이콘(drag_indicator)에서 drag_handle로 변경해 보겠습니다.
이렇게하려면 본문 DragIndicatorIcon
내부에 템플릿을 전달할 수 있습니다. IgrTreeGrid
const dragIndicatorIconTemplate = (ctx: IgrGridEmptyTemplateContext) => {
return (
<>
<IgrIcon name="drag_handle" collection="material" />
</>
);
}
<IgrTreeGrid rowDraggable={true} dragIndicatorIconTemplate={dragIndicatorIconTemplate}>
</IgrTreeGrid>
tsx
애플리케이션 데모
행 재정렬 데모
그리드의 행 드래그 이벤트를 사용하면 행을 드래그하여 재정렬할 수 있는 그리드를 생성할 수 있습니다.
<IgrTreeGrid rowDraggable={true} primaryKey="ID" onRowDragStart={webTreeGridReorderRowStartHandler} onRowDragEnd={webTreeGridReorderRowStartHandler}>
</IgrTreeGrid>
tsx
그리드에 대해 기본 키가 지정되어 있는지 확인하세요! 논리에는 행을 올바르게 다시 정렬할 수 있도록 행에 대한 고유 식별자가 필요합니다.
rowDraggable
활성화되고 드롭 영역이 정의되면 드롭 이벤트에 대한 간단한 핸들러를 구현해야 합니다. 행을 드래그할 때 다음을 확인하세요.
- 행이 확장되었나요? 그렇다면 접으세요.
- 행이 그리드 내부에 삭제되었습니까?
- 그렇다면 드래그된 행이 다른 어느 행에 삭제되었습니까?
- 대상 행을 찾았으면
data
배열에서 레코드 위치를 바꿉니다. - 행이 처음에 선택되었습니까? 그렇다면 선택됨으로 표시하세요.
아래에서 이것이 구현된 것을 볼 수 있습니다.
const webTreeGridReorderRowStartHandler = (args: IgrRowDragStartEventArgs) => {
const draggedRow = args.detail.dragData;
if (draggedRow.expanded) {
draggedRow.expanded = false;
}
}
const webTreeGridReorderRowHandler = (args: IgrRowDragEndEventArgs): void => {
const ghostElement = args.detail.dragDirective.ghostElement;
const dragElementPos = ghostElement.getBoundingClientRect();
const rows = Array.prototype.slice.call(document.getElementsByTagName("igx-tree-grid-row"));
const currRowIndex = getCurrentRowIndex(rows,
{ x: dragElementPos.x, y: dragElementPos.y });
if (currRowIndex === -1) { return; }
const draggedRow = args.detail.dragData.data;
const childRows = findChildRows(treeGridRef.current.data, draggedRow);
//remove the row that was dragged and place it onto its new location
treeGridRef.current.deleteRow(args.detail.dragData.key);
treeGridRef.current.data.splice(currRowIndex, 0, args.detail.dragData.data);
// reinsert the child rows
childRows.reverse().forEach(childRow => {
treeGridRef.current.data.splice(currRowIndex + 1, 0, childRow);
});
}
const findChildRows = (rows: any[], parent: any): any[] => {
const childRows: any[] = [];
rows.forEach(row => {
if (row.ParentID === parent.ID) {
childRows.push(row);
// Recursively find children of current row
const grandchildren = findChildRows(rows, row);
childRows.push(...grandchildren);
}
});
return childRows;
}
const getCurrentRowIndex = (rowList: any[], cursorPosition: any) => {
for (const row of rowList) {
const rowRect = row.getBoundingClientRect();
if (cursorPosition.y > rowRect.top + window.scrollY && cursorPosition.y < rowRect.bottom + window.scrollY &&
cursorPosition.x > rowRect.left + window.scrollX && cursorPosition.x < rowRect.right + window.scrollX) {
// return the index of the targeted row
return parseInt(row.attributes["data-rowindex"].value);
}
}
return -1;
}
tsx
이러한 몇 가지 간단한 단계를 통해 드래그/드롭을 통해 행을 재정렬할 수 있는 그리드를 구성했습니다! 다음 데모에서 위 코드가 실제로 작동하는 모습을 볼 수 있습니다.
또한 행 선택이 활성화되어 있으며 드래그된 행을 삭제할 때 선택이 유지됩니다.
export class EmployeesNestedTreeDataItem {
public constructor(init: Partial<EmployeesNestedTreeDataItem>) {
Object.assign(this, init);
}
public Age: number;
public HireDate: string;
public ID: number;
public Name: string;
public Phone: string;
public OnPTO: boolean;
public ParentID: number;
public Title: string;
}
export class EmployeesNestedTreeData extends Array<EmployeesNestedTreeDataItem> {
public constructor(items: Array<EmployeesNestedTreeDataItem> | number = -1) {
if (Array.isArray(items)) {
super(...items);
} else {
const newItems = [
new EmployeesNestedTreeDataItem(
{
Age: 55,
HireDate: `2008-03-20`,
ID: 1,
Name: `Johnathan Winchester`,
Phone: `0251-031259`,
OnPTO: false,
ParentID: -1,
Title: `Development Manager`
}),
new EmployeesNestedTreeDataItem(
{
Age: 42,
HireDate: `2014-01-22`,
ID: 4,
Name: `Ana Sanders`,
Phone: `(21) 555-0091`,
OnPTO: true,
ParentID: -1,
Title: `CEO`
}),
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`
}),
new EmployeesNestedTreeDataItem(
{
Age: 61,
HireDate: `2010-01-01`,
ID: 10,
Name: `Yang Wang`,
Phone: `(21) 555-0091`,
OnPTO: false,
ParentID: -1,
Title: `Localization Manager`
}),
new EmployeesNestedTreeDataItem(
{
Age: 43,
HireDate: `2011-06-03`,
ID: 3,
Name: `Michael Burke`,
Phone: `0452-076545`,
OnPTO: true,
ParentID: 1,
Title: `Senior Software Developer`
}),
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`
}),
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`
}),
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`
}),
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`
}),
new EmployeesNestedTreeDataItem(
{
Age: 44,
HireDate: `2014-04-04`,
ID: 14,
Name: `Laurence Johnson`,
Phone: `981-443655`,
OnPTO: false,
ParentID: 4,
Title: `Director`
}),
new EmployeesNestedTreeDataItem(
{
Age: 25,
HireDate: `2017-11-09`,
ID: 5,
Name: `Elizabeth Richards`,
Phone: `(2) 283-2951`,
OnPTO: true,
ParentID: 4,
Title: `Vice President`
}),
new EmployeesNestedTreeDataItem(
{
Age: 39,
HireDate: `2010-03-22`,
ID: 13,
Name: `Trevor Ashworth`,
Phone: `981-443655`,
OnPTO: true,
ParentID: 5,
Title: `Director`
}),
new EmployeesNestedTreeDataItem(
{
Age: 44,
HireDate: `2014-04-04`,
ID: 17,
Name: `Antonio Moreno`,
Phone: `(505) 555-5939`,
OnPTO: false,
ParentID: 18,
Title: `Senior Accountant`
}),
new EmployeesNestedTreeDataItem(
{
Age: 50,
HireDate: `2007-11-18`,
ID: 7,
Name: `Pedro Rodriguez`,
Phone: `035-640230`,
OnPTO: false,
ParentID: 10,
Title: `Senior Localization Developer`
}),
new EmployeesNestedTreeDataItem(
{
Age: 27,
HireDate: `2016-02-19`,
ID: 8,
Name: `Casey Harper`,
Phone: `0342-023176`,
OnPTO: true,
ParentID: 10,
Title: `Senior Localization`
}),
new EmployeesNestedTreeDataItem(
{
Age: 25,
HireDate: `2017-11-09`,
ID: 15,
Name: `Patricia Simpson`,
Phone: `069-0245984`,
OnPTO: false,
ParentID: 7,
Title: `Localization Intern`
}),
new EmployeesNestedTreeDataItem(
{
Age: 39,
HireDate: `2010-03-22`,
ID: 9,
Name: `Francisco Chang`,
Phone: `(91) 745 6200`,
OnPTO: false,
ParentID: 7,
Title: `Localization Intern`
}),
new EmployeesNestedTreeDataItem(
{
Age: 25,
HireDate: `2018-03-18`,
ID: 16,
Name: `Peter Lewis`,
Phone: `069-0245984`,
OnPTO: true,
ParentID: 7,
Title: `Localization Intern`
}),
];
super(...newItems.slice(0));
}
}
}
tsimport React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import { IgrTreeGridModule } from "@infragistics/igniteui-react-grids";
import { IgrTreeGrid, IgrColumn } from "@infragistics/igniteui-react-grids";
import { ComponentRenderer, WebTreeGridDescriptionModule } from "@infragistics/igniteui-react-core";
import { EmployeesNestedTreeDataItem, EmployeesNestedTreeData } from './EmployeesNestedTreeData';
import { IgrRowDragStartEventArgs, IgrRowDragEndEventArgs } from "@infragistics/igniteui-react-grids";
import "@infragistics/igniteui-react-grids/grids/themes/light/bootstrap.css";
const mods: any[] = [
IgrTreeGridModule
];
mods.forEach((m) => m.register());
export default class Sample extends React.Component<any, any> {
private treeGrid: IgrTreeGrid
private treeGridRef(r: IgrTreeGrid) {
this.treeGrid = r;
this.setState({});
}
constructor(props: any) {
super(props);
this.treeGridRef = this.treeGridRef.bind(this);
this.webTreeGridReorderRowStartHandler = this.webTreeGridReorderRowStartHandler.bind(this);
this.webTreeGridReorderRowHandler = this.webTreeGridReorderRowHandler.bind(this);
}
public render(): JSX.Element {
return (
<div className="container sample ig-typography">
<div className="container fill">
<IgrTreeGrid
autoGenerate={false}
ref={this.treeGridRef}
id="treeGrid"
data={this.employeesNestedTreeData}
primaryKey="ID"
foreignKey="ParentID"
onRowDragStart={this.webTreeGridReorderRowStartHandler}
rowDraggable={true}
onRowDragEnd={this.webTreeGridReorderRowHandler}>
<IgrColumn
field="Name"
header="Full Name"
dataType="string"
resizable={true}
sortable={true}
filterable={true}
editable={true}>
</IgrColumn>
<IgrColumn
field="Age"
dataType="number"
resizable={false}
sortable={false}
filterable={false}
editable={true}>
</IgrColumn>
<IgrColumn
field="Title"
dataType="string"
resizable={true}
sortable={true}
filterable={true}
editable={true}>
</IgrColumn>
<IgrColumn
field="HireDate"
header="Hire Date"
dataType="date"
resizable={true}
sortable={true}
filterable={true}
editable={true}>
</IgrColumn>
</IgrTreeGrid>
</div>
</div>
);
}
private _employeesNestedTreeData: EmployeesNestedTreeData = null;
public get employeesNestedTreeData(): EmployeesNestedTreeData {
if (this._employeesNestedTreeData == null)
{
this._employeesNestedTreeData = new EmployeesNestedTreeData();
}
return this._employeesNestedTreeData;
}
private _componentRenderer: ComponentRenderer = null;
public get renderer(): ComponentRenderer {
if (this._componentRenderer == null) {
this._componentRenderer = new ComponentRenderer();
var context = this._componentRenderer.context;
WebTreeGridDescriptionModule.register(context);
}
return this._componentRenderer;
}
public webTreeGridReorderRowStartHandler(args: IgrRowDragStartEventArgs){
const draggedRow = args.detail.dragData;
if(draggedRow.expanded){
draggedRow.expanded = false;
}
}
public webTreeGridReorderRowHandler(args: IgrRowDragEndEventArgs): void {
const ghostElement = args.detail.dragDirective.ghostElement;
const dragElementPos = ghostElement.getBoundingClientRect();
const grid = this.treeGrid;
const rows = Array.prototype.slice.call(document.getElementsByTagName("igx-tree-grid-row"));
const currRowIndex = this.getCurrentRowIndex(rows,
{ x: dragElementPos.x, y: dragElementPos.y });
if (currRowIndex === -1) { return; }
const draggedRow = args.detail.dragData.data;
const childRows = this.findChildRows(grid.data, draggedRow);
//remove the row that was dragged and place it onto its new location
grid.deleteRow(args.detail.dragData.key);
grid.data.splice(currRowIndex, 0, args.detail.dragData.data);
// reinsert the child rows
childRows.reverse().forEach(childRow => {
grid.data.splice(currRowIndex + 1, 0, childRow);
});
}
private findChildRows(rows: any[], parent: any): any[] {
const childRows: any[] = [];
rows.forEach(row => {
if (row.ParentID === parent.ID) {
childRows.push(row);
// Recursively find children of current row
const grandchildren = this.findChildRows(rows, row);
childRows.push(...grandchildren);
}
});
return childRows;
}
public getCurrentRowIndex(rowList: any[], cursorPosition: any) {
for (const row of rowList) {
const rowRect = row.getBoundingClientRect();
if (cursorPosition.y > rowRect.top + window.scrollY && cursorPosition.y < rowRect.bottom + window.scrollY &&
cursorPosition.x > rowRect.left + window.scrollX && cursorPosition.x < rowRect.right + window.scrollX) {
// return the index of the targeted row
return parseInt(row.attributes["data-rowindex"].value);
}
}
return -1;
}
}
// rendering above component in the React DOM
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Sample/>);
tsx/* shared styles are loaded from: */
/* https://static.infragistics.com/xplatform/css/samples */
css
제한 사항
현재 rowDraggable
에는 알려진 제한 사항이 없습니다.
API 참조
rowDraggable
RowDragStart
RowDragEnd
IgrTreeGrid
추가 리소스
우리 커뮤니티는 활동적이며 항상 새로운 아이디어를 환영합니다.