---
name: Table
menu: Components
---

# Table
import Table from './lib/Table'
import CollapseTable from './lib/CollapseTable'
import TableSort from './lib/TableSort'
import DataTable from './lib/DataTable'
import AutoTable from './lib/AutoTable'
import AutoCollapseTable from './lib/AutoCollapseTable'
import './style/table.scss'
import './style/table_sort.scss'
import './style/data_table.scss'
import './style/common.scss'
import './style/collapse_table.scss'
import './style/auto_table.scss'
import { mockData, mockCGI } from './demo/util';
import Icon from '../icon/index'
import Button from '../button/index'
import {Playground, Props} from 'docz'

## Props & Methods
### Table
<Props of={Table} />

### CollapseTable
```
可折叠行表格,封装自Table，具有以下功能：
    - 可折叠部分行
```
<Props of={CollapseTable} />

### 👆data
| 属性 | 说明 | 类型 | 默认值 |
| :--- | :--- | :--- | :--- |
| row | 一维数组，当前一行需要的数据。该行会一直显示，通过点击来控制是否显示对应被控制的折叠的行是否显示 如果数组元素是 React组件实例：展示元素本身 else：展示元素toString()  如果数组元素是空字符串或者==null会显示为'-' | `array.isRequired` | `undefined` |
| collapseRows | 当前这行控制的可以被折叠的行,二维数组 | `arrayOf(PropTypes.array)` | `undefined` |
| showCollapseRows | 是否显示,当前这行控制的可以被折叠的行 | `arrayOf(PropTypes.array)` | `false` |

### AutoTable
```
数据表格组件，封装自Table,具有以下功能：
    - 自动分页
    - 数据缓存
    - 选中
    - 排序
    - 筛选
```
<Props of={AutoTable} />

### 👆cols
| 属性 | 说明 | 类型 | 默认值 |
| :--- | :--- | :--- | :--- |
| display | 表格头部一列名称 如果数组元素是 React组件实例：展示元素本身 else：展示元素toString() | `array.isRequired` | `undefined` |
| width | 表格一列所占宽度百分比 | `number` | `undefined` |
| colspan | 跨列,默认为1 | `number` | `1` |
| sort | 该表头是否需要排序，如果需要排序  1.该列只有一个排序选项：请传入一个只有一个元素的[SortType]类型的Arrays  2.该列有多个排序选项:请传入一个[SortType]类型的Arrays | `arrayOf` | `undefined` |
### 👆sort
| 属性 | 说明 | 类型 | 默认值 |
| :--- | :--- | :--- | :--- |
| display | 表格头部一列名称 如果数组元素是 React组件实例：展示元素本身 else：展示元素toString() | `array.isRequired` | `undefined` |
| key | 用于表示该排序方法的唯一key | `string.isRequired` | `undefined` |
| value | 默认排序方法 1=顺序 -1=逆序 如果==null表示当前排序方法默认不启用 | `oneOf([-1, 1])` | `undefined` |


### AutoCollapseTable
```
可折叠行表格数据表格组件，封装自CollapseTable,具有以下功能：
    - 可折叠部分行
    - 自动分页
    - 数据缓存
    - 选中
    - 排序
    - 筛选
```
<Props of={CollapseTable} />


### TableSort
<Props of={TableSort} />

### 👆options
| 属性 | 说明 | 类型 | 默认值 |
| :--- | :--- | :--- | :--- |
| display | 用来展示 | `any.isRequired` | `undefined` |
| value | 用于回调 | `any.isRequired` | `undefined` |


## Basic Usage
<Playground>
    <Table
            cols={[
              { display: '角色', width: 8 },
              { display: '描述', width: 40 },
              { display: '成员数', width: 5 },
              {
                display: <span>操作
                  <Icon
                    type="question"
                  />
                </span>, width: 20,
              },
            ]}
            data={[
              ['超级管理员', '机构创始人，拥有所有功能的权限，且可以为其他角色自由配置功能。', 1, <a>管理成员</a>],
              ['教学管理员', '机构创始人从所关联的成员中选取，协助管理机构，主要是教务教学相关工作的管理，默认拥有大部分权限。', 62, <a>管理成员</a>],
              ['老师', '主要负责给学生上课，以及准备课程教案和教学资料。', 230, <a>管理成员</a>],
              ['助教', '主要协助老师上课，工作内容包括在课堂上进行班级纪律管理，以及维护班级交流QQ群等。', 232, <a>管理成员</a>],
              ['销售管理员', '销售模块的管理人员，默认拥有查询学员、分配销售人员并查看机构与销售人员的销售相关数据的权限。', 3, <a>管理成员</a>],
              ['教务', '主要负责除了上课之外的大部分教务教学相关工作。', 5, <a>管理成员</a>],
              ['销售', '销售人员，默认拥有查询被分配课程的学员、查看自己的销售数据并进行销售记录的相关权限。', 12, <a>管理成员</a>],
              ['财务', '主要负责机构营收的查询和管理。', 1, <a>管理成员</a>],
              ['自定义1', '自定义1', 1, <div>
                <a>管理成员</a>
                <br />
                <a>编辑角色</a>
                <br />
                <a>删除</a>
                <br />
              </div>],
            ]}
          />
</Playground>

## Complex Header
<Playground>
    <Table
        cols={[
            { display: '角色', width: 8 },
            {
            display: <table style={{ width: '100%' }}>
                <tbody>
                <tr>
                    <td>A</td>
                    <td>B</td>
                </tr>
                <tr>
                    <td colSpan="2">C</td>
                </tr>
                </tbody>
            </table>, width: 40,
            },
            { display: '成员数', width: 5 },
            { display: '操作', width: 20 },
        ]}
        data={[
            ['超级管理员', '机构创始人，拥有所有功能的权限，且可以为其他角色自由配置功能。', 1, <a>管理成员</a>],
            ['教学管理员', '机构创始人从所关联的成员中选取，协助管理机构，主要是教务教学相关工作的管理，默认拥有大部分权限。', 62, <a>管理成员</a>],
            ['老师', '主要负责给学生上课，以及准备课程教案和教学资料。', 230, <a>管理成员</a>],
            ['助教', '主要协助老师上课，工作内容包括在课堂上进行班级纪律管理，以及维护班级交流QQ群等。', 232, <a>管理成员</a>],
        ]}
    />
</Playground>

## Cross Column
<Playground>
    <Table
        cols={[
            { display: '角色', width: 8 },
            { display: '描述', width: 80, colspan: 2 },
            { display: '操作', width: 10 },
        ]}
        data={[
            ['超级管理员', '机构创始人，拥有所有功能的权限，且可以为其他角色自由配置功能。', 1, <a>管理成员</a>],
            ['教学管理员', '机构创始人从所关联的成员中选取，协助管理机构，主要是教务教学相关工作的管理，默认拥有大部分权限。', 62, <a>管理成员</a>],
            ['老师', '主要负责给学生上课，以及准备课程教案和教学资料。', 230, <a>管理成员</a>],
            ['助教', '主要协助老师上课，工作内容包括在课堂上进行班级纪律管理，以及维护班级交流QQ群等。', 232, <a>管理成员</a>],
        ]}
    />
</Playground>

## Null Values
<Playground>
    <Table
            cols={[
              { display: '角色', width: 8 },
              { display: '操作', width: 10 },
            ]}
            data={[
              ['超级管理员', null],
              ['教学管理员', undefined],
              ['老师', ''],
              ['助教', 0],
            ]}
    />
</Playground>

## Select Rows
<Playground>
    <Table
        cols={[
            { display: 'A', width: 45 },
            { display: 'B', width: 50 },
        ]}
        data={mockData(2, 4)}
        canSelect
        onSelectedChange={console.log}
        />
</Playground>

## No Data
<Playground>
    <Table
        cols={[
            { display: 'A', width: 50 },
            { display: 'B', width: 50 },
        ]}
        data={[]}
    />
</Playground>


## CollapseTable
<Playground>
    <CollapseTable
            cols={[
              { display: '结算课程/服务', width: 20 },
              { display: '结算订单数', width: 10 },
              { display: '结算金额', width: 10 },
              { display: '操作', width: 10 },
            ]}
            data={[
              {
                row: ['2016-06-29结算查看明细', 2, '0.04元', <a>详情</a>],
                collapseRows: [
                  ['测试角标的课程', 1, '0.02元', <a>查看明细</a>],
                  ['雅思写作题', 1, '0.02元', <a>查看明细</a>],
                ],
              },
              {
                row: ['2016-05-29结算查看明细', 2, '3.09元', <a>详情</a>],
                collapseRows: [
                  ['支付43王萌勿删', 1, '1.02元', <a>查看明细</a>],
                  ['支付优惠卷测试啊', 1, '0.02元', <a>查看明细</a>],
                  ['课中包退啊', 1, '2.07元', <a>查看明细</a>],
                ],
              },
            ]}
          />
</Playground>

## TableSort
<Playground>
{() => {
    class Example extends React.Component{
        constructor(props){
            super(props);
            this.sortData = this.sortData.bind(this);
            this.state = {
            sortTableData: [
                [1, 9, 5],
                [5, 1, 4],
                [4, 4, 2],
                [7, 8, 6],
                [2, 7, 9],
            ],
            };
            this.sortTableQuery = {
            sort: '',
            order: '',
            };
        }
        render(){
            return <>
            <DataTable
            cols={[
              {
                display: <TableSort
                  options={[
                    { display: 'A', key: 'a' },
                    { display: 'B', key: 'b' }
                  ]}
                  onChange={sort => {
                    this.setState({
                      sortTableData: this.sortData(sort)
                    });
                  }}
                  active={this.sortTableQuery.sort === 'a' || this.sortTableQuery.sort === 'b'}
                  dropdownWidth={200}
                />, width: 50
              },
              {
                display: <TableSort
                  options={[
                    { display: 'C', key: 'c' },
                  ]}
                  onChange={sort => {
                    this.setState({
                      sortTableData: this.sortData(sort)
                    });
                  }}
                  active={this.sortTableQuery.sort === 'c'}
                />, width: 50
              },
            ]}
            data={this.state.sortTableData.map(row => [
              `A=${row[0]} B=${row[1]}`,
              row[2]
            ])}
          />
          <p>对字段进行排序使用TableSort组件传入cols属性</p>
            </>
        }
        sortData(sort) {
            this.sortTableQuery.sort = sort.sort;
            let sortTableData = [...this.state.sortTableData];
            sortTableData.sort((x, y) => {
            if (sort.sort === 'a') {
                return [x[0] - y[0]] * sort.order;
            } else if (sort.sort === 'b') {
                return [x[1] - y[1]] * sort.order;
            } else if (sort.sort === 'c') {
                return [x[2] - y[2]] * sort.order;
            }
            return 0;
            });
            return sortTableData;
        }
    }
    return <Example />
}
}
</Playground>

## AutoTable Basic Usage
<Playground>
{() => {
    class Example extends React.Component{
        constructor(props){
            super(props);
            this.state = {
                newPage: 0,
                prevPage: 0,
            };
            this.translateRow = this.translateRow.bind(this);
            this.fetch = this.fetch.bind(this)
        }
        fetch(query) {
            return new Promise((resolve) => {
            mockCGI(query).then(json => {
                let rows = json.data;
                let total = json.total;
                resolve({
                rows,
                total,
                });
            });
            });
        }
        translateRow(rowData) {
            return [
            rowData.A,
            rowData.B,
            // owner
            `${rowData.C}-${rowData.D}`,
            ];
        }
        render(){
            return <>
            <AutoTable
                maxRow={5}
                cols={[
                { display: 'A', width: 10 },
                { sort: [{ display: 'B', key: 'B', value: -1 }], width: 15 },
                { sort: [{ display: 'C', key: 'C', value: 1 }, { display: 'D', key: 'D' }], width: 8 },
                ]}
                fetch={this.fetch}
                translateRow={this.translateRow}
            />
            </>
        }
    }
    return <Example />
}
}
</Playground>

## AutoTable Persistence
<Playground>
{() => {
    class Example extends React.Component{
      constructor(props){
          super(props);
          this.state = {
              newPage: 0,
              prevPage: 0,
          };
          this.translateRow = this.translateRow.bind(this);
          this.fetch = this.fetch.bind(this);
      }
      fetch(query) {
          return new Promise((resolve) => {
          mockCGI(query).then(json => {
              let rows = json.data;
              let total = json.total;
              resolve({
              rows,
              total,
              });
          });
          });
      }
      translateRow(rowData) {
          return [
          rowData.A,
          rowData.B,
          // owner
          `${rowData.C}-${rowData.D}`,
          ];
      }
      render(){
          return <>
            <AutoTable
            maxRow={5}
            cols={[
              { display: 'A', width: 10 },
              { sort: [{ display: 'B', key: 'B', value: -1 }], width: 15 },
              { sort: [{ display: 'C', key: 'C', value: 1 }, { display: 'D', key: 'D' }], width: 8 },
            ]}
            fetch={this.fetch}
            translateRow={this.translateRow}
            persistence={{
              get: () => {
                  if(typeof window !== 'undefined' && window.localStorage){
                    return JSON.parse(window.localStorage.getItem('AutoTable-persistence'));
                  }
              },
              set: (state) => {
                  if(typeof window !== 'undefined' && window.localStorage){
                    localStorage.setItem('AutoTable-persistence', JSON.stringify(state));
                  }
              },
            }}
          />
          <p>AutoTable的state被持久化到了localStorage，先切换下页面，重新刷新页面可以看到这个AutoTable还是之前的样子</p>
        </>
      }
    }
    return <Example />
}
}
</Playground>

## AutoTable APIs
<Playground>
{() => {
    class Example extends React.Component{
        constructor(props){
            super(props);
            this.state = {
                newPage: 0,
                prevPage: 0,
            };
            this.translateRow = this.translateRow.bind(this);
            this.fetch = this.fetch.bind(this);
        }
        fetch(query) {
            return new Promise((resolve) => {
            mockCGI(query).then(json => {
                let rows = json.data;
                let total = json.total;
                resolve({
                rows,
                total,
                });
            });
            });
        }
        translateRow(rowData) {
            return [
            rowData.A,
            rowData.B,
            // owner
            `${rowData.C}-${rowData.D}`,
            ];
        }
        render(){
            return <>
            <AutoTable
                ref={t => this.autoTable = t}
                maxRow={5}
                cols={[
                { display: 'A', width: 10 },
                { sort: [{ display: 'B', key: 'B', value: -1 }], width: 15 },
                { sort: [{ display: 'C', key: 'C', value: 1 }, { display: 'D', key: 'D' }], width: 8 },
                ]}
                fetch={this.fetch}
                translateRow={this.translateRow}
                onPageChange={this.onPageChange}
            />
            <br />
            <Button onClick={() => {
                let page = Math.floor(Math.random() * 20);
                this.autoTable.goPage(page, false);
            }}>goPage</Button>
            <Button onClick={() => {
                let page = Math.floor(Math.random() * 20);
                this.autoTable.showPage(page, false);
            }}>showPage</Button>
            <Button onClick={() => {
                this.autoTable.reset([]);
            }}>reset</Button>
            <p>跳转到第page页, 如果没有第page页的数据会回调fetch去加载更多的数据, 从0开始计数</p>
            <p>跳转到第page页, 如果没有第page页的数据 不会 回调fetch去加载更多的数据, 业务侧自己保证第page页有数据</p>
            <p>每当表单的查询条件发生改变时请调reset方法重置AutoTable</p>
            </>
        }
    }
    return <Example />
}
}
</Playground>

## AutoTable Error Retry
<Playground>
{() => {
    class Example extends React.Component{
        constructor(props){
            super(props);
            this.state = {
                newPage: 0,
                prevPage: 0,
            };
            this.translateRow = this.translateRow.bind(this);
            this.fetch = this.fetch.bind(this);
            this.errorFetch = this.errorFetch.bind(this);
        }
        fetch(query) {
            return new Promise((resolve) => {
            mockCGI(query).then(json => {
                let rows = json.data;
                let total = json.total;
                resolve({
                rows,
                total,
                });
            });
            });
        }
        errorFetch() {
            return new Promise((_, reject) => {
            setTimeout(() => {
                reject(
                <div>
                    服务器发生错误
                    <Button size="s" onClick={() => {
                    this.autoErrorTable.reset();
                    }}>重试</Button>
                </div>
                );
            }, 1000);
            });
        }
        translateRow(rowData) {
            return [
            rowData.A,
            rowData.B,
            // owner
            `${rowData.C}-${rowData.D}`,
            ];
        }
        render(){
            return <>
            <AutoTable
                ref={t => this.autoErrorTable = t}
                maxRow={5}
                cols={[
                { display: 'A', width: 10 },
                { sort: [{ display: 'B', key: 'B', value: -1 }], width: 15 },
                { sort: [{ display: 'C', key: 'C', value: 1 }, { display: 'D', key: 'D' }], width: 8 },
                ]}
                fetch={this.errorFetch}
                translateRow={this.translateRow}
             />
            </>
        }
    }
    return <Example />
}
}
</Playground>

## AutoCollapseTable
<Playground>
{() => {
    class Example extends React.Component{
        constructor(props){
            super(props);
            this.fetch = this.fetch.bind(this);
            this.translateRow = this.translateRow.bind(this);
        }
        fetch(query) {
            return new Promise((resolve) => {
            mockCGI(query).then(json => {
                let rows = json.data;
                let total = json.total;
                resolve({
                rows,
                total,
                });
            });
            });
        }
        translateRow(rowData) {
            return {
            row: [
                rowData.A,
                rowData.B,
                // owner
                `${rowData.C}-${rowData.D}`,
            ],
            collapseRows: rowData.sub,
            };
        }
        render(){
            return <AutoCollapseTable
                maxRow={3}
                cols={[
                { display: 'A', width: 10 },
                { sort: [{ display: 'B', key: 'B', value: -1 }], width: 15 },
                { sort: [{ display: 'C', key: 'C', value: 1 }, { display: 'D', key: 'D' }], width: 8 },
                ]}
                fetch={this.fetch}
                translateRow={this.translateRow}
            />
        }
    }
    return <Example />
}}
</Playground>
