LoginSignup
2
3

More than 5 years have passed since last update.

ReactでDataGridViewが欲しくなった

Posted at

背景

リソースとってきて。

ループでゴリゴリ<table><tr><td>配置して。

いちいちそんなことをやりたくなかった。

react tableとか、react datagridでググると良さげなコンポーネントは結構あるみたい。
けど、ソートとか、カラムの移動とか、そこまで仰々しいものは必要なかった。

なのでお勉強を兼ねて簡単なものを実装することにした。

やりたいこと

最低限、以下の2つが出来ればOK。

  • dataProvider、dataFieldをプロパティに与えると、そこからテーブルを生成する
  • デザインは外からcssを充てるスタイル

実装

コンポーネントはこんな感じで。

import React, { Component, PropTypes } from 'react';

/**
 * データとフィールドを指定して<table>を描画する。
 * 内部的にはシンプルなテーブルなので、デザインは外部からCSSにて操作する。
 * @param {*} props - 利用元から渡されるプロパティ
 * @example
 * <DataGrid dataProvider={array of object}>
 *   <DataGridColumn dataField="dog"></DataGridColumn>
 *   <DataGridColumn dataField="cat"></DataGridColumn>
 *   <DataGridColumn dataField="rabbit"></DataGridColumn>
 * </DataGrid>
 */
export const DataGrid = (props) => {
  // DataGridColumnより、ヘッダを構築
  const makeThead = (children) => {

    let theadCols = children.map((child) => {
      return <td>{child.props.dataField}</td>
    });

    return (
      <thead>
        <tr>
          {theadCols}
        </tr>
      </thead>
    );
  };

  // データプロバイダをリソースに、レコード部を構築
  const makeTbody = (provider, children) => {

    let tbodyRows = provider.map((item) => {
      return (
        <tr>
          {
            children.map((child) => {
              return <td>{item[child.props.dataField]}</td>
            })
          }
        </tr>
      );
    });

    return (
      <tbody>
        {tbodyRows}
      </tbody>
    );
  };

  return (
    <table className={props.className}>
      {makeThead(props.children)}
      {makeTbody(props.dataProvider, props.children)}
    </table>
  );
};

/**
 * データグリッドのカラムを定義する。
 * <DataGrid>の子要素として必ず1つ以上配置する。
 * @param {*} props - 利用元から渡されるプロパティ
 */
export const DataGridColumn = (props) => {
  // datafieldを受け取るのみ。
  // 要素の描画は親コンポーネントにて実施
  return null;
};

DataGrid.propTypes = {
  dataProvider: PropTypes.arrayOf(PropTypes.object).isRequired,
  children: PropTypes.node.isRequired,
  className: PropTypes.string,
};

DataGridColumn.propTypes = {
  dataField: PropTypes.string.isRequired,
};

呼び出し側はこんな感じで呼び出す。

import { DataGrid, DataGridColumn } from '../components/DataGrid';

const dp = [
  { dog: "", cat: "", rabbit: "" },
  { dog: "いぬ", cat: "ねこ", rabbit: "うさぎ" },
  { dog: "dog", cat: "cat", rabbit: "rabbit" },
];

return (
  <DataGrid dataProvider={dp} className="mygrid">
    <DataGridColumn dataField="dog"></DataGridColumn>
    <DataGridColumn dataField="cat"></DataGridColumn>
    <DataGridColumn dataField="rabbit"></DataGridColumn>
  </DataGrid>
);

TODO

やっぱソートとかしたいし、ヘッダ固定でスクロールしたいね。

後者はcssで出来なくもないのかな。

2
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3