UNPKG

element-plus

Version:

A Component Library for Vue3.0

625 lines (615 loc) 17.6 kB
import { h, getCurrentInstance, watch, ref, watchEffect, computed, defineComponent, onBeforeMount, onMounted, onBeforeUnmount, Fragment } from 'vue'; import { getPropByPath } from '../utils/util'; import ElCheckbox from '../el-checkbox'; import '../utils/dom'; import '@popperjs/core'; import '../utils/popup-manager'; const cellStarts = { default: { order: "" }, selection: { width: 48, minWidth: 48, realWidth: 48, order: "", className: "el-table-column--selection" }, expand: { width: 48, minWidth: 48, realWidth: 48, order: "" }, index: { width: 48, minWidth: 48, realWidth: 48, order: "" } }; const cellForced = { selection: { renderHeader: function({ store }) { function isDisabled() { return store.states.data.value && store.states.data.value.length === 0; } return h(ElCheckbox, { disabled: isDisabled(), indeterminate: store.states.selection.value.length > 0 && !store.states.isAllSelected.value, "onUpdate:modelValue": store.toggleAllSelection, modelValue: store.states.isAllSelected.value }); }, renderCell: function({ row, column, store, $index }) { return h(ElCheckbox, { disabled: column.selectable ? !column.selectable.call(null, row, $index) : false, onChange: () => { store.commit("rowSelectedChanged", row); }, onClick: (event) => event.stopPropagation(), modelValue: store.isSelected(row) }); }, sortable: false, resizable: false }, index: { renderHeader: function({ column }) { return column.label || "#"; }, renderCell: function({ column, $index }) { let i = $index + 1; const index = column.index; if (typeof index === "number") { i = $index + index; } else if (typeof index === "function") { i = index($index); } return h("div", {}, [i]); }, sortable: false }, expand: { renderHeader: function({ column }) { return column.label || ""; }, renderCell: function({ row, store }) { const classes = ["el-table__expand-icon"]; if (store.states.expandRows.value.indexOf(row) > -1) { classes.push("el-table__expand-icon--expanded"); } const callback = function(e) { e.stopPropagation(); store.toggleRowExpansion(row); }; return h("div", { class: classes, onClick: callback }, [ h("i", { class: "el-icon el-icon-arrow-right" }) ]); }, sortable: false, resizable: false, className: "el-table__expand-column" } }; function defaultRenderCell({ row, column, $index }) { var _a; const property = column.property; const value = property && getPropByPath(row, property, false).v; if (column && column.formatter) { return column.formatter(row, column, value, $index); } return ((_a = value == null ? void 0 : value.toString) == null ? void 0 : _a.call(value)) || ""; } function treeCellPrefix({ row, treeNode, store }) { if (!treeNode) return null; const ele = []; const callback = function(e) { e.stopPropagation(); store.loadOrToggle(row); }; if (treeNode.indent) { ele.push(h("span", { class: "el-table__indent", style: { "padding-left": treeNode.indent + "px" } })); } if (typeof treeNode.expanded === "boolean" && !treeNode.noLazyChildren) { const expandClasses = [ "el-table__expand-icon", treeNode.expanded ? "el-table__expand-icon--expanded" : "" ]; let iconClasses = ["el-icon-arrow-right"]; if (treeNode.loading) { iconClasses = ["el-icon-loading"]; } ele.push(h("div", { class: expandClasses, onClick: callback }, [ h("i", { class: iconClasses }) ])); } else { ele.push(h("span", { class: "el-table__placeholder" })); } return ele; } /** * Make a map and return a function for checking if a key * is in that map. * IMPORTANT: all calls of this function must be prefixed with * \/\*#\_\_PURE\_\_\*\/ * So that rollup can tree-shake them if necessary. */ const EMPTY_OBJ = (process.env.NODE_ENV !== 'production') ? Object.freeze({}) : {}; const EMPTY_ARR = (process.env.NODE_ENV !== 'production') ? Object.freeze([]) : []; const hasOwnProperty = Object.prototype.hasOwnProperty; const hasOwn = (val, key) => hasOwnProperty.call(val, key); function mergeOptions(defaults, config) { const options = {}; let key; for (key in defaults) { options[key] = defaults[key]; } for (key in config) { if (hasOwn(config, key)) { const value = config[key]; if (typeof value !== "undefined") { options[key] = value; } } } return options; } function parseWidth(width) { if (width !== void 0) { width = parseInt(width, 10); if (isNaN(width)) { width = null; } } return +width; } function parseMinWidth(minWidth) { if (typeof minWidth !== "undefined") { minWidth = parseWidth(minWidth); if (isNaN(minWidth)) { minWidth = 80; } } return minWidth; } function compose(...funcs) { if (funcs.length === 0) { return (arg) => arg; } if (funcs.length === 1) { return funcs[0]; } return funcs.reduce((a, b) => (...args) => a(b(...args))); } function useWatcher(owner, props_) { const instance = getCurrentInstance(); const 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]; if (hasOwn(props_, columnKey)) { watch(() => props_[columnKey], (newVal) => { let value = newVal; if (columnKey === "width" && key === "realWidth") { value = parseWidth(newVal); } if (columnKey === "minWidth" && key === "realMinWidth") { value = parseMinWidth(newVal); } instance.columnConfig.value[columnKey] = value; instance.columnConfig.value[key] = value; const updateColumns = columnKey === "fixed"; owner.value.store.scheduleLayout(updateColumns); }); } }); }; const registerNormalWatchers = () => { const props = [ "label", "filters", "filterMultiple", "sortable", "index", "formatter", "className", "labelClassName", "showOverflowTooltip" ]; const aliases = { property: "prop", align: "realAlign", headerAlign: "realHeaderAlign" }; const allAliases = props.reduce((prev, cur) => { prev[cur] = cur; return prev; }, aliases); Object.keys(allAliases).forEach((key) => { const columnKey = aliases[key]; if (hasOwn(props_, columnKey)) { watch(() => props_[columnKey], (newVal) => { instance.columnConfig.value[key] = newVal; }); } }); }; return { registerComplexWatchers, registerNormalWatchers }; } function useRender(props, slots, owner) { const instance = getCurrentInstance(); const columnId = ref(""); const isSubColumn = ref(false); const realAlign = ref(); const realHeaderAlign = ref(); watchEffect(() => { realAlign.value = !!props.align ? "is-" + props.align : null; realAlign.value; }); watchEffect(() => { realHeaderAlign.value = !!props.headerAlign ? "is-" + props.headerAlign : realAlign.value; realHeaderAlign.value; }); const columnOrTableParent = computed(() => { let parent = instance.vnode.vParent || instance.parent; while (parent && !parent.tableId && !parent.columnId) { parent = parent.vnode.vParent || parent.parent; } return parent; }); const realWidth = ref(parseWidth(props.width)); const realMinWidth = ref(parseMinWidth(props.minWidth)); const setColumnWidth = (column) => { if (realWidth.value) column.width = realWidth.value; if (realMinWidth.value) { column.minWidth = realMinWidth.value; } if (!column.minWidth) { column.minWidth = 80; } column.realWidth = Number(column.width === void 0 ? column.minWidth : column.width); return column; }; const setColumnForcedProps = (column) => { const type = column.type; const source = cellForced[type] || {}; Object.keys(source).forEach((prop) => { const value = source[prop]; if (value !== void 0) { column[prop] = prop === "className" ? `${column[prop]} ${value}` : value; } }); return column; }; const checkSubColumn = (children) => { if (children instanceof Array) { children.forEach((child) => check(child)); } else { check(children); } function check(item) { var _a; if (((_a = item == null ? void 0 : item.type) == null ? void 0 : _a.name) === "ElTableColumn") { item.vParent = instance; } } }; const setColumnRenders = (column) => { if (props.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."); } else if (column.type !== "selection") { column.renderHeader = (scope) => { instance.columnConfig.value["label"]; const renderHeader = slots.header; return renderHeader ? renderHeader(scope) : column.label; }; } let originRenderCell = column.renderCell; if (column.type === "expand") { column.renderCell = (data) => h("div", { class: "cell" }, [originRenderCell(data)]); owner.value.renderExpanded = (data) => { return slots.default ? slots.default(data) : slots.default; }; } else { originRenderCell = originRenderCell || defaultRenderCell; column.renderCell = (data) => { let children = null; if (slots.default) { children = slots.default(data); } else { children = originRenderCell(data); } const prefix = treeCellPrefix(data); const props2 = { class: "cell", style: {} }; if (column.showOverflowTooltip) { props2.class += " el-tooltip"; props2.style = { width: (data.column.realWidth || Number(data.column.width)) - 1 + "px" }; } checkSubColumn(children); return h("div", props2, [prefix, children]); }; } return column; }; const getPropsData = (...propsKey) => { return propsKey.reduce((prev, cur) => { if (Array.isArray(cur)) { cur.forEach((key) => { prev[key] = props[key]; }); } return prev; }, {}); }; const getColumnElIndex = (children, child) => { return [].indexOf.call(children, child); }; return { columnId, realAlign, isSubColumn, realHeaderAlign, columnOrTableParent, setColumnWidth, setColumnForcedProps, setColumnRenders, getPropsData, getColumnElIndex }; } var defaultProps = { type: { type: String, default: "default" }, label: String, className: String, labelClassName: String, property: String, prop: String, width: { type: [String, Number], default: "" }, minWidth: { type: [String, Number], default: "" }, renderHeader: Function, sortable: { type: [Boolean, String], default: false }, sortMethod: Function, sortBy: [String, Function, Array], resizable: { type: Boolean, default: true }, columnKey: String, align: String, headerAlign: String, showTooltipWhenOverflow: Boolean, showOverflowTooltip: Boolean, fixed: [Boolean, String], formatter: Function, selectable: Function, reserveSelection: Boolean, filterMethod: Function, filteredValue: Array, filters: Array, filterPlacement: String, filterMultiple: { type: Boolean, default: true }, index: [Number, Function], sortOrders: { type: Array, default: () => { return ["ascending", "descending", null]; }, validator: (val) => { return val.every((order) => ["ascending", "descending", null].indexOf(order) > -1); } } }; var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); let columnIdSeed = 1; var ElTableColumn = defineComponent({ name: "ElTableColumn", components: { ElCheckbox }, props: defaultProps, setup(props, { slots }) { const instance = getCurrentInstance(); const columnConfig = ref({}); const owner = computed(() => { let parent2 = instance.parent; while (parent2 && !parent2.tableId) { parent2 = parent2.parent; } return parent2; }); const { registerNormalWatchers, registerComplexWatchers } = useWatcher(owner, props); const { columnId, isSubColumn, realHeaderAlign, columnOrTableParent, setColumnWidth, setColumnForcedProps, setColumnRenders, getPropsData, getColumnElIndex, realAlign } = useRender(props, slots, owner); const parent = columnOrTableParent.value; columnId.value = (parent.tableId || parent.columnId) + "_column_" + columnIdSeed++; onBeforeMount(() => { isSubColumn.value = owner.value !== parent; const type = props.type || "default"; const sortable = props.sortable === "" ? true : props.sortable; const defaults = __spreadProps(__spreadValues({}, cellStarts[type]), { id: columnId.value, type, property: props.prop || props.property, align: realAlign, headerAlign: realHeaderAlign, showOverflowTooltip: props.showOverflowTooltip || props.showTooltipWhenOverflow, filterable: props.filters || props.filterMethod, filteredValue: [], filterPlacement: "", isColumnGroup: false, filterOpened: false, sortable, index: props.index, rawColumnKey: instance.vnode.key }); const basicProps = [ "columnKey", "label", "className", "labelClassName", "type", "renderHeader", "formatter", "fixed", "resizable" ]; const sortProps = ["sortMethod", "sortBy", "sortOrders"]; const selectProps = ["selectable", "reserveSelection"]; const filterProps = [ "filterMethod", "filters", "filterMultiple", "filterOpened", "filteredValue", "filterPlacement" ]; let column = getPropsData(basicProps, sortProps, selectProps, filterProps); column = mergeOptions(defaults, column); const chains = compose(setColumnRenders, setColumnWidth, setColumnForcedProps); column = chains(column); columnConfig.value = column; registerNormalWatchers(); registerComplexWatchers(); }); onMounted(() => { var _a; const parent2 = columnOrTableParent.value; const children = isSubColumn.value ? parent2.vnode.el.children : (_a = parent2.refs.hiddenColumns) == null ? void 0 : _a.children; const getColumnIndex = () => getColumnElIndex(children || [], instance.vnode.el); columnConfig.value.getColumnIndex = getColumnIndex; const columnIndex = getColumnIndex(); columnIndex > -1 && owner.value.store.commit("insertColumn", columnConfig.value, isSubColumn.value ? parent2.columnConfig.value : null); }); onBeforeUnmount(() => { owner.value.store.commit("removeColumn", columnConfig.value, isSubColumn.value ? parent.columnConfig.value : null); }); instance.columnId = columnId.value; instance.columnConfig = columnConfig; return; }, render() { var _a, _b, _c; let children = []; try { const renderDefault = (_b = (_a = this.$slots).default) == null ? void 0 : _b.call(_a, { row: {}, column: {}, $index: -1 }); if (renderDefault instanceof Array) { for (const childNode of renderDefault) { if (((_c = childNode.type) == null ? void 0 : _c.name) === "ElTableColumn") { children.push(childNode); } else if (childNode.type === Fragment && childNode.children instanceof Array) { children.push(...childNode.children); } } } } catch (e) { children = []; } return h("div", children); } }); const _TableColumn = ElTableColumn; _TableColumn.install = (app) => { app.component(_TableColumn.name, _TableColumn); }; export default _TableColumn;