業務で使おうと思ったらそれなりのデータグリッド部品が必要になりますよね。そんなとき、ちょっと我慢すれば使えそうなreact-datagridを紹介したいと思います。
react-datagrid
npm install react-datagrid --save tsd install react-datagrid
で導入が可能なデータグリッド部品です。公式サイトは以下のページになります。
A carefully crafted datagrid for React
サンプルを見ると、大体どんなことが出来るのかわかるようになっています。
A carefully crafted datagrid for React
ライセンスはMITになるので、ライセンス的にも使いやすいライブラリです。
React + TypeScriptで使う
npmとtsdコマンドを打ち込んで必要なファイルを準備したら、node_modules/react-datagrid/dist/index-no-normalize.min.cssをプロジェクトにコピーしてプロジェクトに含めます。そしてindex.htmlで参照するように設定します。今回はWebAPIの呼び出し結果をバインドしたいので、whatwg-fetchもインストールして参照しておきました。index.htmlは以下のような雰囲気になります。
<!DOCTYPE html><html><head><metahttp-equiv="Content-Type"content="text/html; charset=utf-8" /><metacharset="utf-8" /><title>Hello world</title><linkhref="index-no-normalize.min.css"rel="stylesheet" /></head><body><divid="content"></div><scriptsrc="scripts/fetch.js"></script><scriptsrc="bundle.js"></script></body></html>
WebAPI
こんな感じのASP.NET WebAPIを準備しておきます。
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Threading; using System.Web.Http; namespace ReactApplication3.Controllers { publicclass PeopleController : ApiController { public IHttpActionResult Get() { Thread.Sleep(5000); var source = Enumerable.Range(1, 1000) .Select(x => new Person { Id = x, Name = $"おかずき{x}", Age = x % 30 + 30, }); return Ok(source); } } publicclass Person { publicint Id { get; set; } publicstring Name { get; set; } publicint Age { get; set; } } }
react-datagridを使う
idPropertyとdataSoruceとcolumnsは必須っぽいです。TypeScriptだと割とインテリセンスがきくので簡単に書けます。色気を出してフィルタリングも実装してみました。onFilterに何かしら追加するとフィルタリングが有効になるみたいです。
/// <reference path="../typings/whatwg-fetch/whatwg-fetch.d.ts" />import * as React from 'react'; import * as ReactDOM from 'react-dom'; import ReactDataGrid = require('react-datagrid'); class Person { constructor(public id: number, public name: string, public age: number) {}}interface DataGridComposerState { data: Person[]; loading: boolean; }class DataGridComposer extends React.Component<{}, DataGridComposerState> {private originalData: Person[]; constructor(props: {}) {super(props); this.state = { data: [], loading: true}; }private dataSource() {return fetch('api/People', { headers: {'Accept-Type': 'application/json'}}) .then(x => x.json()); }private handleFilter(column, value, allFilterValues) {var data = this.originalData; Object.keys(allFilterValues).forEach(name => {var f = allFilterValues[name] as string; if (f === '') {return; } data = data.filter(x => {return x[name].toString().indexOf(f) === 0; }); }); this.setState({ data: data } as DataGridComposerState); } componentDidMount() {this.dataSource().then(x => {this.originalData = x as Person[]; this.setState({ data: x as Person[], loading: false} as DataGridComposerState); }); } render() {return ( <ReactDataGrid idProperty='id' dataSource={this.state.data} columns={[{ name: 'name', title: '名前', width: 200 }, { name: 'age', title: '年齢', width: 200 }]} pagination={false} style={{ height: 300 }} loading={this.state.loading} liveFilter={true} onFilter={this.handleFilter.bind(this)}/> ); }}class App extends React.Component<{}, {}> { render() {return ( <div> <h1>OK Google.</h1> <DataGridComposer /> </div>); }} ReactDOM.render( <App />, document.getElementById('content'));
実行してみる
こんな感じでローディング中の表示がされます。
そしてデータが表示されます。
フィルタリングもばっちり。
いまいちなところと注意点
style属性のheightでデータグリッドの高さを決めれるのですが、ここはnumber型じゃないとダメです。'500px'とかって書くと効きません。あと、ローカライズが弱いです。一部表示が英語のままでもいいかなというのが許容できない場合は使えないと思います。