diff --git a/packages/descriptions/__tests__/descriptions.spec.ts b/packages/descriptions/__tests__/descriptions.spec.ts index 6dccdaa780..6d3d8dd156 100644 --- a/packages/descriptions/__tests__/descriptions.spec.ts +++ b/packages/descriptions/__tests__/descriptions.spec.ts @@ -37,6 +37,50 @@ describe('Descriptions.vue', () => { expect(wrapper.find('table').classes()).toContain('is-bordered') }) + test('should render align props', () => { + const wrapper = _mount(` + + {{ item }} + + `) + + expect(wrapper.find('.el-descriptions__label').classes()).toContain('is-center') + expect(wrapper.find('.el-descriptions__content').classes()).toContain('is-right') + }) + + test('should render width props', () => { + const wrapper = _mount(` + + {{ item }} + + `) + + expect(wrapper.find('.el-descriptions__label').attributes('style')).toContain('width: 50px; min-width: 60px;') + expect(wrapper.find('.el-descriptions__content').attributes('style')).toContain('width: 50px; min-width: 60px;') + }) + + test('should render class props', () => { + const wrapper = _mount(` + + {{ item }} + + `) + + expect(wrapper.find('.el-descriptions__label').classes()).toContain('label-class-name') + expect(wrapper.find('.el-descriptions__content').classes()).toContain('class-name') + }) + + test('should render width props', () => { + const wrapper = _mount(` + + {{ item }} + + `) + + expect(wrapper.find('.el-descriptions__label').attributes('style')).toContain('width: 50px; min-width: 60px;') + expect(wrapper.find('.el-descriptions__content').attributes('style')).toContain('width: 50px; min-width: 60px;') + }) + test('should render column props', async () => { const wrapper = _mount(` @@ -110,7 +154,7 @@ describe('Descriptions.vue', () => { remarks: ['school', 'hospital'], } }, { - onClick () { + onClick() { this.remarks[0] = CHANGE_VALUE }, }) diff --git a/packages/descriptions/src/description-item.ts b/packages/descriptions/src/description-item.ts index 92981c294c..964dacfa78 100644 --- a/packages/descriptions/src/description-item.ts +++ b/packages/descriptions/src/description-item.ts @@ -2,4 +2,38 @@ import { defineComponent } from 'vue' export default defineComponent({ name: 'ElDescriptionsItem', + props: { + label: { + type: String, + default: '1', + }, + span: { + type: Number, + default: 1, + }, + width: { + type: [String, Number], + default: '', + }, + minWidth: { + type: [String, Number], + default: '', + }, + align: { + type: String, + default: 'left', + }, + labelAlign: { + type: String, + default: '', + }, + className: { + type: String, + default: '', + }, + labelClassName: { + type: String, + default: '', + }, + }, }) diff --git a/packages/descriptions/src/descriptions-cell.ts b/packages/descriptions/src/descriptions-cell.ts index 027b976aa9..739cd18f88 100644 --- a/packages/descriptions/src/descriptions-cell.ts +++ b/packages/descriptions/src/descriptions-cell.ts @@ -1,5 +1,10 @@ -import { computed, defineComponent, h, inject } from 'vue' -import { elDescriptionsKey, IDescriptionsInject } from './descriptions.type' +import { defineComponent, h, inject } from 'vue' +import { addUnit } from '@element-plus/utils/util' +import { getNormalizedProps } from '@element-plus/utils/vnode' +import { elDescriptionsKey } from './descriptions.type' + +import type { VNode } from 'vue' +import type { IDescriptionsInject, IDescriptionsItemInject } from './descriptions.type' export default defineComponent({ name: 'ElDescriptionsCell', @@ -14,42 +19,53 @@ export default defineComponent({ type: String, }, }, - setup(props) { + setup() { const descriptions = inject(elDescriptionsKey, {} as IDescriptionsInject) - const label = computed(() => props.cell?.children?.label?.() || props.cell?.props?.label) - const content = computed(() => props.cell?.children?.default?.()) - const span = computed(() => props.cell?.props?.span || 1) - return { descriptions, - label: label, - content: content, - span: span, } }, render() { + const item = getNormalizedProps(this.cell as VNode) as IDescriptionsItemInject + + const label = this.cell?.children?.label?.() || item.label + const content = this.cell?.children?.default?.() + const span = item.span + const align = item.align ? `is-${item.align}` : '' + const labelAlign = item.labelAlign ? `is-${item.labelAlign}` : '' || align + const className = item.className + const labelClassName = item.labelClassName + const style = { + width: addUnit(item.width), + minWidth: addUnit(item.minWidth), + } + switch (this.type) { case 'label': return h(this.tag, { - class: ['el-descriptions__label', { 'is-bordered-label': this.descriptions.border }], - colSpan: this.descriptions.direction === 'vertical' ? this.span : 1, - }, this.label) + style: style, + class: ['el-descriptions__label', { 'is-bordered-label': this.descriptions.border }, labelAlign, labelClassName], + colSpan: this.descriptions.direction === 'vertical' ? span : 1, + }, label) case 'content': return h(this.tag, { - class: 'el-descriptions__content', - colSpan: this.descriptions.direction === 'vertical' ? this.span : this.span * 2 - 1, - }, this.content) + style: style, + class: ['el-descriptions__content', align, className], + colSpan: this.descriptions.direction === 'vertical' ? span : span * 2 - 1, + }, content) default: return h('td', { - colSpan: this.span, + style: style, + class: [align], + colSpan: span, }, [ h('span', { - class: ['el-descriptions__label', { 'is-bordered-label': this.descriptions.border }], - }, this.label), + class: ['el-descriptions__label', labelClassName], + }, label), h('span', { - class: 'el-descriptions__content', - }, this.content)]) + class: ['el-descriptions__content', className], + }, content)]) } }, }) diff --git a/packages/descriptions/src/descriptions-row.vue b/packages/descriptions/src/descriptions-row.vue index b3e5d97d4e..1decc93c04 100644 --- a/packages/descriptions/src/descriptions-row.vue +++ b/packages/descriptions/src/descriptions-row.vue @@ -30,7 +30,8 @@