2019-05-30 11:33:30 +00:00
import { cellStarts , cellForced , defaultRenderCell , treeCellPrefix } from './config' ;
import { mergeOptions , parseWidth , parseMinWidth , compose } from './util' ;
2016-10-25 13:35:41 +00:00
import ElCheckbox from 'element-ui/packages/checkbox' ;
2016-08-16 08:07:18 +00:00
let columnIdSeed = 1 ;
export default {
2016-12-31 15:33:51 +00:00
name : 'ElTableColumn' ,
2016-08-16 08:07:18 +00:00
props : {
type : {
type : String ,
default : 'default'
} ,
label : String ,
2016-11-13 06:39:24 +00:00
className : String ,
2017-03-08 11:14:36 +00:00
labelClassName : String ,
2016-08-16 08:07:18 +00:00
property : String ,
2016-10-12 11:18:34 +00:00
prop : String ,
2016-08-16 08:07:18 +00:00
width : { } ,
minWidth : { } ,
2016-11-04 23:30:23 +00:00
renderHeader : Function ,
2016-08-16 08:07:18 +00:00
sortable : {
2019-05-30 11:33:30 +00:00
type : [ Boolean , String ] ,
2016-08-16 08:07:18 +00:00
default : false
} ,
2016-10-27 17:24:13 +00:00
sortMethod : Function ,
2017-10-30 02:26:25 +00:00
sortBy : [ String , Function , Array ] ,
2016-08-16 08:07:18 +00:00
resizable : {
type : Boolean ,
default : true
} ,
2016-12-20 10:21:15 +00:00
columnKey : String ,
2016-09-20 22:20:36 +00:00
align : String ,
2016-12-21 03:03:22 +00:00
headerAlign : String ,
2016-11-04 08:27:51 +00:00
showTooltipWhenOverflow : Boolean ,
showOverflowTooltip : Boolean ,
2016-10-12 11:18:34 +00:00
fixed : [ Boolean , String ] ,
formatter : Function ,
2016-10-19 10:53:31 +00:00
selectable : Function ,
2016-10-27 13:45:21 +00:00
reserveSelection : Boolean ,
filterMethod : Function ,
2017-01-13 06:53:58 +00:00
filteredValue : Array ,
2016-10-27 13:45:21 +00:00
filters : Array ,
2017-04-27 06:08:59 +00:00
filterPlacement : String ,
2016-10-27 13:45:21 +00:00
filterMultiple : {
type : Boolean ,
default : true
2017-10-25 07:35:12 +00:00
} ,
2018-05-22 10:20:04 +00:00
index : [ Number , Function ] ,
sortOrders : {
type : Array ,
default ( ) {
return [ 'ascending' , 'descending' , null ] ;
} ,
validator ( val ) {
return val . every ( order => [ 'ascending' , 'descending' , null ] . indexOf ( order ) > - 1 ) ;
}
}
2016-08-16 08:07:18 +00:00
} ,
data ( ) {
return {
2016-11-23 12:32:23 +00:00
isSubColumn : false ,
2016-08-30 07:36:21 +00:00
columns : [ ]
2016-08-16 08:07:18 +00:00
} ;
} ,
2016-10-12 11:18:34 +00:00
computed : {
owner ( ) {
let parent = this . $parent ;
while ( parent && ! parent . tableId ) {
parent = parent . $parent ;
}
return parent ;
2017-11-27 06:59:21 +00:00
} ,
2019-05-30 11:33:30 +00:00
2017-11-27 06:59:21 +00:00
columnOrTableParent ( ) {
let parent = this . $parent ;
while ( parent && ! parent . tableId && ! parent . columnId ) {
parent = parent . $parent ;
}
return parent ;
2019-05-30 11:33:30 +00:00
} ,
2016-11-12 15:08:17 +00:00
2019-05-30 11:33:30 +00:00
realWidth ( ) {
return parseWidth ( this . width ) ;
} ,
2016-08-30 07:36:21 +00:00
2019-05-30 11:33:30 +00:00
realMinWidth ( ) {
return parseMinWidth ( this . minWidth ) ;
} ,
2016-11-12 15:08:17 +00:00
2019-05-30 11:33:30 +00:00
realAlign ( ) {
return this . align ? 'is-' + this . align : null ;
} ,
2016-11-12 15:08:17 +00:00
2019-05-30 11:33:30 +00:00
realHeaderAlign ( ) {
return this . headerAlign ? 'is-' + this . headerAlign : this . realAlign ;
2016-11-12 15:08:17 +00:00
}
2016-08-16 08:07:18 +00:00
} ,
2019-05-30 11:33:30 +00:00
methods : {
getPropsData ( ... props ) {
return props . reduce ( ( prev , cur ) => {
if ( Array . isArray ( cur ) ) {
cur . forEach ( ( key ) => {
prev [ key ] = this [ key ] ;
} ) ;
}
return prev ;
} , { } ) ;
2016-08-16 08:07:18 +00:00
} ,
2019-05-30 11:33:30 +00:00
getColumnElIndex ( children , child ) {
return [ ] . indexOf . call ( children , child ) ;
2016-10-12 11:18:34 +00:00
} ,
2019-05-30 11:33:30 +00:00
setColumnWidth ( column ) {
if ( this . realWidth ) {
column . width = this . realWidth ;
2016-08-16 08:07:18 +00:00
}
2019-05-30 11:33:30 +00:00
if ( this . realMinWidth ) {
column . minWidth = this . realMinWidth ;
2016-11-04 08:27:51 +00:00
}
2019-05-30 11:33:30 +00:00
if ( ! column . minWidth ) {
column . minWidth = 80 ;
2016-11-04 08:27:51 +00:00
}
2019-05-30 11:33:30 +00:00
column . realWidth = column . width === undefined ? column . minWidth : column . width ;
return column ;
2016-11-04 08:27:51 +00:00
} ,
2019-05-30 11:33:30 +00:00
setColumnForcedProps ( column ) {
// 对于特定类型的 column, 某些属性不允许设置
const type = column . type ;
const source = cellForced [ type ] || { } ;
Object . keys ( source ) . forEach ( prop => {
let value = source [ prop ] ;
if ( value !== undefined ) {
column [ prop ] = prop === 'className' ? ` ${ column [ prop ] } ${ value } ` : value ;
2017-01-06 02:28:01 +00:00
}
2019-05-30 11:33:30 +00:00
} ) ;
return column ;
2016-11-04 08:27:51 +00:00
} ,
2019-05-30 11:33:30 +00:00
setColumnRenders ( column ) {
// renderHeader 属性不推荐使用。
if ( this . renderHeader ) {
console . warn ( '[Element Warn][TableColumn]Comparing to render-header, scoped-slot header is easier to use. We recommend users to use scoped-slot header.' ) ;
2019-09-03 08:45:51 +00:00
} else if ( column . type !== 'selection' ) {
2019-05-30 11:33:30 +00:00
column . renderHeader = ( h , scope ) => {
const renderHeader = this . $scopedSlots . header ;
return renderHeader ? renderHeader ( scope ) : column . label ;
} ;
2016-12-21 03:03:22 +00:00
}
2019-05-30 11:33:30 +00:00
let originRenderCell = column . renderCell ;
// TODO: 这里的实现调整
if ( column . type === 'expand' ) {
// 对于展开行, renderCell 不允许配置的。在上一步中已经设置过,这里需要简单封装一下。
column . renderCell = ( h , data ) => ( < div class = "cell" >
{ originRenderCell ( h , data ) }
< / d i v > ) ;
this . owner . renderExpanded = ( h , data ) => {
return this . $scopedSlots . default
? this . $scopedSlots . default ( data )
: this . $slots . default ;
} ;
} else {
originRenderCell = originRenderCell || defaultRenderCell ;
// 对 renderCell 进行包装
column . renderCell = ( h , data ) => {
let children = null ;
if ( this . $scopedSlots . default ) {
children = this . $scopedSlots . default ( data ) ;
} else {
children = originRenderCell ( h , data ) ;
}
const prefix = treeCellPrefix ( h , data ) ;
const props = {
class : 'cell' ,
style : { }
} ;
if ( column . showOverflowTooltip ) {
props . class += ' el-tooltip' ;
props . style = { width : ( data . column . realWidth || data . column . width ) - 1 + 'px' } ;
}
return ( < div { ... props } >
{ prefix }
{ children }
< / d i v > ) ;
} ;
2016-11-04 08:27:51 +00:00
}
2019-05-30 11:33:30 +00:00
return column ;
2016-11-04 08:27:51 +00:00
} ,
2019-05-30 11:33:30 +00:00
registerNormalWatchers ( ) {
2019-07-01 08:05:19 +00:00
const props = [ 'label' , 'property' , 'filters' , 'filterMultiple' , 'sortable' , 'index' , 'formatter' , 'className' , 'labelClassName' , 'showOverflowTooltip' ] ;
2019-05-30 11:33:30 +00:00
// 一些属性具有别名
const aliases = {
prop : 'property' ,
realAlign : 'align' ,
realHeaderAlign : 'headerAlign' ,
realWidth : 'width'
} ;
const allAliases = props . reduce ( ( prev , cur ) => {
prev [ cur ] = cur ;
return prev ;
} , aliases ) ;
Object . keys ( allAliases ) . forEach ( key => {
const columnKey = aliases [ key ] ;
this . $watch ( key , ( newVal ) => {
this . columnConfig [ columnKey ] = newVal ;
} ) ;
} ) ;
2016-11-04 08:27:51 +00:00
} ,
2019-05-30 11:33:30 +00:00
registerComplexWatchers ( ) {
const props = [ 'fixed' ] ;
const aliases = {
realWidth : 'width' ,
realMinWidth : 'minWidth'
} ;
const allAliases = props . reduce ( ( prev , cur ) => {
prev [ cur ] = cur ;
return prev ;
} , aliases ) ;
Object . keys ( allAliases ) . forEach ( key => {
const columnKey = aliases [ key ] ;
this . $watch ( key , ( newVal ) => {
this . columnConfig [ columnKey ] = newVal ;
const updateColumns = columnKey === 'fixed' ;
this . owner . store . scheduleLayout ( updateColumns ) ;
} ) ;
} ) ;
}
} ,
2017-04-28 07:53:39 +00:00
2019-05-30 11:33:30 +00:00
components : {
ElCheckbox
} ,
2017-10-25 07:35:12 +00:00
2019-05-30 11:33:30 +00:00
beforeCreate ( ) {
this . row = { } ;
this . column = { } ;
this . $index = 0 ;
this . columnId = '' ;
} ,
2018-03-16 03:04:44 +00:00
2019-05-30 11:33:30 +00:00
created ( ) {
const parent = this . columnOrTableParent ;
this . isSubColumn = this . owner !== parent ;
this . columnId = ( parent . tableId || parent . columnId ) + '_column_' + columnIdSeed ++ ;
2018-06-14 09:07:00 +00:00
2019-05-30 11:33:30 +00:00
const type = this . type || 'default' ;
const sortable = this . sortable === '' ? true : this . sortable ;
const defaults = {
... cellStarts [ type ] ,
id : this . columnId ,
type : type ,
property : this . prop || this . property ,
align : this . realAlign ,
headerAlign : this . realHeaderAlign ,
showOverflowTooltip : this . showOverflowTooltip || this . showTooltipWhenOverflow ,
// filter 相关属性
filterable : this . filters || this . filterMethod ,
filteredValue : [ ] ,
filterPlacement : '' ,
isColumnGroup : false ,
filterOpened : false ,
// sort 相关属性
sortable : sortable ,
// index 列
index : this . index
} ;
2018-06-14 09:07:00 +00:00
2019-07-01 08:05:19 +00:00
const basicProps = [ 'columnKey' , 'label' , 'className' , 'labelClassName' , 'type' , 'renderHeader' , 'formatter' , 'fixed' , 'resizable' ] ;
2019-05-30 11:33:30 +00:00
const sortProps = [ 'sortMethod' , 'sortBy' , 'sortOrders' ] ;
const selectProps = [ 'selectable' , 'reserveSelection' ] ;
const filterProps = [ 'filterMethod' , 'filters' , 'filterMultiple' , 'filterOpened' , 'filteredValue' , 'filterPlacement' ] ;
2016-08-16 08:07:18 +00:00
2019-05-30 11:33:30 +00:00
let column = this . getPropsData ( basicProps , sortProps , selectProps , filterProps ) ;
column = mergeOptions ( defaults , column ) ;
2019-03-27 08:13:21 +00:00
2019-05-30 11:33:30 +00:00
// 注意 compose 中函数执行的顺序是从右到左
const chains = compose ( this . setColumnRenders , this . setColumnWidth , this . setColumnForcedProps ) ;
column = chains ( column ) ;
this . columnConfig = column ;
// 注册 watcher
this . registerNormalWatchers ( ) ;
this . registerComplexWatchers ( ) ;
2019-03-27 08:13:21 +00:00
} ,
2016-08-16 08:07:18 +00:00
mounted ( ) {
2016-10-12 11:18:34 +00:00
const owner = this . owner ;
2017-11-27 06:59:21 +00:00
const parent = this . columnOrTableParent ;
2019-05-30 11:33:30 +00:00
const children = this . isSubColumn ? parent . $el . children : parent . $refs . hiddenColumns . children ;
const columnIndex = this . getColumnElIndex ( children , this . $el ) ;
2016-08-16 08:07:18 +00:00
2019-05-30 11:33:30 +00:00
owner . store . commit ( 'insertColumn' , this . columnConfig , columnIndex , this . isSubColumn ? parent . columnConfig : null ) ;
} ,
2016-08-16 08:07:18 +00:00
2019-05-30 11:33:30 +00:00
destroyed ( ) {
if ( ! this . $parent ) return ;
const parent = this . $parent ;
this . owner . store . commit ( 'removeColumn' , this . columnConfig , this . isSubColumn ? parent . columnConfig : null ) ;
} ,
2018-10-26 03:16:56 +00:00
2019-05-30 11:33:30 +00:00
render ( h ) {
// slots 也要渲染,需要计算合并表头
return h ( 'div' , this . $slots . default ) ;
2016-08-16 08:07:18 +00:00
}
} ;