feat: 新增排序和全选高阶组件,并增加使用示例
This commit is contained in:
parent
d8343df513
commit
f8a00fe2e8
|
@ -0,0 +1,76 @@
|
|||
/**
|
||||
*
|
||||
* @title 全选功能
|
||||
* @description 全选功能
|
||||
*
|
||||
*/
|
||||
|
||||
import React, { Component } from "react";
|
||||
import Table from "../../src";
|
||||
import Checkbox from "bee-checkbox";
|
||||
import multiTable from "../../src/lib/multiSelectFunc.js";
|
||||
import sortTable from "../../src/lib/sortFunc.js";
|
||||
|
||||
const columns13 = [
|
||||
{
|
||||
title: "名字",
|
||||
dataIndex: "a",
|
||||
key: "a",
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
title: "性别",
|
||||
dataIndex: "b",
|
||||
key: "b",
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
title: "年龄",
|
||||
dataIndex: "c",
|
||||
key: "c",
|
||||
width: 200,
|
||||
sorter: (a, b) => a.c - b.c
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
dataIndex: "",
|
||||
key: "d",
|
||||
render() {
|
||||
return <a href="#">一些操作</a>;
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
const data13 = [
|
||||
{ a: "杨过", b: "男", c: 30, key: "2" },
|
||||
{ a: "令狐冲", b: "男", c: 41, key: "1" },
|
||||
{ a: "郭靖", b: "男", c: 25, key: "3" }
|
||||
];
|
||||
class Demo13 extends Component {
|
||||
getCheckedObj = () => {
|
||||
console.log(this.state);
|
||||
};
|
||||
setCheckedOjb = (data) =>{
|
||||
console.log(data)
|
||||
}
|
||||
render() {
|
||||
let multiObj = {
|
||||
type: "checkbox",
|
||||
param: "key"
|
||||
};
|
||||
let ComplexTable = multiTable(sortTable(Table));
|
||||
return (
|
||||
<div>
|
||||
<ComplexTable
|
||||
columns={columns13}
|
||||
data={data13}
|
||||
multiSelect={multiObj}
|
||||
prefixCls="bee-table"
|
||||
getSelectedDataFunc={this.setCheckedOjb}
|
||||
/>
|
||||
<button onClick={this.getCheckedObj}>xxxx</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
export default Demo13;
|
|
@ -5,180 +5,200 @@
|
|||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
import Button from 'bee-button';
|
||||
import React, { Component } from 'react';
|
||||
import Table from '../../src';
|
||||
import Animate from 'bee-animate';
|
||||
import Button from "bee-button";
|
||||
import React, { Component } from "react";
|
||||
import Table from "../../src";
|
||||
import Animate from "bee-animate";
|
||||
import Icon from "bee-icon";
|
||||
import Input from 'bee-form-control';
|
||||
import Popconfirm from 'bee-popconfirm';
|
||||
import Input from "bee-form-control";
|
||||
import Popconfirm from "bee-popconfirm";
|
||||
|
||||
class EditableCell extends React.Component {
|
||||
state = {
|
||||
value: this.props.value,
|
||||
editable: false,
|
||||
}
|
||||
handleChange = (e) => {
|
||||
editable: false
|
||||
};
|
||||
handleChange = e => {
|
||||
const value = e.target.value;
|
||||
this.setState({ value });
|
||||
}
|
||||
};
|
||||
check = () => {
|
||||
this.setState({ editable: false });
|
||||
if (this.props.onChange) {
|
||||
this.props.onChange(this.state.value);
|
||||
}
|
||||
}
|
||||
};
|
||||
edit = () => {
|
||||
this.setState({ editable: true });
|
||||
}
|
||||
handleKeydown = (event) => {
|
||||
console.log(event.keyCode);
|
||||
if(event.keyCode == 13){
|
||||
this.check();
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
handleKeydown = event => {
|
||||
console.log(event.keyCode);
|
||||
if (event.keyCode == 13) {
|
||||
this.check();
|
||||
}
|
||||
};
|
||||
render() {
|
||||
const { value, editable } = this.state;
|
||||
return (<div className="editable-cell">
|
||||
{
|
||||
editable ?
|
||||
<div className="editable-cell-input-wrapper">
|
||||
<Input
|
||||
value={value}
|
||||
onChange={this.handleChange}
|
||||
onKeyDown = {this.handleKeydown}
|
||||
/>
|
||||
<Icon
|
||||
type="uf-correct"
|
||||
className="editable-cell-icon-check"
|
||||
onClick={this.check}
|
||||
/>
|
||||
</div>
|
||||
:
|
||||
<div className="editable-cell-text-wrapper">
|
||||
{value || ' '}
|
||||
<Icon
|
||||
type="uf-pencil"
|
||||
className="editable-cell-icon"
|
||||
onClick={this.edit}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
</div>);
|
||||
return (
|
||||
<div className="editable-cell">
|
||||
{editable ? (
|
||||
<div className="editable-cell-input-wrapper">
|
||||
<Input
|
||||
value={value}
|
||||
onChange={this.handleChange}
|
||||
onKeyDown={this.handleKeydown}
|
||||
/>
|
||||
<Icon
|
||||
type="uf-correct"
|
||||
className="editable-cell-icon-check"
|
||||
onClick={this.check}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="editable-cell-text-wrapper">
|
||||
{value || " "}
|
||||
<Icon
|
||||
type="uf-pencil"
|
||||
className="editable-cell-icon"
|
||||
onClick={this.edit}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Demo2 extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.columns = [{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
key:'name',
|
||||
width: '30%',
|
||||
render: (text, record, index) => (
|
||||
<EditableCell
|
||||
value={text}
|
||||
onChange={this.onCellChange(index, 'name')}
|
||||
/>
|
||||
),
|
||||
}, {
|
||||
title: '年龄',
|
||||
dataIndex: 'age',
|
||||
key:'age',
|
||||
}, {
|
||||
title: '你懂的',
|
||||
dataIndex: 'address',
|
||||
key:'address',
|
||||
}, {
|
||||
title: '操作',
|
||||
dataIndex: 'operation',
|
||||
key: 'operation',
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
this.state.dataSource.length > 1 ?
|
||||
(
|
||||
<Popconfirm content="确认删除?" id='aa' onClose={this.onDelete(index)}>
|
||||
<Icon type="uf-del"></Icon>
|
||||
</Popconfirm>
|
||||
) : null
|
||||
);
|
||||
this.columns = [
|
||||
{
|
||||
title: "姓名",
|
||||
dataIndex: "name",
|
||||
key: "name",
|
||||
width: "30%",
|
||||
render: (text, record, index) => (
|
||||
<EditableCell
|
||||
value={text}
|
||||
onChange={this.onCellChange(index, "name")}
|
||||
/>
|
||||
)
|
||||
},
|
||||
}];
|
||||
{
|
||||
title: "年龄",
|
||||
dataIndex: "age",
|
||||
key: "age"
|
||||
},
|
||||
{
|
||||
title: "你懂的",
|
||||
dataIndex: "address",
|
||||
key: "address"
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
dataIndex: "operation",
|
||||
key: "operation",
|
||||
render: (text, record, index) => {
|
||||
return this.state.dataSource.length > 1 ? (
|
||||
<Popconfirm content="确认删除?" id="aa" onClose={this.onDelete(index)}>
|
||||
<Icon type="uf-del" />
|
||||
</Popconfirm>
|
||||
) : null;
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
this.state = {
|
||||
dataSource: [{
|
||||
key: '0',
|
||||
name: '沉鱼',
|
||||
age: '18',
|
||||
address: '96, 77, 89',
|
||||
}, {
|
||||
key: '1',
|
||||
name: '落雁',
|
||||
age: '16',
|
||||
address: '90, 70, 80',
|
||||
}, {
|
||||
key: '2',
|
||||
name: '闭月',
|
||||
age: '17',
|
||||
address: '80, 60, 80',
|
||||
}, {
|
||||
key: '3',
|
||||
name: '羞花',
|
||||
age: '20',
|
||||
address: '120, 60, 90',
|
||||
}],
|
||||
count: 4,
|
||||
dataSource: [
|
||||
{
|
||||
key: "0",
|
||||
name: "沉鱼",
|
||||
age: "18",
|
||||
address: "96, 77, 89"
|
||||
},
|
||||
{
|
||||
key: "1",
|
||||
name: "落雁",
|
||||
age: "16",
|
||||
address: "90, 70, 80"
|
||||
},
|
||||
{
|
||||
key: "2",
|
||||
name: "闭月",
|
||||
age: "17",
|
||||
address: "80, 60, 80"
|
||||
},
|
||||
{
|
||||
key: "3",
|
||||
name: "羞花",
|
||||
age: "20",
|
||||
address: "120, 60, 90"
|
||||
}
|
||||
],
|
||||
count: 4
|
||||
};
|
||||
}
|
||||
onCellChange = (index, key) => {
|
||||
return (value) => {
|
||||
return value => {
|
||||
const dataSource = [...this.state.dataSource];
|
||||
dataSource[index][key] = value;
|
||||
this.setState({ dataSource });
|
||||
};
|
||||
}
|
||||
onDelete = (index) => {
|
||||
};
|
||||
onDelete = index => {
|
||||
return () => {
|
||||
const dataSource = [...this.state.dataSource];
|
||||
dataSource.splice(index, 1);
|
||||
this.setState({ dataSource });
|
||||
};
|
||||
}
|
||||
};
|
||||
handleAdd = () => {
|
||||
const { count, dataSource } = this.state;
|
||||
const newData = {
|
||||
key: count,
|
||||
name: `凤姐 ${count}`,
|
||||
age: 32,
|
||||
address: `100 100 100`,
|
||||
address: `100 100 100`
|
||||
};
|
||||
this.setState({
|
||||
dataSource: [...dataSource, newData],
|
||||
count: count + 1,
|
||||
count: count + 1
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
getBodyWrapper = (body) => {
|
||||
getBodyWrapper = body => {
|
||||
return (
|
||||
<Animate transitionName="move" component="tbody" className={body.props.className}>
|
||||
<Animate
|
||||
transitionName="move"
|
||||
component="tbody"
|
||||
className={body.props.className}
|
||||
>
|
||||
{body.props.children}
|
||||
</Animate>
|
||||
);
|
||||
}
|
||||
};
|
||||
render() {
|
||||
const { dataSource } = this.state;
|
||||
const columns = this.columns;
|
||||
return (<div>
|
||||
<Button className="editable-add-btn" type="ghost" onClick={this.handleAdd}>添加</Button>
|
||||
<Table bordered data={dataSource} columns={columns} getBodyWrapper={this.getBodyWrapper} />
|
||||
</div>);
|
||||
return (
|
||||
<div>
|
||||
<Button
|
||||
className="editable-add-btn"
|
||||
type="ghost"
|
||||
onClick={this.handleAdd}
|
||||
>
|
||||
添加
|
||||
</Button>
|
||||
<Table
|
||||
bordered
|
||||
data={dataSource}
|
||||
columns={columns}
|
||||
getBodyWrapper={this.getBodyWrapper}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Demo2;
|
||||
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,149 @@
|
|||
import React, { Component } from "react";
|
||||
import Checkbox from "bee-checkbox";
|
||||
/**
|
||||
* multiSelect={
|
||||
* type--默认值为checkbox
|
||||
* param--可以设置返回的选中的数据属性;默认值:null;
|
||||
* }
|
||||
* getSelectedDataFunc--function,能获取到选中的数据
|
||||
* 使用全选时得注意,data中的key值一定要是唯一值
|
||||
*/
|
||||
module.exports = function multiTable(Table) {
|
||||
Array.prototype.indexOf = function(val) {
|
||||
for (var i = 0; i < this.length; i++) {
|
||||
if (this[i] == val) return i;
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
Array.prototype.remove = function(val) {
|
||||
var index = this.indexOf(val);
|
||||
if (index > -1) {
|
||||
this.splice(index, 1);
|
||||
}
|
||||
};
|
||||
return class BookLoader extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
checkedAll: false,
|
||||
checkedObj: {},
|
||||
selIds: [],
|
||||
data: this.props.data
|
||||
};
|
||||
}
|
||||
onAllCheckChange = () => {
|
||||
let self = this;
|
||||
let listData = self.state.data.concat();
|
||||
let checkedObj = Object.assign({}, self.state.checkedObj);
|
||||
let data = self.props.data;
|
||||
let selIds = [];
|
||||
let id = self.props.multiSelect.param;
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
checkedObj[data[i]["key"]] = !self.state.checkedAll;
|
||||
}
|
||||
if (self.state.checkedAll) {
|
||||
selIds = [];
|
||||
} else {
|
||||
for (var i = 0; i < listData.length; i++) {
|
||||
if (id) {
|
||||
selIds[i] = listData[i][id];
|
||||
} else {
|
||||
selIds[i] = listData[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
self.setState({
|
||||
checkedAll: !self.state.checkedAll,
|
||||
checkedObj: checkedObj,
|
||||
selIds: selIds
|
||||
});
|
||||
self.props.getSelectedDataFunc(selIds);
|
||||
};
|
||||
onCheckboxChange = (text, record, index) => {
|
||||
let self = this;
|
||||
let allFlag = false;
|
||||
let selIds = self.state.selIds;
|
||||
let id = self.props.multiSelect.param
|
||||
? record[self.props.multiSelect.param]
|
||||
: record;
|
||||
let checkedObj = Object.assign({}, self.state.checkedObj);
|
||||
let checkedArray = Object.keys(checkedObj);
|
||||
if (checkedObj[record["key"]]) {
|
||||
selIds.remove(id);
|
||||
} else {
|
||||
selIds.push(id);
|
||||
}
|
||||
checkedObj[record["key"]] = !checkedObj[record["key"]];
|
||||
for (var i = 0; i < checkedArray.length; i++) {
|
||||
if (!checkedObj[checkedArray[i]]) {
|
||||
allFlag = false;
|
||||
break;
|
||||
} else {
|
||||
allFlag = true;
|
||||
}
|
||||
}
|
||||
self.setState({
|
||||
checkedAll: allFlag,
|
||||
checkedObj: checkedObj,
|
||||
selIds: selIds
|
||||
});
|
||||
self.props.getSelectedDataFunc(selIds);
|
||||
};
|
||||
renderColumnsMultiSelect(columns) {
|
||||
const { data } = this.state;
|
||||
let checkedObj = Object.assign({}, this.state.checkedObj);
|
||||
let checkedArray = Object.keys(checkedObj);
|
||||
let { multiSelect } = this.props;
|
||||
let select_column = {};
|
||||
let indeterminate_bool = false;
|
||||
if (!multiSelect || !multiSelect.type) {
|
||||
multiSelect = Object.assign({}, multiSelect, { type: "checkbox" });
|
||||
}
|
||||
if (multiSelect && multiSelect.type === "checkbox") {
|
||||
let i = checkedArray.length;
|
||||
while (i--) {
|
||||
if (checkedObj[checkedArray[i]]) {
|
||||
indeterminate_bool = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
let defaultColumns = [
|
||||
{
|
||||
title: (
|
||||
<Checkbox
|
||||
className="table-checkbox"
|
||||
checked={this.state.checkedAll}
|
||||
indeterminate={indeterminate_bool && !this.state.checkedAll}
|
||||
onChange={this.onAllCheckChange}
|
||||
/>
|
||||
),
|
||||
key: "checkbox",
|
||||
dataIndex: "checkbox",
|
||||
width: "5%",
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Checkbox
|
||||
className="table-checkbox"
|
||||
checked={checkedObj[record.key]}
|
||||
onChange={this.onCheckboxChange.bind(
|
||||
this,
|
||||
text,
|
||||
record,
|
||||
index
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
];
|
||||
columns = defaultColumns.concat(columns);
|
||||
}
|
||||
return columns;
|
||||
}
|
||||
render() {
|
||||
let { data } = this.props;
|
||||
let columns = this.renderColumnsMultiSelect(this.props.columns).concat();
|
||||
return <Table {...this.props} columns={columns} data={data} />;
|
||||
}
|
||||
};
|
||||
};
|
|
@ -0,0 +1,100 @@
|
|||
|
||||
import React, { Component } from 'react';
|
||||
import Icon from 'bee-icon';
|
||||
|
||||
/**
|
||||
* 参数:prefixCls,默认bee-table,用于设置图标的样式
|
||||
* @param {*} Table
|
||||
*/
|
||||
export default function sortTable(Table) {
|
||||
return class Demo11 extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
sortOrder: "",
|
||||
data: this.props.data
|
||||
};
|
||||
}
|
||||
toggleSortOrder = (order, column) => {
|
||||
let { sortOrder, data, oldData } = this.state;
|
||||
let ascend_sort = function (key) {
|
||||
return function (a, b) {
|
||||
return a.key - b.key;
|
||||
};
|
||||
};
|
||||
let descend_sort = function (key) {
|
||||
return function (a, b) {
|
||||
return b.key - a.key;
|
||||
};
|
||||
};
|
||||
if (sortOrder === order) {
|
||||
// 切换为未排序状态
|
||||
order = "";
|
||||
}
|
||||
if (!oldData) {
|
||||
oldData = data.concat();
|
||||
}
|
||||
if (order === "ascend") {
|
||||
data = data.sort(function (a, b) {
|
||||
return column.sorter(a, b);
|
||||
});
|
||||
} else if (order === "descend") {
|
||||
data = data.sort(function (a, b) {
|
||||
return column.sorter(b, a);
|
||||
});
|
||||
} else {
|
||||
data = oldData.concat();
|
||||
}
|
||||
this.setState({
|
||||
sortOrder: order,
|
||||
data: data,
|
||||
oldData: oldData
|
||||
});
|
||||
}
|
||||
renderColumnsDropdown(columns) {
|
||||
const { sortOrder } = this.state;
|
||||
const prefixCls = this.props.prefixCls || 'bee-table';
|
||||
return columns.map(originColumn => {
|
||||
let column = Object.assign({}, originColumn);
|
||||
let sortButton;
|
||||
if (column.sorter) {
|
||||
const isAscend = sortOrder === "ascend";
|
||||
const isDescend = sortOrder === "descend";
|
||||
sortButton = (
|
||||
<div className={`${prefixCls}-column-sorter`}>
|
||||
<span
|
||||
className={`${prefixCls}-column-sorter-up ${isAscend
|
||||
? "on"
|
||||
: "off"}`}
|
||||
title="↑"
|
||||
onClick={() => this.toggleSortOrder("ascend", column)}
|
||||
>
|
||||
<Icon type="uf-triangle-up" />
|
||||
</span>
|
||||
<span
|
||||
className={`${prefixCls}-column-sorter-down ${isDescend
|
||||
? "on"
|
||||
: "off"}`}
|
||||
title="↓"
|
||||
onClick={() => this.toggleSortOrder("descend", column)}
|
||||
>
|
||||
<Icon type="uf-triangle-down" />
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
column.title = (
|
||||
<span>
|
||||
{column.title}
|
||||
{sortButton}
|
||||
</span>
|
||||
);
|
||||
return column;
|
||||
});
|
||||
}
|
||||
render() {
|
||||
let columns = this.renderColumnsDropdown(this.props.columns).concat();
|
||||
return <Table{...this.props} columns={columns} data={this.state.data}/>;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue