diff --git a/README.md b/README.md
index 9e3545d..d5adeb3 100644
--- a/README.md
+++ b/README.md
@@ -46,6 +46,8 @@ $ npm start
* addEmptyRowFromTop(): 从顶部添加一个空的新行。
* addRow(rowData): 以指定数据添加一个新行。
* addRowFromTop(rowData): 以指定数据从顶部添加一个新行。
+* addSubRow(rowData, jsxid, cb): 树形表格模式下从底部插入一个子树节点行
+* addSubRomFromTop(rowData, jsxid, cb): 树形表格模式下从顶部插入一个子树节点行
* delRow(rowData): 删除一个新行。
* editRow(rowData): 使指定的行切换到编辑模式。
* editAllRow(): 使所有行切换到编辑模式。
diff --git a/demo/TreeGridDemo.jsx b/demo/TreeGridDemo.jsx
index 6104ae1..5a029f8 100644
--- a/demo/TreeGridDemo.jsx
+++ b/demo/TreeGridDemo.jsx
@@ -8,97 +8,257 @@
import React from 'react';
import Table from '../src';
+import Constants from 'uxcore-const';
+
import NattyFetch from 'natty-fetch';
const urlPrefix = window.urlPrefix || 'http://30.9.174.1:3000/';
function loadTreeData(rowData) {
- const request = NattyFetch.create({
- method: 'GET',
- url: `${urlPrefix}demo/rowData.json`,
- data: '',
- Promise,
- });
- return request();
+ // const request = NattyFetch.create({
+ // method: 'GET',
+ // url: `${urlPrefix}demo/rowData.json`,
+ // data: '',
+ // Promise,
+ // });
+ // return request();
+ return new Promise(resolve => {
+ setTimeout(() => {
+ resolve({
+ data: [
+ {
+ "id": `${setTimeout(0)}`,
+ "radio": true,
+ "grade": "2grade2",
+ "email": "2email2",
+ "firstName": "2firstName2",
+ "lastName": "2lastName2",
+ "birthDate": "2birthDate2",
+ "country": "2country2",
+ "city": "2city2",
+ "data": []
+ },
+ {
+ "id": `${setTimeout(0)}`,
+ "check": true,
+ "grade": "2grade3",
+ "email": "2email3",
+ "firstName": "2firstName3",
+ "lastName": "2lastName3",
+ "birthDate": "2birthDate3",
+ "country": "2country3",
+ "city": "2city3"
+ }
+ ]
+ })
+ }, 500)
+ })
}
class Demo extends React.Component {
constructor(props) {
super(props);
this.state = {
+ columns: [
+ {
+ dataKey: 'country',
+ title: '国家',
+ width: '200px',
+ ordered: true,
+ align: 'left',
+ type: 'money',
+ delimiter: ',',
+ fixed: true,
+ },
+ {
+ dataKey: 'city',
+ title: '城市',
+ width: '150px',
+ },
+ {
+ dataKey: 'firstName',
+ title: 'FristName',
+ },
+ {
+ dataKey: 'lastName',
+ title: 'LastName',
+ },
+ {
+ dataKey: 'email',
+ title: 'Email',
+ width: '200px',
+ ordered: true,
+ },
+ {
+ title: '操作',
+ type: 'action',
+ rightFixed: true,
+ width: '300px',
+ collapseNum: 5,
+ actions: [
+ {
+ title: '新增',
+ callback: (rowData) => {
+ this.table.addSubRow({
+ "id": `${setTimeout(0)}`,
+ "check": true,
+ "grade": "2grade3",
+ "email": "2email",
+ "firstName": "2firstName3",
+ "lastName": "2lastName3",
+ "birthDate": "2birthDate3",
+ "country": `country_${setTimeout(0)}`,
+ "city": "2city3"
+ }, rowData.jsxid, () => {
+ console.log(this.table.getData())
+ })
+ }
+ },
+ {
+ title: '上移',
+ callback: (rowData) => {
+ this.table.moveRowUp(rowData);
+ },
+ },
+ {
+ title: '删除',
+ callback: (rowData) => {
+ this.table.delRow(rowData);
+ },
+ },
+ {
+ title: '下移',
+ callback: (rowData) => { this.table.moveRowDown(rowData); },
+ },
+ ],
+ },
+ ]
};
}
-
render() {
- const columns = [
- {
- dataKey: 'id',
- title: 'ID',
- width: '50px',
- hidden: true,
- },
- {
- dataKey: 'country',
- title: '国家',
- width: '200px',
- ordered: true,
- align: 'left',
- type: 'money',
- // fixed: true,
- delimiter: ',',
- },
- {
- dataKey: 'city',
- title: '城市',
- width: '150px',
- },
- {
- dataKey: 'firstName',
- title: 'FristName',
- },
- {
- dataKey: 'lastName',
- title: 'LastName',
- },
- {
- dataKey: 'email',
- title: 'Email',
- width: '200px',
- ordered: true,
- },
- {
- title: '操作',
- type: 'action',
- width: '200px',
- actions: [
- {
- title: '上移',
- callback: (rowData) => {
- this.table.moveRowUp(rowData);
- },
- },
- {
- title: '删除',
- callback: (rowData) => {
- this.table.delRow(rowData);
- },
- },
- {
- title: '下移',
- callback: (rowData) => { this.table.moveRowDown(rowData); },
- },
- ],
- },
- ];
-
const renderProps = {
- height: '400px',
+ height: '600px',
width: '1000px',
showSearch: true,
levels: 0,
fetchUrl: `${urlPrefix}demo/data.json`,
loadTreeData,
- jsxcolumns: columns,
+ processData(data) {
+ data.data.map(item => {
+ item.data = []
+ });
+ return data
+ },
+ useListActionBar: true,
+ showColumnPickerCheckAll: true,
+ showColumnPicker: true,
+ actionBar: {
+ columnsOrder: {
+ iconName: 'huxiangguanzhu',
+ // keepActiveInCustomView: true,
+ title: '列排序',
+ includeActionColumn: false, // 优先级低于fixed和rightFixed
+ onChange(dragInfo, data) {
+ console.log(data)
+ }
+ },
+ buttons: [
+ {
+ title: '新增一行',
+ callback: () => {
+ this.table.addRowFromTop(
+ {
+ "id": `${setTimeout(0)}`,
+ "check": true,
+ "grade": "2grade3",
+ "email": "2email",
+ "firstName": "2firstName3",
+ "lastName": "2lastName3",
+ "birthDate": "2birthDate3",
+ "country": `country_${setTimeout(0)}`,
+ "city": "2city3"
+ }
+ )
+ }
+ },
+ {
+ title: '变更columns',
+ callback: () => {
+ this.setState({
+ columns: [
+ {
+ dataKey: 'id',
+ title: 'ID',
+ width: '50px',
+ hidden: true,
+ },
+ {
+ dataKey: 'country',
+ title: '国家',
+ width: '200px',
+ ordered: true,
+ align: 'left',
+ type: 'money',
+ delimiter: ',',
+ },
+ {
+ title: '操作',
+ type: 'action',
+ width: '300px',
+ collapseNum: 5,
+ actions: [
+ {
+ title: '新增',
+ callback: (rowData) => {
+ this.table.addSubRow({
+ "id": `${setTimeout(0)}`,
+ "check": true,
+ "grade": "2grade3",
+ "email": "2email",
+ "firstName": "2firstName3",
+ "lastName": "2lastName3",
+ "birthDate": "2birthDate3",
+ "country": `country_${setTimeout(0)}`,
+ "city": "2city3"
+ }, rowData.jsxid, () => {
+ console.log(this.table.getData())
+ })
+ }
+ },
+ {
+ title: '上移',
+ callback: (rowData) => {
+ this.table.moveRowUp(rowData);
+ },
+ },
+ {
+ title: '编辑',
+ callback: (rowData) => {
+ this.table.editRow(rowData);
+ },
+ mode: Constants.MODE.VIEW,
+ },
+ {
+ title: '删除',
+ callback: (rowData) => {
+ this.table.delRow(rowData);
+ },
+ },
+ {
+ title: '下移',
+ callback: (rowData) => { this.table.moveRowDown(rowData); },
+ },
+ ],
+ },
+ ]
+ }, () => {
+ this.table.checkRightFixed(true)
+ })
+ }
+ }
+ ]
+ },
+ jsxcolumns: this.state.columns,
renderModel: 'tree',
toggleTreeExpandOnRowClick: true,
rowSelection: {
@@ -111,7 +271,7 @@ class Demo extends React.Component {
this.table = c;
},
};
- return (
);
+ return ( {this.table = c}} {...renderProps} className={'kuma-uxtable-border-line'} />);
}
}
diff --git a/demo/index.jsx b/demo/index.jsx
index e440879..80f5d2a 100644
--- a/demo/index.jsx
+++ b/demo/index.jsx
@@ -17,9 +17,9 @@ import Demo5 from './TableGroup';
import Demo6 from './TableRowGroup';
import '../style';
-ReactDOM.render(, document.getElementById('UXCoreDemo'));
+// ReactDOM.render(, document.getElementById('UXCoreDemo'));
// ReactDOM.render(, document.getElementById('UXCoreDemo2'));
-// ReactDOM.render(, document.getElementById('UXCoreDemo3'));
+ReactDOM.render(, document.getElementById('UXCoreDemo3'));
// ReactDOM.render(, document.getElementById('UXCoreDemo4'));
// ReactDOM.render(, document.getElementById('UXCoreDemo5'));
// ReactDOM.render(, document.getElementById('UXCoreDemo6'));
diff --git a/doc/README_EN.md b/doc/README_EN.md
index cfe5fda..83bc2da 100644
--- a/doc/README_EN.md
+++ b/doc/README_EN.md
@@ -213,6 +213,10 @@ let columns = [
## API
+* addSubRow(rowData, jsxid, cb): add an sub row with specified data in tree table from bottom
+* addSubRowFromTop(rowData, jsxid, cb): add an sub row with specified data in tree table from top
+
+
### Row Editing
* getData(): return cellData & do Validation
diff --git a/src/ActionBar/ColumnOrder.jsx b/src/ActionBar/ColumnOrder.jsx
index ff851fb..ba4c5ea 100644
--- a/src/ActionBar/ColumnOrder.jsx
+++ b/src/ActionBar/ColumnOrder.jsx
@@ -23,13 +23,13 @@ class ColumnOrder extends React.Component {
this.state = {
value: props.defaultValue,
preColumns: props.columns,
- checkAbleColumns: getColumnsInfo(props.columns, props.includeActionColumn),
+ checkAbleColumns: getColumnsInfo(props.columns, props.includeActionColumn, true),
}
}
static getDerivedStateFromProps = (props, state) => {
if (props.columns !== state.preColumns) {
return {
- checkAbleColumns: getColumnsInfo(props.columns, props.includeActionColumn),
+ checkAbleColumns: getColumnsInfo(props.columns, props.includeActionColumn, true),
preColumns: props.columns
};
}
@@ -76,7 +76,8 @@ class ColumnOrder extends React.Component {
}
render() {
const p = this.props;
- const disabled = !p.keepActiveInCustomView && !p.isTableView
+ const { checkAbleColumns } = this.state;
+ const disabled = !p.keepActiveInCustomView && !p.isTableView || !checkAbleColumns.columns.length;
return (
}
diff --git a/src/ActionBar/ColumnPickerNew.jsx b/src/ActionBar/ColumnPickerNew.jsx
index 430710e..dbb7638 100644
--- a/src/ActionBar/ColumnPickerNew.jsx
+++ b/src/ActionBar/ColumnPickerNew.jsx
@@ -300,7 +300,8 @@ class ColumnPicker extends React.Component {
renderListActionBar() {
const me = this;
const p = me.props;
- const disabled = !p.keepActiveInCustomView && !p.isTableView;
+ const { columnsInfo } = this.state
+ const disabled = !p.keepActiveInCustomView && !p.isTableView || !columnsInfo.columns.length
return (
{me.renderIndent()}
diff --git a/src/innerMethods.js b/src/innerMethods.js
index ba56de2..02fce36 100644
--- a/src/innerMethods.js
+++ b/src/innerMethods.js
@@ -58,7 +58,7 @@ function addValuesInData(objAux, operation) {
* @param objAux {Array or Object} datum or data need to be inserted
*/
-function insertRecords(obj, reverse, cb) {
+function insertRecords(obj, reverse, cb, targetJsxId) {
if (typeof obj !== 'object') return;
const me = this;
let objAux = deepcopy(obj);
@@ -66,11 +66,16 @@ function insertRecords(obj, reverse, cb) {
objAux = [objAux];
}
objAux = me.addJSXIdsForRecord(objAux);
- const content = util.mergeData(me.state.data, objAux, reverse);
- updateTreeId(content.data);
- me.data = content;
+ const { data, expandedKey } = util.mergeData(me.state.data, objAux, reverse, targetJsxId);
+ updateTreeId(data.data);
+ me.data = data;
+ let expandedKeys = [...this.state.expandedKeys];
+ if (expandedKey >= 0) {
+ expandedKeys.push(expandedKey)
+ }
me.setState({
- data: content,
+ data: data,
+ expandedKeys
}, () => {
if (cb) {
cb();
diff --git a/src/methods.js b/src/methods.js
index c47e980..badbe65 100644
--- a/src/methods.js
+++ b/src/methods.js
@@ -18,6 +18,18 @@ function addRowFromTop(rowData, cb) {
this.insertRecords(rowData, true, cb);
}
+function addSubRow(rowData, jsxid, cb) {
+ if (jsxid >= 0 && this.props.renderModel === 'tree') {
+ this.insertRecords(rowData, false, cb, jsxid)
+ }
+}
+
+function addSubRowFromTop(rowData, jsxid, cb) {
+ if (jsxid >= 0 && this.props.renderModel === 'tree') {
+ this.insertRecords(rowData, true, cb, jsxid)
+ }
+}
+
function resetRow(rowData, cb) {
const me = this;
let updateData = {};
@@ -321,6 +333,8 @@ export default {
addEmptyRowFromTop,
addRow,
addRowFromTop,
+ addSubRow,
+ addSubRowFromTop,
resetRow,
resetAllRow,
delRow,
diff --git a/src/style/ActionBar.less b/src/style/ActionBar.less
index ce9471f..3c555c2 100644
--- a/src/style/ActionBar.less
+++ b/src/style/ActionBar.less
@@ -146,6 +146,9 @@
line-height: 32px;
margin-right: 20px;
position: relative;
+ &:first-child {
+ margin-right: 2px;
+ }
}
.order-title,
.column-order-title,
diff --git a/src/style/Main.less b/src/style/Main.less
index e74d8bb..7617866 100644
--- a/src/style/Main.less
+++ b/src/style/Main.less
@@ -182,6 +182,7 @@
display: inline-block;
text-align: left;
overflow: hidden;
+ text-overflow: ellipsis;
height: 100%;
padding: 0 20px 0 20px;
vertical-align: top;
@@ -189,7 +190,7 @@
word-break: break-all;
height: 50px;
line-height: 50px;
- &>div {
+ & > div {
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
@@ -557,4 +558,4 @@
.kuma-button-group-separated {
line-height: 1.5;
}
-}
\ No newline at end of file
+}
diff --git a/src/util.js b/src/util.js
index 8eea43f..0a4e70d 100644
--- a/src/util.js
+++ b/src/util.js
@@ -84,8 +84,44 @@ const arrayConcat = (oldArr, newArr, reverse) => {
return resArr;
};
-const mergeData = (data, obj, reverse) => {
- const newData = deepcopy(data);
+const getFindRowData = ()=> {
+ let ret = null
+ const findRowData = (data, jsxId) => {
+ if (!data || !data.length || jsxId === undefined) {
+ return
+ }
+ for (let i = 0, len = data.length; i < len; i++) {
+ const item = data[i]
+ if (item.jsxid === jsxId) {
+ ret = item
+ break
+ }
+ if (item.data && item.data.length) {
+ findRowData(item.data, jsxId)
+ }
+ }
+ return ret
+ };
+ return findRowData
+};
+
+const mergeData = (data, obj, reverse, targetId) => {
+ let newData = deepcopy(data);
+ let expandedKey
+ if (targetId >= 0) {
+ const findRowData = getFindRowData()
+ let ret = findRowData(newData.data, targetId)
+ if (ret) {
+ if (ret.data && ret.data.length) {
+ ret.data = arrayConcat(ret.data, obj, reverse)
+ } else {
+ ret.data = obj
+ }
+ expandedKey = ret.jsxid
+ }
+ return { data: newData, expandedKey }
+ }
+
// code compatible
if (newData.datas) {
newData.datas = arrayConcat(newData.datas, obj, reverse);
@@ -93,7 +129,7 @@ const mergeData = (data, obj, reverse) => {
newData.data = arrayConcat(newData.data, obj, reverse);
}
newData.totalCount += 1;
- return newData;
+ return { data: newData, expandedKey };
};
/* eslint-disable no-param-reassign */
@@ -300,7 +336,7 @@ const dropFunc = (obj) => {
return obj;
};
-const getColumnsInfo = (columns, includeActionColumn) => {
+const getColumnsInfo = (columns, includeActionColumn, excludeHiddenColumn) => {
const blackList = {'jsxchecked': 1, 'jsxtreeIcon': 1, 'jsxwhite': 1};
let columnsKey = [];
let actionColumn = null;
@@ -310,7 +346,7 @@ const getColumnsInfo = (columns, includeActionColumn) => {
let fixedColumns = [];
return {
columns: columns.filter((column, index) => {
- if (column.dataKey in blackList) {
+ if (column.dataKey in blackList || excludeHiddenColumn && column.hidden) {
otherColumns.push(column)
return false
}
diff --git a/tests/tree.spec.jsx b/tests/tree.spec.jsx
index d4882dc..a92ccfd 100644
--- a/tests/tree.spec.jsx
+++ b/tests/tree.spec.jsx
@@ -237,4 +237,76 @@ describe('Tree', () => {
wrapper.find('.kuma-icon.kuma-icon-triangle-right').at(4).simulate('click');
expect(wrapper.find('.kuma-uxtable-row').length).to.be(rowLength + 1);
});
+
+ it('api addSubRow & addSubRowFromTop', (done) => {
+ wrapper = mount(
+
+ );
+ const table = wrapper.instance()
+ expect(table.state.expandedKeys).to.have.length(0)
+ table.addSubRow({
+ id: '9999',
+ radio: true,
+ grade: '2grade2',
+ email: '2email2',
+ firstName: '2firstName2',
+ lastName: '2lastName2',
+ birthDate: '2birthDate2',
+ country: '2country2',
+ city: '2city2'
+ }, 0, () => {
+ const data = table.getData().data.data;
+ expect(data[0].data).to.have.length(4);
+ expect(data[0].data[3].id).to.be('9999');
+ expect(data[0].data[3].__treeId__).to.be('0-3');
+ expect(table.state.expandedKeys.includes(0))
+ done();
+ });
+ table.addSubRowFromTop({
+ id: '0000',
+ radio: true,
+ grade: '2grade2',
+ email: '2email2',
+ firstName: '2firstName2',
+ lastName: '2lastName2',
+ birthDate: '2birthDate2',
+ country: '2country2',
+ city: '2city2'
+ }, 0, () => {
+ const data = table.getData().data.data;
+ expect(data[0].data).to.have.length(5);
+ expect(data[0].data[4].id).to.be('0000');
+ expect(data[0].data[4].__treeId__).to.be('0-0');
+ done();
+ });
+
+ // not tree table
+ let wrapper = mount(
+
+ );
+ wrapper.instance().addSubRow({
+ id: '9999',
+ radio: true,
+ grade: '2grade2',
+ email: '2email2',
+ firstName: '2firstName2',
+ lastName: '2lastName2',
+ birthDate: '2birthDate2',
+ country: '2country2',
+ city: '2city2'
+ }, 0, () => {
+ const data = wrapper.instance().getData().data.data;
+ expect(data[0].data).to.have.length(3);
+ done();
+ });
+ });
});