table-column.js 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. import ElCheckbox from 'element-ui/packages/checkbox';
  2. import ElTag from 'element-ui/packages/tag';
  3. import objectAssign from 'element-ui/src/utils/merge';
  4. import { getValueByPath } from './util';
  5. let columnIdSeed = 1;
  6. const defaults = {
  7. default: {
  8. order: ''
  9. },
  10. selection: {
  11. width: 48,
  12. minWidth: 48,
  13. realWidth: 48,
  14. order: '',
  15. className: 'el-table-column--selection'
  16. },
  17. expand: {
  18. width: 48,
  19. minWidth: 48,
  20. realWidth: 48,
  21. order: ''
  22. },
  23. index: {
  24. width: 48,
  25. minWidth: 48,
  26. realWidth: 48,
  27. order: ''
  28. }
  29. };
  30. const forced = {
  31. selection: {
  32. renderHeader: function(h) {
  33. return <el-checkbox
  34. nativeOn-click={ this.toggleAllSelection }
  35. domProps-value={ this.isAllSelected } />;
  36. },
  37. renderCell: function(h, { row, column, store, $index }) {
  38. return <el-checkbox
  39. domProps-value={ store.isSelected(row) }
  40. disabled={ column.selectable ? !column.selectable.call(null, row, $index) : false }
  41. on-input={ () => { store.commit('rowSelectedChanged', row); } } />;
  42. },
  43. sortable: false,
  44. resizable: false
  45. },
  46. index: {
  47. renderHeader: function(h, { column }) {
  48. return column.label || '#';
  49. },
  50. renderCell: function(h, { $index }) {
  51. return <div>{ $index + 1 }</div>;
  52. },
  53. sortable: false
  54. },
  55. expand: {
  56. renderHeader: function(h, {}) {
  57. return '';
  58. },
  59. renderCell: function(h, { row, store }, proxy) {
  60. const expanded = store.states.expandRows.indexOf(row) > -1;
  61. return <div class={ 'el-table__expand-icon ' + (expanded ? 'el-table__expand-icon--expanded' : '') }
  62. on-click={ () => proxy.handleExpandClick(row) }>
  63. <i class='el-icon el-icon-arrow-right'></i>
  64. </div>;
  65. },
  66. sortable: false,
  67. resizable: false,
  68. className: 'el-table__expand-column'
  69. }
  70. };
  71. const getDefaultColumn = function(type, options) {
  72. const column = {};
  73. objectAssign(column, defaults[type || 'default']);
  74. for (let name in options) {
  75. if (options.hasOwnProperty(name)) {
  76. const value = options[name];
  77. if (typeof value !== 'undefined') {
  78. column[name] = value;
  79. }
  80. }
  81. }
  82. if (!column.minWidth) {
  83. column.minWidth = 80;
  84. }
  85. column.realWidth = column.width || column.minWidth;
  86. return column;
  87. };
  88. const DEFAULT_RENDER_CELL = function(h, { row, column }) {
  89. const property = column.property;
  90. if (column && column.formatter) {
  91. return column.formatter(row, column);
  92. }
  93. if (property && property.indexOf('.') === -1) {
  94. return row[property];
  95. }
  96. return getValueByPath(row, property);
  97. };
  98. export default {
  99. name: 'ElTableColumn',
  100. props: {
  101. type: {
  102. type: String,
  103. default: 'default'
  104. },
  105. label: String,
  106. className: String,
  107. property: String,
  108. prop: String,
  109. width: {},
  110. minWidth: {},
  111. renderHeader: Function,
  112. sortable: {
  113. type: [String, Boolean],
  114. default: false
  115. },
  116. sortMethod: Function,
  117. resizable: {
  118. type: Boolean,
  119. default: true
  120. },
  121. context: {},
  122. columnKey: String,
  123. align: String,
  124. headerAlign: String,
  125. showTooltipWhenOverflow: Boolean,
  126. showOverflowTooltip: Boolean,
  127. fixed: [Boolean, String],
  128. formatter: Function,
  129. selectable: Function,
  130. reserveSelection: Boolean,
  131. filterMethod: Function,
  132. filteredValue: Array,
  133. filters: Array,
  134. filterMultiple: {
  135. type: Boolean,
  136. default: true
  137. }
  138. },
  139. data() {
  140. return {
  141. isSubColumn: false,
  142. columns: []
  143. };
  144. },
  145. beforeCreate() {
  146. this.row = {};
  147. this.column = {};
  148. this.$index = 0;
  149. },
  150. components: {
  151. ElCheckbox,
  152. ElTag
  153. },
  154. computed: {
  155. owner() {
  156. let parent = this.$parent;
  157. while (parent && !parent.tableId) {
  158. parent = parent.$parent;
  159. }
  160. return parent;
  161. }
  162. },
  163. created() {
  164. this.customRender = this.$options.render;
  165. this.$options.render = h => h('div', this.$slots.default);
  166. let columnId = this.columnId = this.columnKey || ((this.$parent.tableId || (this.$parent.columnId + '_')) + 'column_' + columnIdSeed++);
  167. let parent = this.$parent;
  168. let owner = this.owner;
  169. this.isSubColumn = owner !== parent;
  170. let type = this.type;
  171. let width = this.width;
  172. if (width !== undefined) {
  173. width = parseInt(width, 10);
  174. if (isNaN(width)) {
  175. width = null;
  176. }
  177. }
  178. let minWidth = this.minWidth;
  179. if (minWidth !== undefined) {
  180. minWidth = parseInt(minWidth, 10);
  181. if (isNaN(minWidth)) {
  182. minWidth = 80;
  183. }
  184. }
  185. let isColumnGroup = false;
  186. let column = getDefaultColumn(type, {
  187. id: columnId,
  188. label: this.label,
  189. className: this.className,
  190. property: this.prop || this.property,
  191. type,
  192. renderCell: null,
  193. renderHeader: this.renderHeader,
  194. minWidth,
  195. width,
  196. isColumnGroup,
  197. context: this.context,
  198. align: this.align ? 'is-' + this.align : null,
  199. headerAlign: this.headerAlign ? 'is-' + this.headerAlign : (this.align ? 'is-' + this.align : null),
  200. sortable: this.sortable === '' ? true : this.sortable,
  201. sortMethod: this.sortMethod,
  202. resizable: this.resizable,
  203. showOverflowTooltip: this.showOverflowTooltip || this.showTooltipWhenOverflow,
  204. formatter: this.formatter,
  205. selectable: this.selectable,
  206. reserveSelection: this.reserveSelection,
  207. fixed: this.fixed === '' ? true : this.fixed,
  208. filterMethod: this.filterMethod,
  209. filters: this.filters,
  210. filterable: this.filters || this.filterMethod,
  211. filterMultiple: this.filterMultiple,
  212. filterOpened: false,
  213. filteredValue: this.filteredValue || []
  214. });
  215. objectAssign(column, forced[type] || {});
  216. this.columnConfig = column;
  217. let renderCell = column.renderCell;
  218. let _self = this;
  219. if (type === 'expand') {
  220. owner.renderExpanded = function(h, data) {
  221. return _self.$scopedSlots.default
  222. ? _self.$scopedSlots.default(data)
  223. : _self.$slots.default;
  224. };
  225. column.renderCell = function(h, data) {
  226. return <div class="cell">{ renderCell(h, data, this._renderProxy) }</div>;
  227. };
  228. return;
  229. }
  230. column.renderCell = function(h, data) {
  231. // 未来版本移除
  232. if (_self.$vnode.data.inlineTemplate) {
  233. renderCell = function() {
  234. data._self = _self.context || data._self;
  235. if (Object.prototype.toString.call(data._self) === '[object Object]') {
  236. for (let prop in data._self) {
  237. if (!data.hasOwnProperty(prop)) {
  238. data[prop] = data._self[prop];
  239. }
  240. }
  241. }
  242. // 静态内容会缓存到 _staticTrees 内,不改的话获取的静态数据就不是内部 context
  243. data._staticTrees = _self._staticTrees;
  244. data.$options.staticRenderFns = _self.$options.staticRenderFns;
  245. return _self.customRender.call(data);
  246. };
  247. } else if (_self.$scopedSlots.default) {
  248. renderCell = () => _self.$scopedSlots.default(data);
  249. }
  250. if (!renderCell) {
  251. renderCell = DEFAULT_RENDER_CELL;
  252. }
  253. return _self.showOverflowTooltip || _self.showTooltipWhenOverflow
  254. ? <el-tooltip
  255. effect={ this.effect }
  256. placement="top"
  257. disabled={ this.tooltipDisabled }>
  258. <div class="cell">{ renderCell(h, data) }</div>
  259. <span slot="content">{ renderCell(h, data) }</span>
  260. </el-tooltip>
  261. : <div class="cell">{ renderCell(h, data) }</div>;
  262. };
  263. },
  264. destroyed() {
  265. if (!this.$parent) return;
  266. this.owner.store.commit('removeColumn', this.columnConfig);
  267. },
  268. watch: {
  269. label(newVal) {
  270. if (this.columnConfig) {
  271. this.columnConfig.label = newVal;
  272. }
  273. },
  274. prop(newVal) {
  275. if (this.columnConfig) {
  276. this.columnConfig.property = newVal;
  277. }
  278. },
  279. property(newVal) {
  280. if (this.columnConfig) {
  281. this.columnConfig.property = newVal;
  282. }
  283. },
  284. filters(newVal) {
  285. if (this.columnConfig) {
  286. this.columnConfig.filters = newVal;
  287. }
  288. },
  289. filterMultiple(newVal) {
  290. if (this.columnConfig) {
  291. this.columnConfig.filterMultiple = newVal;
  292. }
  293. },
  294. align(newVal) {
  295. if (this.columnConfig) {
  296. this.columnConfig.align = newVal ? 'is-' + newVal : null;
  297. if (!this.headerAlign) {
  298. this.columnConfig.headerAlign = newVal ? 'is-' + newVal : null;
  299. }
  300. }
  301. },
  302. headerAlign(newVal) {
  303. if (this.columnConfig) {
  304. this.columnConfig.headerAlign = 'is-' + (newVal ? newVal : this.align);
  305. }
  306. },
  307. width(newVal) {
  308. if (this.columnConfig) {
  309. this.columnConfig.width = newVal;
  310. this.owner.store.scheduleLayout();
  311. }
  312. },
  313. minWidth(newVal) {
  314. if (this.columnConfig) {
  315. this.columnConfig.minWidth = newVal;
  316. this.owner.store.scheduleLayout();
  317. }
  318. },
  319. fixed(newVal) {
  320. if (this.columnConfig) {
  321. this.columnConfig.fixed = newVal;
  322. this.owner.store.scheduleLayout();
  323. }
  324. }
  325. },
  326. mounted() {
  327. const owner = this.owner;
  328. const parent = this.$parent;
  329. let columnIndex;
  330. if (!this.isSubColumn) {
  331. columnIndex = [].indexOf.call(parent.$refs.hiddenColumns.children, this.$el);
  332. } else {
  333. columnIndex = [].indexOf.call(parent.$el.children, this.$el);
  334. }
  335. owner.store.commit('insertColumn', this.columnConfig, columnIndex, this.isSubColumn ? parent.columnConfig : null);
  336. }
  337. };