import * as React from "react"; import { TableProps, IColDef } from "."; import { some, debounce } from "lodash"; interface IState { filter: any; showSubComponent: object; } export class TablePlain extends React.Component { state = { filter: {}, showSubComponent: {} }; get rootElement() { return this.props.rootElement || "table"; } get rowElement() { return this.props.rowElement || "tr"; } get cellElement() { return this.props.cellElement || "td"; } get headerCellElement() { return this.props.headerCellElement || "th"; } get headerElement() { return this.props.headerElement || "thead"; } get bodyElement() { return this.props.bodyElement || "tbody"; } get footerElement() { return this.props.footerElement || "tfoot"; } get hasFooter() { return some(this.props.colDef, def => def.footer != null); } get isFilterable() { return some(this.props.colDef, def => def.filterable === true); } componentWillMount() { for (const plugin of this.props.plugins || []) { if (plugin != null) { plugin.init(this.props.colDef!); } } } render() { const { data } = this.props; const colDef = this.props.colDef || this.generateColDef(data); if (data != null) { const Root: any = this.rootElement; return ( {this.renderHeader(colDef)} {this.renderData(colDef, data)} {this.hasFooter && this.renderFooter(colDef, data)} ); } return null; } renderData(colDef: IColDef[], data: any[]) { const Body: any = this.bodyElement; return ( {data && data.map((d, idx) => this.renderRow(colDef, d, idx))} ); } renderRow(colDef: IColDef[], data: any, key: number) { const Row: any = this.rowElement; const Cell: any = this.cellElement; const renderIndicator = this.props.renderExpansionIndicator || this.renderExpansionIndicator; const result = [ this.props.onRowClick && this.props.onRowClick(data)} > {this.props.subComponent && this.renderCell( { header: "", prop: "", props: () => ({ onClick: (e: React.MouseEvent) => this.handleExpansionClick(e, key) }), render: () => renderIndicator(this.state.showSubComponent[key] === true) }, data, -1, { width: "1%", style: { paddingRight: 0 } } )} {colDef.map((def, idx) => this.renderCell(def, data, idx))} ]; if (this.props.subComponent && this.state.showSubComponent[key]) { result.push( {this.props.subComponent(data)} ); } return result; } renderCell(colDef: IColDef, data: any, idx: number, props?: object) { const Cell: any = this.cellElement; const ps = colDef.props != null ? { ...props, ...colDef.props(data) } : props; if (colDef.render != null) { return ( {colDef.render(data)} ); } const val = colDef.accessor != null ? colDef.accessor(data) : data[colDef.prop]; return ( {val} ); } renderHeader(colDef: IColDef[]) { const Header: any = this.headerElement; const Row: any = this.rowElement; const Cell: any = this.cellElement; const render = this.props.renderHeaderCell != null ? this.props.renderHeaderCell.bind(this) : this.renderHeaderCell.bind(this); return (
{this.props.subComponent && render({ prop: "", header: "" }, -1, { width: "1%", style: { paddingRight: 0 } })} {colDef.map(render)} {this.isFilterable && ( {colDef.map((def, idx) => ( {def.filterable ? this.props.renderFilter != null ? this.props.renderFilter(def, idx) : this.renderFilter(def, idx) : null} ))} )}
); } renderHeaderCell(colDef: IColDef, idx: number, props?: object) { const HeaderCell: any = this.headerCellElement; return ( colDef.sortable && this.handleChangeSort(colDef)} {...props} > {colDef.header} {this.props.orderedBy === colDef && this.props.renderSortLabel && this.props.renderSortLabel(colDef, this.props.desc)} ); } renderFilter(colDef: IColDef, idx: number) { return ( this.handleFilterChange(colDef, e.target.value)} /> ); } renderFooter(colDef: IColDef[], data: any[]) { const Footer: any = this.footerElement; const Row: any = this.rowElement; return ( ); } renderFooterCell(colDef: IColDef, data: any[], idx: number) { const FooterCell: any = this.cellElement; return ( {colDef.footer != null ? typeof colDef.footer === "string" ? colDef.footer : colDef.footer!(colDef, data) : null} ); } renderExpansionIndicator(expanded: boolean) { const rot = expanded ? -90 : 90; return (
>
); } generateColDef(data: any[]): IColDef[] { return []; } handleChangeSort = (colDef: IColDef) => { if (this.props.onChangeOrderBy) { this.props.onChangeOrderBy(colDef); } }; handleFilterChange = (colDef: IColDef, value: any) => { const name = colDef.prop; this.setState( p => ({ filter: { ...p.filter, [name]: value } }), debounce(() => { if (this.props.onChangeFilter) { this.props.onChangeFilter(colDef, value); } }, 500) ); }; handleExpansionClick = (e: React.MouseEvent, key: number) => { e.stopPropagation(); this.toggleSubmenu(key); }; private toggleSubmenu = (key: number) => { this.setState(prev => ({ showSubComponent: { ...prev.showSubComponent, [key]: prev.showSubComponent[key] ? false : true } })); }; }