mirror of
https://github.com/element-plus/element-plus.git
synced 2026-03-13 07:51:17 +08:00
feat(components): [virtual-table] empty renderer (#7308)
- Add Empty component. - Add empty render conditions. - Add empty rendering to table-v2.
This commit is contained in:
19
packages/components/table-v2/src/renderers/empty.tsx
Normal file
19
packages/components/table-v2/src/renderers/empty.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import ElEmpty from '@element-plus/components/empty'
|
||||
import type { CSSProperties, FunctionalComponent } from 'vue'
|
||||
|
||||
type EmptyRendererProps = {
|
||||
class?: JSX.IntrinsicAttributes['class']
|
||||
style?: CSSProperties
|
||||
}
|
||||
|
||||
const Footer: FunctionalComponent<EmptyRendererProps> = (props, { slots }) => {
|
||||
return (
|
||||
<div class={props.class} style={props.style}>
|
||||
{slots.default ? slots.default() : <ElEmpty />}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Footer.displayName = 'ElTableV2Empty'
|
||||
|
||||
export default Footer
|
||||
@@ -3,7 +3,7 @@ import HeaderCell from '../table-header-cell'
|
||||
import SortIcon from '../sort-icon'
|
||||
import { Alignment, SortOrder, oppositeOrderMap } from '../constants'
|
||||
import { placeholderSign } from '../private'
|
||||
import { componentToSlot, tryCall } from '../utils'
|
||||
import { componentToSlot, enforceUnit, tryCall } from '../utils'
|
||||
|
||||
import type { FunctionalComponent, UnwrapNestedRefs } from 'vue'
|
||||
import type { UseNamespaceReturn } from '@element-plus/hooks'
|
||||
@@ -42,7 +42,7 @@ const HeaderCellRenderer: FunctionalComponent<HeaderCellRendererProps> = (
|
||||
onColumnSorted,
|
||||
} = props
|
||||
|
||||
const style = columnsStyles[column.key]
|
||||
const style = enforceUnit(columnsStyles[column.key])
|
||||
|
||||
if (column.placeholderSign === placeholderSign) {
|
||||
return <div class={ns.em('header-row-cell', 'placeholder')} style={style} />
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { FunctionalComponent } from 'vue'
|
||||
import type { TableV2HeaderCell } from './header-cell'
|
||||
|
||||
const HeaderCell = (props: TableV2HeaderCell, { slots }) =>
|
||||
const HeaderCell: FunctionalComponent<TableV2HeaderCell> = (props, { slots }) =>
|
||||
slots.default ? (
|
||||
slots.default(props)
|
||||
) : (
|
||||
@@ -9,6 +10,6 @@ const HeaderCell = (props: TableV2HeaderCell, { slots }) =>
|
||||
</div>
|
||||
)
|
||||
|
||||
HeaderCell.componentName = 'ElTableV2HeaderCell'
|
||||
HeaderCell.displayName = 'ElTableV2HeaderCell'
|
||||
|
||||
export default HeaderCell
|
||||
|
||||
@@ -12,6 +12,7 @@ import Cell from './renderers/cell'
|
||||
import Header from './renderers/header'
|
||||
import HeaderCell from './renderers/header-cell'
|
||||
import Footer from './renderers/footer'
|
||||
import Empty from './renderers/empty'
|
||||
|
||||
import type { TableGridRowSlotParams } from './table-grid'
|
||||
import type { TableV2RowCellRenderParam } from './table-row'
|
||||
@@ -49,10 +50,13 @@ const TableV2 = defineComponent({
|
||||
isScrolling,
|
||||
|
||||
bodyWidth,
|
||||
emptyStyle,
|
||||
rootStyle,
|
||||
headerWidth,
|
||||
footerHeight,
|
||||
|
||||
showEmpty,
|
||||
|
||||
getRowHeight,
|
||||
onColumnSorted,
|
||||
onRowHeightChange,
|
||||
@@ -271,6 +275,11 @@ const TableV2 = defineComponent({
|
||||
<LeftTable {...leftTableProps}>{tableSlots}</LeftTable>
|
||||
<RightTable {...rightTableProps}>{tableSlots}</RightTable>
|
||||
<Footer {...footerProps}>{{ default: slots.footer }}</Footer>
|
||||
{unref(showEmpty) && (
|
||||
<Empty class={ns.e('empty')} style={unref(emptyStyle)}>
|
||||
{{ default: slots.empty }}
|
||||
</Empty>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
watch,
|
||||
} from 'vue'
|
||||
import { debounce } from 'lodash-unified'
|
||||
import { isNumber, isObject } from '@element-plus/utils'
|
||||
import { addUnit, isArray, isNumber, isObject } from '@element-plus/utils'
|
||||
import { enforceUnit, sum } from './utils'
|
||||
import { useColumns } from './use-columns'
|
||||
import { FixedDir, SortOrder, oppositeOrderMap } from './constants'
|
||||
@@ -116,6 +116,14 @@ function useTable(props: TableV2Props) {
|
||||
return expandColumnKey ? unref(flattenedData) : data
|
||||
})
|
||||
|
||||
const showEmpty = computed(() => {
|
||||
const noData = unref(data).length === 0
|
||||
|
||||
return isArray(props.fixedData)
|
||||
? props.fixedData.length === 0 && noData
|
||||
: noData
|
||||
})
|
||||
|
||||
const isDynamic = computed(() => isNumber(props.estimatedRowHeight))
|
||||
|
||||
const bodyWidth = computed(() => {
|
||||
@@ -157,6 +165,12 @@ function useTable(props: TableV2Props) {
|
||||
enforceUnit({ height: props.footerHeight })
|
||||
)
|
||||
|
||||
const emptyStyle = computed<CSSProperties>(() => ({
|
||||
top: addUnit(unref(headerHeight)),
|
||||
bottom: addUnit(props.footerHeight),
|
||||
width: addUnit(props.width),
|
||||
}))
|
||||
|
||||
const fixedTableHeight = computed(() => {
|
||||
const { maxHeight } = props
|
||||
const tableHeight = unref(mainTableHeight)
|
||||
@@ -423,6 +437,7 @@ function useTable(props: TableV2Props) {
|
||||
mainColumns,
|
||||
// metadata
|
||||
bodyWidth,
|
||||
emptyStyle,
|
||||
rootStyle,
|
||||
headerWidth,
|
||||
footerHeight,
|
||||
@@ -430,6 +445,8 @@ function useTable(props: TableV2Props) {
|
||||
fixedTableHeight,
|
||||
leftTableWidth,
|
||||
rightTableWidth,
|
||||
// flags
|
||||
showEmpty,
|
||||
|
||||
// methods
|
||||
getRowHeight,
|
||||
|
||||
@@ -118,6 +118,11 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@include e('empty') {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
@include e('header-row') {
|
||||
display: flex;
|
||||
border-bottom: getCssVar('table', 'border');
|
||||
|
||||
Reference in New Issue
Block a user