UNPKG

4.61 kBJavaScriptView Raw
1import DescriptionsRow from './descriptions-row';
2import { isFunction } from 'element-ui/src/utils/types';
3
4export default {
5 name: 'ElDescriptions',
6 components: {
7 [DescriptionsRow.name]: DescriptionsRow
8 },
9 props: {
10 border: {
11 type: Boolean,
12 default: false
13 },
14 column: {
15 type: Number,
16 default: 3
17 },
18 direction: {
19 type: String,
20 default: 'horizontal'
21 },
22 size: {
23 type: String
24 // validator: isValidComponentSize,
25 },
26 title: {
27 type: String,
28 default: ''
29 },
30 extra: {
31 type: String,
32 default: ''
33 },
34 labelStyle: {
35 type: Object
36 },
37 contentStyle: {
38 type: Object
39 },
40 labelClassName: {
41 type: String,
42 default: ''
43 },
44 contentClassName: {
45 type: String,
46 default: ''
47 },
48 colon: {
49 type: Boolean,
50 default: true
51 }
52 },
53 computed: {
54 descriptionsSize() {
55 return this.size || (this.$ELEMENT || {}).size;
56 }
57 },
58 provide() {
59 return {
60 elDescriptions: this
61 };
62 },
63 methods: {
64 getOptionProps(vnode) {
65 if (vnode.componentOptions) {
66 const componentOptions = vnode.componentOptions;
67 const { propsData = {}, Ctor = {} } = componentOptions;
68 const props = (Ctor.options || {}).props || {};
69 const res = {};
70 for (const k in props) {
71 const v = props[k];
72 const defaultValue = v.default;
73 if (defaultValue !== undefined) {
74 res[k] = isFunction(defaultValue) ? defaultValue.call(vnode) : defaultValue;
75 }
76 }
77 return { ...res, ...propsData };
78 }
79 return {};
80 },
81 getSlots(vnode) {
82 let componentOptions = vnode.componentOptions || {};
83 const children = vnode.children || componentOptions.children || [];
84 const slots = {};
85 children.forEach(child => {
86 if (!this.isEmptyElement(child)) {
87 const name = (child.data && child.data.slot) || 'default';
88 slots[name] = slots[name] || [];
89 if (child.tag === 'template') {
90 slots[name].push(child.children);
91 } else {
92 slots[name].push(child);
93 }
94 }
95 });
96 return { ...slots };
97 },
98 isEmptyElement(c) {
99 return !(c.tag || (c.text && c.text.trim() !== ''));
100 },
101 filledNode(node, span, count, isLast = false) {
102 if (!node.props) {
103 node.props = {};
104 }
105 if (span > count) {
106 node.props.span = count;
107 }
108 if (isLast) {
109 // set the max span, cause of the last td
110 node.props.span = count;
111 }
112 return node;
113 },
114 getRows() {
115 const children = ((this.$slots.default || []).filter(vnode => vnode.tag &&
116 vnode.componentOptions && vnode.componentOptions.Ctor.options.name === 'ElDescriptionsItem'));
117 const nodes = children.map(vnode => {
118 return {
119 props: this.getOptionProps(vnode),
120 slots: this.getSlots(vnode),
121 vnode
122 };
123 });
124 const rows = [];
125 let temp = [];
126 let count = this.column;
127
128 nodes.forEach((node, index) => {
129 const span = node.props.span || 1;
130
131 if (index === children.length - 1) {
132 temp.push(this.filledNode(node, span, count, true));
133 rows.push(temp);
134 return;
135 }
136
137 if (span < count) {
138 count -= span;
139 temp.push(node);
140 } else {
141 temp.push(this.filledNode(node, span, count));
142 rows.push(temp);
143 count = this.column;
144 temp = [];
145 }
146 });
147
148 return rows;
149 }
150 },
151 render() {
152 const { title, extra, border, descriptionsSize, $slots } = this;
153 const rows = this.getRows();
154
155 return (
156 <div class="el-descriptions">
157 {
158 (title || extra || $slots.title || $slots.extra)
159 ? <div class="el-descriptions__header">
160 <div class="el-descriptions__title">
161 { $slots.title ? $slots.title : title}
162 </div>
163 <div class="el-descriptions__extra">
164 { $slots.extra ? $slots.extra : extra }
165 </div>
166 </div>
167 : null
168 }
169
170 <div class="el-descriptions__body">
171 <table class={['el-descriptions__table', {'is-bordered': border}, descriptionsSize ? `el-descriptions--${descriptionsSize}` : '']}>
172 {rows.map(row => (
173 <DescriptionsRow row={row}></DescriptionsRow>
174 ))}
175 </table>
176 </div>
177 </div>
178 );
179 }
180};