Front-End

Ag gird 정리

딸기케잌🍓 2023. 2. 8. 18:29

AG Grid

JavaScript 기반으로 그리드를 손쉽게 그려주는 라이브러리입니다.

react, vue, angular를 모두 지원하고, 복잡한 그리드를 비교적 쉽게 그릴 수 있게 도와줍니다.

 

AG Grid사용해보기

다음의 명령어로 ag-grid 디펜던시를 설치합니다.

npm install --save ag-grid-community
npm install --save ag-grid-react

package.json에서 디펜던시가 설치된 모습을 확인할 수 있습니다.

"dependencies": {
   "ag-grid-community": "29.0.0",
   "ag-grid-react": "29.0.0",
   ...

ag-grid-community는 그리드 코어 로직이며

ag-grid-react는 리액트 렌더링 엔진입니다. 리액트 기반으로 ag grid를 그리기 위해서 두 디펜던시 모두 필요하며 두개 버전이 꼭 같아야 합니다.

 

AG Grid 예제

다음은 AG Grid 공식문서에서 가져온 예제 코드와 렌더링된 결과입니다. 주요 개념 위주로 살펴보겠습니다.

import React, { useState, useRef, useEffect, useMemo, useCallback} from 'react';
import { render } from 'react-dom';
import { AgGridReact } from 'ag-grid-react'; // the AG Grid React Component

import 'ag-grid-community/styles/ag-grid.css'; // Core grid CSS, always needed
import 'ag-grid-community/styles/ag-theme-alpine.css'; // Optional theme CSS

const App = () => {

 const gridRef = useRef(); // Optional - for accessing Grid's API
 const [rowData, setRowData] = useState(); // Set rowData to Array of Objects, one Object per Row

 // Each Column Definition results in one Column.
 const [columnDefs, setColumnDefs] = useState([
   {field: 'make', filter: true},
   {field: 'model', filter: true},
   {field: 'price'}
 ]);

 // DefaultColDef sets props common to all Columns
 const defaultColDef = useMemo( ()=> ({
     sortable: true
   }));

 // Example of consuming Grid Event
 const cellClickedListener = useCallback( event => {
   console.log('cellClicked', event);
 }, []);

 // Example load data from sever
 useEffect(() => {
   fetch('https://www.ag-grid.com/example-assets/row-data.json')
   .then(result => result.json())
   .then(rowData => setRowData(rowData))
 }, []);

 // Example using Grid's API
 const buttonListener = useCallback( e => {
   gridRef.current.api.deselectAll();
 }, []);

 return (
   <div>

     {/* Example using Grid's API */}
     <button onClick={buttonListener}>Push Me</button>

     {/* On div wrapping Grid a) specify theme CSS Class Class and b) sets Grid size */}
     <div className="ag-theme-alpine" style={{width: 500, height: 500}}>

       <AgGridReact
           ref={gridRef} // Ref for accessing Grid's API
           rowData={rowData} // Row Data for Rows
           columnDefs={columnDefs} // Column Defs for Columns
           defaultColDef={defaultColDef} // Default Column Properties
           animateRows={true} // Optional - set to 'true' to have rows animate when sorted
           rowSelection='multiple' // Options - allows click selection of rows
           onCellClicked={cellClickedListener} // Optional - registering for Grid Event
           />
     </div>
   </div>
 );
};

export default App;

 

 

스타일 셋팅

임포트 문에서 ag-grid.css 는 꼭 필요한 css파일이고, ag-theme-alpine.css는 옵셔널한 그리드의 테마입니다.

https://www.ag-grid.com/react-data-grid/themes/

 

React Data Grid: Themes

The grid is styled with CSS, and a theme is simply a CSS class that applies styles to the grid. Download v29 of the best React Data Grid in the world now.

www.ag-grid.com

위 링크에서 적용 가능한 테마를 더 확인할 수 있습니다.

 

AgGridReact의 부모 div에 className 프롭스로 ag-theme-alpine을 주고, 스타일 프롭스도 주어서 그리드의 테마와 스타일을 설정할 수 있습니다.

 

AG Grid의 필수 프롭스

AgGridReact 컴포넌트로 그리드를 그릴 수 있는데 필수 프롭스는 다음과 같습니다.

  • rowData
  • columnDefs

데이터 셋팅(rowData 프롭스)

보통 위의 예제와 같이 useEffect에서 그리드에서 필요한 데이터를 미리 가져온 후 useState 훅으로 데이터를 변수에 셋해줍니다.

그리고 AgGridReact 컴포넌트 프롭의 rowData에 셋해준 데이터를 넘겨줍니다.

 // Example load data from sever
 useEffect(() => {
   fetch('https://www.ag-grid.com/example-assets/row-data.json')
   .then(result => result.json())
   .then(rowData => setRowData(rowData))
 }, []);
 return (
  ...
       <AgGridReact
         ...
           rowData={rowData} />
  ...
 );

 

열 정의(columnDefs 프롭스)

위의 예제에 headerName을 추가했습니다.

 // Each Column Definition results in one Column.
 const [columnDefs, setColumnDefs] = useState([
   {headerName: 'Make', field: 'make', filter: true},
   {headerName: 'Model', field: 'model', filter: true},
   {headerName: 'Price', field: 'price'}
 ]);

 

columnDefs는 배열이고 각 원소들은 Object로 되어있습니다. 각각의 object는 headerName, field와 filter를 키로 가지고 있습니다.

headerName은 열의 이름으로, 화면에 표시됩니다.

field는 rowData 프롭에 넘겨준 데이터에서 표시할 key 입니다.

 

예를 들어, rowData가 다음과 같고 메달의 골드 갯수를 열에 표시하고 싶다면

const rowData = [
    {
        athlete: 'Michael Phelps',
        medals: {
            gold: 8, silver: 1, bronze: 0
        }
    }
];

아래와 같이 field에 밸류로 'medals.gold'를 주면됩니다.

const columnDefs = [
    { field: 'athlete', headerName: 'Name' },
    // Using dot notation to access nested property
    { field: 'medals.gold', headerName: 'Gold' },
];

다음은 렌더링된 결과입니다.

 

 

그리드 API 사용

Ref를 이용해서 AG Grid의 API에 접근할 수 있습니다.

const gridRef = useRef(); // Ref for accessing Grid's API

// Example using Grid's API
const buttonListener = useCallback( e => {
   gridRef.current.api.deselectAll();
}, []);

 return (
  ...
  <button onClick={buttonListener}>Push Me</button>
  <AgGridReact
    ...
    rowData={rowData} />
  ...
 );

 

gridRef.current.api.deselectAll();

 

위와 같이 gridRef를 이용하여 그리드 API를 호출할 수 있습니다.

 

deselectAll을 공식문서에서 검색해보면 필터링 여부와 상관없이 셀렉션을 모두 초기화하는 함수라는 것을 알 수 있습니다.

공식 문서에서는 이 외에도 컬럼 정의, 컬럼 헤더, 이벤트, 필터링, 페이지네이션, Row, 스크롤링, 셀렉션, 소팅 등

그리드를 컨트롤할 수 있는 다양한 API를 제공하고 있습니다.

 

 

 

Column에 대해서 더욱 디테일하게 컨트롤할 수 있는 columnApi도 별도로 제공하고 있습니다.

 gridRef.current?.columnApi.getColumns();

공식 문서에서 어떤 인자를 받고 리턴형은 무엇이고 함수에 대한 설명까지 정리가 잘 되어 있습니다.

예를 들어 getColumns 함수의 경우 그리드의 모든 컬럼들을 Column 타입의 배열로 리턴하는 것을 알 수 있습니다.

이 뿐만 아니고 columnApi로 접근하여 Column Keys, Column Groups, Moving, Pinning, Pivoting, Sizing 등을 컨트롤 할 수 있습니다.

 

 
 

그리드의 다양한 옵션들

AgGridReact 컴포넌트의 프롭스를 어떻게 주냐에 따라서 그리드에 다양한 옵션들을 설정할 수 있습니다.

 

 

 

 

주로 쓰이는 <AgGridReact> 컴포넌트 관련되 프롭스는 다음과 같습니다.

 

rowSelection : 한번에 셀랙할 수 있는 갯수로, 'single'은 1개 'multiple'은 다중선택 의미 

onCellClicked : 행 클릭시의 콜백함수

onRowDoubleClicked

ref : gird를 참조하는 ref로 추후에 이 ref를 이요해서 griddata api 호출 가능

 

 

 

트리 구조로 ag-grid 사용하기

girOptions을 선언해서

  const gridOptions = useMemo(() => {
    return {
      gridRef,
      rowData: [],
      // defaultColDef,
      //columnDefs
      // defaultColDef: columnDefs,
      autoGroupColumnDef: autoGroupColumnDef,
      treeData: true,
      //suppressCopyRowsToClipboard: true,
      //enableRangeSelection: true,
      //tooltipShowDelay: 100,
      groupDefaultExpanded: 1,
      rowSelection: "single",
      getDataPath: (data: any) => data.treePath,
      // onComponentStateChanged,
      // onGridReady,
      onCellClicked: onCellClicked,
      // onSelectionChanged: onSelectionChanged,
      getContextMenuItems,
      // onRowDoubleClicked,
    };
  }, [isAdminMode]);

  return (
    <>
      <DataGrid {...gridOptions} gridSize={{ height: "100%" }} />
    </>
  );

 

 

ag-grid 트리로 구현하기

트리 구조로도 ag-grid를 사용할 수 있습니다.

 <AgGridReact
           ref={gridRef} // Ref for accessing Grid's API
           rowData={rowData} // Row Data for Rows
           onCellClicked={cellClickedListener} // Optional - registering for Grid Event
           treeData={true}
           getDataPath: {(data: any) => data.treePath}
           />

treeData = true,

getDataPath는 데이터의 트리 구조를 배열에 담아 리턴합니다.

예를 들어 

 

음식(0 depth)

-한식(1 depth)

--불고기(2 depth)

--비빔밥(2 depth)

--갈비찜(2 depth)

-양식(1 depth)

-중식(1 depth)

 

위와 같은 트리 구조에서 getDataPath는 아래와 같이 리턴합니다.

["음식"], ["음식", "한식"], ["음식", "한식", "불고기"], ["음식", "한식", "비빔밥"], ...,

 

 

ag-grid에서 컨텍스트 메뉴 구현하기

그리드 셀에서 우클릭하여 컨텍스트 메뉴를 보여줄 수도 있습니다.

 <AgGridReact
         ...
           getContextMenuItems={getContextMenuItems}
           />

 

GetContextMenuItemsParams와 MenuItemDef를 임포트합니다.

import {GetContextMenuItemsParams, MenuItemDef} from "ag-grid-community";

...

const getContextMenuItems = useCallback(
    (params: GetContextMenuItemsParams): (string | MenuItemDef)[] => {
      const result: (string | MenuItemDef)[] = [
        {
          name: "Create",
          action: () => handleCreate(params.node ? params.node : null),
        },
        {
          name: "Modify",
          action: () => handleModify(params.node ? params.node : null),
        },
        {
          name: "Delete",
          action: () => handleDelete(params.node ? params.node : null),
        },
      ];
      return result;
    },
  );

다음과 같이 컨텍스트 메뉴를 생성할 수 있습니다.

'Front-End' 카테고리의 다른 글

[html]개행 표시하기  (0) 2023.12.02
[끄적끄적] CSS 스타일링 고민  (0) 2023.11.20
vite 로컬에서 https 설정  (0) 2023.08.20