게으른개발너D

[React] Handsontable 1 - 설치 및 데이터 추가 본문

프로젝트/Side Project

[React] Handsontable 1 - 설치 및 데이터 추가

lazyhysong 2023. 11. 4. 19:59

 

Handsontable을 이용하여 간단한 기능을 구현하려다 의외로 개고생을 하여 기록한다.

 

 

https://handsontable.com/docs/react-data-grid/

 

React Data Grid - Documentation | Handsontable

Handsontable documentation What is Handsontable? Handsontable (pronounced "hands-on-table") is a JavaScript data grid component that brings the well-known look and feel of spreadsheets to your application. Thousands of business apps depend on Handsontable

handsontable.com

Handsontable은 React-Data-Grid를 기반으로 하는 라이브러리로, 엑셀과 유사한 기능을 제공한다.
공식 문서에서 자세한 내용을 확인할 수 있다.

 

React를 이용한 demo는 여기에서 확인할 수 있다.

https://codesandbox.io/s/handsontable-react-data-grid-hello-world-app-13-1-0-fdv2lc

 

Handsontable React Data Grid - Hello World App 13.1.0 - CodeSandbox

Handsontable React Data Grid - Hello World App 13.1.0 by jansiegel using @handsontable/react, handsontable, react, react-dom, react-native-listener, react-scripts

codesandbox.io

 

 

1. 구현할 내용

이름 생년월일 모임 만남 횟수
James 1999-08-30 알고리즘 2
Emily 2000-12-24 프론트엔드 5
Amber 1988-06-14 알고리즘 3
Lisa 1994-07-03 돼지파티 13

 

1. 해당 내용을 table data로 넣는다.

2. 이름, 생년월일, 모임 열은 내용을 수정할 수 없다.

3. 컨텍스트메뉴 기능을 넣어 행과 열을 추가하거나 삭제할 수 있다. (1행은 삭제하지 못한다.)

4. 저장 버튼을 클릭 시 console.log로 삭제된 행과 열에 대한 정보를 출력한다.

5. 새로운 행이 추가 되었을 시, 저장 버튼을 누르면 해당 행의 이름, 생년월일, 모일 열은 수정할 수 없게된다.

 

point 🤔

여기서 포인트이면서 문제가 되는 게 readonly를 적용해야하는 열(이름, 생년월일, 모임)이 있다는 점이다.

이게 왜 문제가 되냐하면 handsontable의 데이터는 배열로 받고, 특정한 열에 readonly를 적용하게 되면 그건 배열 index에 적용이 된다. 하지만 행이나 열을 추가하게 되면 readonly를 적용한 열의 index가 바뀐다는 점.

그리고 행을 추가할 시 새로운 행의 이름, 생년월일, 모임 부분은 내용을 넣을 수 있도록 readonly가 적용되지 않아야된다.

 

일단 천천히 구현해보자.

 

 

2. handsontable 설치

먼저 create-react-app으로 react 프로젝트를 만든다. typescript로 구현할 예정이며 프로젝트 이름은 manage_crew로 정하였다.

1. handsontable 설치

$ npm install handsontable @handsontable/react

 

해당 명령어를 입력하여 handsontable for react를 설치한다.

package.json을 확인하면 dependencies에 @handsontable/react 와 handsontable가 설치되어 있다.

src 디렉토리엔 index.tsx와 App.tsx만 남겨두었고 App.tsx에서 모두 구현할 예정이다.

2. css import

// App.tsx
import 'handsontable/dist/handsontable.full.min.css';

 

hansontable css를 import 한다.

 

3. hansontable modules

// App.tsx
import Handsontable from 'handsontable/base';
import { registerAllModules } from 'handsontable/registry';
import 'handsontable/dist/handsontable.full.min.css';

registerAllModules();

 

registerAllModules(); 를 사용하면 handsontable의 모든 모듈을 한번에 가져올 수 있다.

https://handsontable.com/docs/react-data-grid/modules/

물론 위 링크에서 필요한 모듈을 찾아서 따로 추가할 수도 있다.

 

4. HotTable Component

// App.tsx
import Handsontable from 'handsontable/base';
import { registerAllModules } from 'handsontable/registry';
import { HotTable } from '@handsontable/react';
import './App.css';
import 'handsontable/dist/handsontable.full.min.css';
import Button from './components/Button';

registerAllModules();

function App() {
  const handleClickSave = () => {};
  return (
    <div className="App">
      <Button callback={handleClickSave}>저장</Button>
      <HotTable 
        licenseKey="non-commercial-and-evaluation" 
        height="auto"
        widht="auto"
      />
    </div>
  );
}

export default App;

 

import { HotTable } from '@handsontable/react';

HotTable 컴포넌트를 부르면 기본적인 엑셀 테이블 만들기는 준비되었다.

상업적 이용으로 사용하는게 아닐 경우 컴포넌트에 licenseKey="non-commercial-and-evaluation" 를 추가한다.

참고로 저장 버튼은 컴포넌트로 따로 분리하였다.

 

5. add props

내용을 추가하기 위해 HotTable의 props를 추가해주자.

먼저 src 위치에 default_data.ts 파일을 만들어 위의 테이블 데이터를 2차 배열로 나타내었다.

// default_data.ts
export const DEFAULT_DATA = [
  ['이름', '생년월일', '모임', '만남 횟수'],
  ['James', '1999-08-30', '알고리즘', 2],
  ['Emily', '2000-12-24', '프론트엔드', 5],
  ['Amber', '1988-06-14', '알고리즘', 3],
  ['Lisa', '1994-07-03', '돼지파티', 13],
];

 

기본적인 데이터는 data prop으로 채울 수 있다.

데이터와 관련없는 props는 HOTTABLE_PROPS 변수로 따로 분리해주었다.

// App.tsx
import Handsontable from 'handsontable/base';
import { registerAllModules } from 'handsontable/registry';
import { HotTable } from '@handsontable/react';
import './App.css';
import 'handsontable/dist/handsontable.full.min.css';
import Button from './components/Button';
import { DEFAULT_DATA } from './default_data';

registerAllModules();

const HOTTABLE_PROPS = {
  height: 'auto',
  width: 'auto',
  licenseKey: 'non-commercial-and-evaluation',
};

function App() {
  const handleClickSave = () => {};
  return (
    <div className="App">
      <Button callback={handleClickSave}>저장</Button>
      <HotTable data={DEFAULT_DATA} {...HOTTABLE_PROPS} />
    </div>
  );
}

export default App;

 

 

 

 

3. context menu

https://handsontable.com/docs/react-data-grid/context-menu/

 

Context menu - React Data Grid | Handsontable

Quickly access contextual actions such as removing rows, inserting columns or copying data, by opening the context menu. Enable the context menu with the default configuration: To see the context menu, right-click on a cell: You can define items in the men

handsontable.com

오른쪽 마우스를 클릭했을 때 context menu가 나오게 하려면 prop으로 contextMenu를 쓰면 된다.

// App.tsx
function App() {
  const handleClickSave = () => {};
  return (
    <div className="App">
      <Button callback={handleClickSave}>저장</Button>
      <HotTable data={DEFAULT_DATA} contextMenu={true} {...HOTTABLE_PROPS} />
    </div>
  );
}

이렇게 행과 열의 추가, 삭제, readonly까지 지정할 수 있다.

하지만 우리가 사용할 건 행과 열의 추가와 삭제뿐이니 context menu로 사용할 메뉴를 지정해주자

// App.tsx
import { Settings } from 'handsontable/plugins/contextMenu';
...

const CONTEXT_MENU: Settings = [
  'row_above',
  'row_below',
  '---------',
  'col_left',
  'col_right',
  '---------',
  'remove_col',
  'remove_row',
];
...

function App() {
  const handleClickSave = () => {};
  return (
    <div className="App">
      <Button callback={handleClickSave}>저장</Button>
      <HotTable
        data={DEFAULT_DATA}
        contextMenu={CONTEXT_MENU}
        {...HOTTABLE_PROPS}
      />
    </div>
  );
}

Comments