Table: add single selection back. Add current-change event & highlight-current-row event.

pull/824/head
furybean 2016-11-04 16:15:33 +08:00
parent f4e2face02
commit 7263db12b3
7 changed files with 112 additions and 7 deletions

View File

@ -13,6 +13,7 @@
- 修复 Slider 在 Form 中的显示问题 - 修复 Slider 在 Form 中的显示问题
- 修复 Upload 在 onSuccess、onError 钩子无法拿到服务端返回信息的问题 - 修复 Upload 在 onSuccess、onError 钩子无法拿到服务端返回信息的问题
- 改善 tabs 现在支持动态更新 - 改善 tabs 现在支持动态更新
- Table 新增 highlightCurrentRow 属性、新增 current-change 事件
#### 非兼容性更新 #### 非兼容性更新

View File

@ -898,6 +898,7 @@
| stripe | 是否为斑马纹 table | boolean | — | false | | stripe | 是否为斑马纹 table | boolean | — | false |
| border | 是否带有纵向边框 | boolean | — | false | | border | 是否带有纵向边框 | boolean | — | false |
| fit | 列的宽度是否自撑开 | boolean | — | true | | fit | 列的宽度是否自撑开 | boolean | — | true |
| highlight-current-row | 是否要高亮当前行 | boolean | - | false |
| row-class-name | 行的 className 的回调。 | Function(row, index) | - | - | | row-class-name | 行的 className 的回调。 | Function(row, index) | - | - |
| row-key | 行数据的 Key用来优化 Table 的渲染;在使用 reserve-selection 功能的情况下,该属性是必填的 | Function(row), String | - | - | | row-key | 行数据的 Key用来优化 Table 的渲染;在使用 reserve-selection 功能的情况下,该属性是必填的 | Function(row), String | - | - |
@ -912,6 +913,7 @@
| cell-click | 当某个单元格被点击时会触发该事件 | row, column, cell, event | | cell-click | 当某个单元格被点击时会触发该事件 | row, column, cell, event |
| row-click | 当某一行被点击时会触发该事件 | row, event | | row-click | 当某一行被点击时会触发该事件 | row, event |
| sort-change | 当表格的排序条件发生变化的时候会触发该事件 | { column, prop, order } | | sort-change | 当表格的排序条件发生变化的时候会触发该事件 | { column, prop, order } |
| current-change | 当表格的当前行发生变化的时候会触发该事件,如果要高亮当前行,请打开表格的 highlight-current-row 属性 | { column, prop, order } |
### Table Methods ### Table Methods
| 方法名 | 说明 | 参数 | | 方法名 | 说明 | 参数 |

View File

@ -9,7 +9,8 @@ export default {
required: true required: true
}, },
rowClassName: [String, Function], rowClassName: [String, Function],
fixed: String fixed: String,
highlight: Boolean
}, },
render(h) { render(h) {
@ -115,6 +116,11 @@ export default {
classes.push(rowClassName.apply(null, [row, index]) || ''); classes.push(rowClassName.apply(null, [row, index]) || '');
} }
const currentRow = this.store.states.currentRow;
if (this.highlight && currentRow === row) {
classes.push('current-row');
}
return classes.join(' '); return classes.join(' ');
}, },
@ -161,6 +167,8 @@ export default {
} }
} }
this.store.commit('setCurrentRow', row);
table.$emit('row-click', row, event); table.$emit('row-click', row, event);
}, },

View File

@ -74,6 +74,7 @@ const TableStore = function(table, initialState = {}) {
selection: [], selection: [],
reserveSelection: false, reserveSelection: false,
selectable: null, selectable: null,
currentRow: null,
hoverRow: null, hoverRow: null,
filters: {} filters: {}
}; };
@ -89,6 +90,9 @@ TableStore.prototype.mutations = {
setData(states, data) { setData(states, data) {
states._data = data; states._data = data;
states.data = sortData((data || []), states); states.data = sortData((data || []), states);
this.updateCurrentRow();
const selection = states.selection; const selection = states.selection;
if (!states.reserveSelection) { if (!states.reserveSelection) {
@ -186,13 +190,23 @@ TableStore.prototype.mutations = {
states.hoverRow = row; states.hoverRow = row;
}, },
setCurrentRow(states, row) {
const oldCurrentRow = states.currentRow;
states.currentRow = row;
if (oldCurrentRow !== row) {
this.table.$emit('current-change', row, oldCurrentRow);
}
},
rowSelectedChanged(states, row) { rowSelectedChanged(states, row) {
const changed = toggleRowSelection(states, row); const changed = toggleRowSelection(states, row);
const selection = states.selection; const selection = states.selection;
if (changed) { if (changed) {
this.table.$emit('selection-change', selection); const table = this.table;
this.table.$emit('select', selection, row); table.$emit('selection-change', selection);
table.$emit('select', selection, row);
} }
this.updateAllSelected(); this.updateAllSelected();
@ -216,10 +230,11 @@ TableStore.prototype.mutations = {
} }
}); });
const table = this.table;
if (selectionChanged) { if (selectionChanged) {
this.table.$emit('selection-change', selection); table.$emit('selection-change', selection);
} }
this.table.$emit('select-all', selection); table.$emit('select-all', selection);
states.isAllSelected = value; states.isAllSelected = value;
}) })
}; };
@ -295,6 +310,21 @@ TableStore.prototype.scheduleLayout = function() {
this.table.debouncedLayout(); this.table.debouncedLayout();
}; };
TableStore.prototype.updateCurrentRow = function() {
const states = this.states;
const table = this.table;
const data = states.data || [];
const oldCurrentRow = states.currentRow;
if (data.indexOf(oldCurrentRow) === -1) {
states.currentRow = null;
if (states.currentRow !== oldCurrentRow) {
table.$emit('current-change', null, oldCurrentRow);
}
}
};
TableStore.prototype.commit = function(name, ...args) { TableStore.prototype.commit = function(name, ...args) {
const mutations = this.mutations; const mutations = this.mutations;
if (mutations[name]) { if (mutations[name]) {

View File

@ -17,6 +17,7 @@
:store="store" :store="store"
:layout="layout" :layout="layout"
:row-class-name="rowClassName" :row-class-name="rowClassName"
:highlight="highlightCurrentRow"
:style="{ width: layout.bodyWidth ? layout.bodyWidth - (layout.scrollY ? layout.gutterWidth : 0 ) + 'px' : '' }"> :style="{ width: layout.bodyWidth ? layout.bodyWidth - (layout.scrollY ? layout.gutterWidth : 0 ) + 'px' : '' }">
</table-body> </table-body>
<div class="el-table__empty-block" v-if="!data || data.length === 0"> <div class="el-table__empty-block" v-if="!data || data.length === 0">
@ -47,6 +48,7 @@
fixed="left" fixed="left"
:store="store" :store="store"
:layout="layout" :layout="layout"
:highlight="highlightCurrentRow"
:row-class-name="rowClassName" :row-class-name="rowClassName"
:style="{ width: layout.fixedWidth ? layout.fixedWidth + 'px' : '' }"> :style="{ width: layout.fixedWidth ? layout.fixedWidth + 'px' : '' }">
</table-body> </table-body>
@ -78,6 +80,7 @@
:store="store" :store="store"
:layout="layout" :layout="layout"
:row-class-name="rowClassName" :row-class-name="rowClassName"
:highlight="highlightCurrentRow"
:style="{ width: layout.rightFixedWidth ? layout.rightFixedWidth + 'px' : '' }"> :style="{ width: layout.rightFixedWidth ? layout.rightFixedWidth + 'px' : '' }">
</table-body> </table-body>
</div> </div>
@ -130,6 +133,8 @@
rowClassName: [String, Function], rowClassName: [String, Function],
highlightCurrentRow: Boolean,
emptyText: { emptyText: {
type: String, type: String,
default: $t('el.table.emptyText') default: $t('el.table.emptyText')

View File

@ -330,7 +330,7 @@
background-color: #eff2f7; background-color: #eff2f7;
} }
tr.current-row { tr.current-row td {
background: #eff7ff; background: #eff7ff;
} }
} }

View File

@ -261,7 +261,7 @@ describe('Table', () => {
}, },
data() { data() {
return { result: '' }; return { result: '', testData: this.testData };
} }
}, true); }, true);
}; };
@ -358,6 +358,32 @@ describe('Table', () => {
done(); done();
}, DELAY); }, DELAY);
}); });
it('current-change', done => {
const vm = createTable('current-change');
setTimeout(_ => {
const cell = vm.$el.querySelectorAll('.el-table__body .cell')[2]; // first row
triggerEvent(cell.parentNode.parentNode, 'click');
expect(vm.result).to.length(2); // currentRow, oldCurrentRow
expect(vm.result[0]).to.have.property('name').to.equal(getTestData()[0].name);
expect(vm.result[1]).to.equal(null);
// clear data => current-change should fire again.
const oldRow = vm.result[0];
vm.testData = [];
setTimeout(() => {
expect(vm.result).to.length(2); // currentRow, oldCurrentRow
expect(vm.result[0]).to.equal(null);
expect(vm.result[1]).to.equal(oldRow);
destroyVM(vm);
done();
}, DELAY);
}, DELAY);
});
}); });
describe('column attributes', () => { describe('column attributes', () => {
@ -825,4 +851,37 @@ describe('Table', () => {
}, DELAY); }, DELAY);
}, DELAY); }, DELAY);
}); });
it('highlight-current-row', done => {
const vm = createVue({
template: `
<el-table :data="testData" highlight-current-row>
<el-table-column prop="name" label="片名" />
<el-table-column prop="release" label="发行日期" />
<el-table-column prop="director" label="导演" />
<el-table-column prop="runtime" label="时长(分)" />
</el-table>
`,
created() {
this.testData = getTestData();
}
}, true);
setTimeout(_ => {
const tr = vm.$el.querySelector('.el-table__body-wrapper tbody tr');
triggerEvent(tr, 'click', true, false);
setTimeout(_ => {
expect(tr.classList.contains('current-row')).to.be.true;
const rows = vm.$el.querySelectorAll('.el-table__body-wrapper tbody tr');
triggerEvent(rows[2], 'click', true, false);
setTimeout(_ => {
expect(tr.classList.contains('current-row')).to.be.false;
expect(rows[2].classList.contains('current-row')).to.be.true;
destroyVM(vm);
done();
}, DELAY);
}, DELAY);
}, DELAY);
});
}); });