Feat/scoped slot table (#1844)

* Upgrade to vue 2.1.0

* Table: support scoped slots, resolve #1763, #1161

* Update vue version

* fix test

* fix test

* Update doc

* Fix english docs
pull/1913/merge
cinwell.li 2016-12-20 10:47:16 +08:00 committed by baiyaaaaa
parent cecf9eb8d5
commit 339dada583
8 changed files with 73 additions and 99 deletions

View File

@ -8,7 +8,7 @@ cooking.set({
extends: process.env.CI_ENV ? ['vue2'] : ['vue2', 'lint'],
minimize: false,
alias: Object.assign(config.alias, {
'vue$': 'vue/dist/vue.js'
'vue$': 'vue/dist/vue.common.js'
}),
postcss: function(webapck) {
return [

View File

@ -45,7 +45,7 @@ Typical configurations for these config files are:
},
"dependencies": {
"element-ui": "^1.0.0",
"vue": "^2.0.5"
"vue": "^2.1.6"
},
"devDependencies": {
"babel-core": "^6.0.0",

View File

@ -568,15 +568,13 @@ When there are too many columns, you can fix some of them.
width="120">
</el-table-column>
<el-table-column
inline-template
:context="_self"
fixed="right"
label="Operations"
width="120">
<span>
<template scope="scope">
<el-button @click="handleClick" type="text" size="small">Detail</el-button>
<el-button type="text" size="small">Edit</el-button>
</span>
</template>
</el-table-column>
</el-table>
</template>
@ -781,19 +779,17 @@ When the the data is dynamically changed, you might want the table to have a max
width="120">
</el-table-column>
<el-table-column
inline-template
:context="_self"
fixed="right"
label="Operations"
width="120">
<span>
<template scope="scope">
<el-button
@click.native.prevent="deleteRow($index, tableData4)"
@click.native.prevent="deleteRow(scope.$index, tableData4)"
type="text"
size="small">
Remove
</el-button>
</span>
</template>
</el-table-column>
</el-table>
</template>
@ -1045,13 +1041,12 @@ Single row selection is supported.
You can also select multiple rows.
:::demo Activating multiple selection is easy: simply add an `el-table-column` with its `type` set to `selection`. Apart from multiple selection, this example also uses `inline-template` and `show-overflow-tooltip`: when the attribute `inline-template` is set, you can use custom template inside `el-table-column`, and access current row data via `row`; by default, if the content is too long, it will break into multiple lines. If you want to keep it in one line, use attribute `show-overflow-tooltip`, which accepts a `Boolean` value. When set `true`, the extra content will show in tooltip when hover on the cell.
:::demo Activating multiple selection is easy: simply add an `el-table-column` with its `type` set to `selection`. Apart from multiple selection, this example also uses `show-overflow-tooltip`: by default, if the content is too long, it will break into multiple lines. If you want to keep it in one line, use attribute `show-overflow-tooltip`, which accepts a `Boolean` value. When set `true`, the extra content will show in tooltip when hover on the cell.
```html
<template>
<el-table
:data="tableData3"
border
selection-mode="multiple"
style="width: 100%"
@selection-change="handleSelectionChange">
<el-table-column
@ -1059,10 +1054,9 @@ You can also select multiple rows.
width="55">
</el-table-column>
<el-table-column
inline-template
label="Date"
width="120">
<div>{{ row.date }}</div>
<template scope="scope">{{ scope.row.date }}</template>
</el-table-column>
<el-table-column
property="name"
@ -1219,9 +1213,12 @@ Filter the table to find desired data.
label="Tag"
width="100"
:filters="[{ text: 'Home', value: 'Home' }, { text: 'Office', value: 'Office' }]"
:filter-method="filterTag"
inline-template>
<el-tag :type="row.tag === 'Home' ? 'primary' : 'success'" close-transition>{{row.tag}}</el-tag>
:filter-method="filterTag">
<template scope="scope">
<el-tag
:type="scope.row.tag === 'Home' ? 'primary' : 'success'"
close-transition>{{scope.row.tag}}</el-tag>
</template>
</el-table-column>
</el-table>
</template>
@ -1269,7 +1266,7 @@ Filter the table to find desired data.
### Custom column template
Customize table column so it can be integrated with other components.
:::demo Activate custom column template by adding the `inline-template` attribute. By default, the context of `el-table-column` is the one where `el-table` lies, and you can customize it with the `context` attribute, e.g. `:context="_self"` refers to the current context. This is useful when sometimes Table is encapsulated into another component, and `table-column` is distributed by slots. In `el-column`, you have access to the following data: row, column, $index and store (state management of Table).
:::demo You have access to the following data: row, column, $index and store (state management of Table) by [Scoped slot](https://vuejs.org/v2/guide/components.html#Scoped-Slots). (Scoped slots is supported from `1.1`, `inline-template` still works, but it's not recommended).
```html
<template>
<el-table
@ -1277,43 +1274,38 @@ Customize table column so it can be integrated with other components.
border
style="width: 100%">
<el-table-column
inline-template
label="Date"
width="180">
<div>
<template scope="scope">
<el-icon name="time"></el-icon>
<span style="margin-left: 10px">{{ row.date }}</span>
</div>
<span style="margin-left: 10px">{{ scope.row.date }}</span>
</template>
</el-table-column>
<el-table-column
inline-template
label="Name"
width="180">
<el-popover trigger="hover" placement="top">
<p>Name: {{ row.name }}</p>
<p>Addr: {{ row.address }}</p>
<div slot="reference" class="name-wrapper">
<el-tag>{{ row.name }}</el-tag>
</div>
</el-popover>
<template scope="scope">
<el-popover trigger="hover" placement="top">
<p>Name: {{ scope.row.name }}</p>
<p>Addr: {{ scope.row.address }}</p>
<div slot="reference" class="name-wrapper">
<el-tag>{{ scope.row.name }}</el-tag>
</div>
</el-popover>
</template>
</el-table-column>
<el-table-column
:context="_self"
inline-template
label="Operations">
<div>
<template scope="scope">
<el-button
size="small"
@click="handleEdit($index, row)">
Edit
</el-button>
@click="handleEdit(scope.$index, scope.row)">Edit</el-button>
<el-button
size="small"
type="danger"
@click="handleDelete($index, row)">
Delete
</el-button>
</div>
@click="handleDelete(scope.$index, scope.row)">Delete</el-button>
</template>
</el-table-column>
</el-table>
</template>
@ -1410,8 +1402,6 @@ Customize table column so it can be integrated with other components.
| resizable | whether column width can be resized, works when `border` of `el-table` is `true` | boolean | — | false |
| formatter | function that formats content | Function(row, column) | — | — |
| show-overflow-tooltip | whether to hide extra content and show them in a tooltip when hovering on the cell | boolean | — | false |
| context | context of Table-column, e.g. `_self` refers to the current context, `$parent` parent context, `$root` root context | Object | - | current context where Table lies |
| inline-template | by using this attribute, you can customize column template. Row data can be accessed by `row` object. In your template, you have access to the following: `{ row (current row), column (current column), $index (row index), store (table store) }` | — | — |
| align | alignment | string | left/center/right | left |
| class-name | class name of cells in the column | string | — | — |
| selectable | function that determines if a certain row can be selected, works when `type` is 'selection' | Function(row, index) | — | — |

View File

@ -45,7 +45,7 @@
},
"dependencies": {
"element-ui": "^1.0.0",
"vue": "^2.0.5"
"vue": "^2.1.6"
},
"devDependencies": {
"babel-core": "^6.0.0",

View File

@ -581,15 +581,13 @@
width="120">
</el-table-column>
<el-table-column
inline-template
:context="_self"
fixed="right"
label="操作"
width="100">
<span>
<template scope="scope">
<el-button @click="handleClick" type="text" size="small">查看</el-button>
<el-button type="text" size="small">编辑</el-button>
</span>
</template>
</el-table-column>
</el-table>
</template>
@ -791,19 +789,17 @@
width="120">
</el-table-column>
<el-table-column
inline-template
:context="_self"
fixed="right"
label="操作"
width="120">
<span>
<template scope="scope">
<el-button
@click.native.prevent="deleteRow($index, tableData4)"
@click.native.prevent="deleteRow(scope.$index, tableData4)"
type="text"
size="small">
移除
</el-button>
</span>
</template>
</el-table-column>
</el-table>
</template>
@ -1055,7 +1051,7 @@
选择多行数据时使用 Checkbox。
:::demo 实现多选非常简单: 手动添加一个`el-table-column`,设`type`属性为`selection`即可。在本例中,为了方便说明其他属性,我们还使用了`inline-template`和`show-overflow-tooltip`:设置了`inline-template`属性后,可以通过调用`row`对象中的值取代`prop`属性的设置;默认情况下若内容过多会折行显示,若需要单行显示可以使用`show-overflow-tooltip`属性,它接受一个`Boolean`,为`true`时多余的内容会在 hover 时以 tooltip 的形式显示出来。
:::demo 实现多选非常简单: 手动添加一个`el-table-column`,设`type`属性为`selection`即可;默认情况下若内容过多会折行显示,若需要单行显示可以使用`show-overflow-tooltip`属性,它接受一个`Boolean`,为`true`时多余的内容会在 hover 时以 tooltip 的形式显示出来。
```html
<template>
<el-table
@ -1068,10 +1064,9 @@
width="55">
</el-table-column>
<el-table-column
inline-template
label="日期"
width="120">
<div>{{ row.date }}</div>
<template scope="scope">{{ scope.row.date }}</template>
</el-table-column>
<el-table-column
prop="name"
@ -1228,9 +1223,12 @@
label="标签"
width="100"
:filters="[{ text: '家', value: '家' }, { text: '公司', value: '公司' }]"
:filter-method="filterTag"
inline-template>
<el-tag :type="row.tag === '家' ? 'primary' : 'success'" close-transition>{{row.tag}}</el-tag>
:filter-method="filterTag">
<template scope="scope">
<el-tag
:type="scope.row.tag === '家' ? 'primary' : 'success'"
close-transition>{{scope.row.tag}}</el-tag>
</template>
</el-table-column>
</el-table>
</template>
@ -1278,7 +1276,7 @@
### 自定义列模板
自定义列的显示内容,可组合其他组件使用。
:::demo 通过设置 `inline-template` 属性可以开启自定义模板功能,此时 `el-table-column` 的上下文指的是 `el-table` 所处的上下文,当然你可以通过 `context` 属性指定上下文环境,例如设置成 `:context="_self"` 就是指的当前上下文。有些时候我们会把 table 封装在其他组件里,通过 slot 设置 `table-column`,这样的话就要注意设置 `context`。在 column 组件内部,可以获取到 row, column, $index 和 storetable 内部的状态管理)的数据。
:::demo 通过 `Scoped slot` 可以获取到 row, column, $index 和 storetable 内部的状态管理)的数据,用法参考 demo。(`1.1` 后支持通过 [Scoped slot](https://vuejs.org/v2/guide/components.html#Scoped-Slots) 自定义模板。之前的 `inline-template` 同样适用,但不推荐。)
```html
<template>
<el-table
@ -1286,43 +1284,36 @@
border
style="width: 100%">
<el-table-column
inline-template
label="日期"
width="180">
<div>
<template scope="scope">
<el-icon name="time"></el-icon>
<span style="margin-left: 10px">{{ row.date }}</span>
</div>
<span style="margin-left: 10px">{{ scope.row.date }}</span>
</template>
</el-table-column>
<el-table-column
inline-template
label="姓名"
width="180">
<el-popover trigger="hover" placement="top">
<p>姓名: {{ row.name }}</p>
<p>住址: {{ row.address }}</p>
<div slot="reference" class="name-wrapper">
<el-tag>{{ row.name }}</el-tag>
</div>
</el-popover>
<template scope="scope">
<el-popover trigger="hover" placement="top">
<p>姓名: {{ scope.row.name }}</p>
<p>住址: {{ scope.row.address }}</p>
<div slot="reference" class="name-wrapper">
<el-tag>{{ scope.row.name }}</el-tag>
</div>
</el-popover>
</template>
</el-table-column>
<el-table-column
:context="_self"
inline-template
label="操作">
<div>
<el-table-column label="操作">
<template scope="scope">
<el-button
size="small"
@click="handleEdit($index, row)">
编辑
</el-button>
@click="handleEdit(scope.$index, scope.row)">编辑</el-button>
<el-button
size="small"
type="danger"
@click="handleDelete($index, row)">
删除
</el-button>
</div>
@click="handleDelete(scope.$index, scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</template>
@ -1418,8 +1409,6 @@
| resizable | 对应列是否可以通过拖动改变宽度(需要在 el-table 上设置 border 属性为真) | boolean | — | true |
| formatter | 用来格式化内容 | Function(row, column) | — | — |
| show-overflow-tooltip | 当内容过长被隐藏时显示 tooltip | Boolean | — | false |
| context | 设置上下文环境,例如设置当前上下文就是 `_self`,父级就是 `$parent`,根组件 `$root` | Object | - | Table 所处上下文 |
| inline-template | 指定该属性后可以自定义 column 模板,参考多选的时间列,通过 row 获取行信息。总共可以获取到 `{ row(当前行), column(当前列), $index(行数), store(table store) }` 以及 Table 所处的上下文环境。 | — | — |
| align | 对齐方式 | String | left, center, right | left |
| class-name | 列的 className | string | — | — |
| selectable | 仅对 type=selection 的列有效,类型为 FunctionFunction 的返回值用来决定这一行的 CheckBox 是否可以勾选 | Function(row, index) | — | — |

View File

@ -8,7 +8,7 @@
</head>
<body>
<div id="app"></div><% if (process.env.NODE_ENV === 'production') { %>
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.0.7/vue.runtime.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.1.6/vue.runtime.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/vue-router/2.0.1/vue-router.min.js"></script><% } %>
</body>
<% if (process.env.NODE_ENV === 'production') { %><script>

View File

@ -50,7 +50,7 @@
"wind-dom": "0.0.3"
},
"peerDependencies": {
"vue": "^2.0.0"
"vue": "^2.1.6"
},
"devDependencies": {
"babel-cli": "^6.14.0",
@ -64,7 +64,7 @@
"cheerio": "^0.18.0",
"cooking": "^1.2.0",
"cooking-lint": "^0.1.3",
"cooking-vue2": "^0.1.4",
"cooking-vue2": "^0.3.0",
"coveralls": "^2.11.14",
"cp-cli": "^1.0.2",
"cross-env": "^3.1.3",
@ -111,11 +111,11 @@
"transliteration": "^1.1.11",
"uppercamelcase": "^1.1.0",
"url-loader": "^0.5.7",
"vue": "2.0.5",
"vue-loader": "^9.9.0",
"vue": "2.1.6",
"vue-loader": "^10.0.2",
"vue-markdown-loader": "^0.5.1",
"vue-router": "^2.0.0",
"vue-template-compiler": "2.0.5",
"vue-template-compiler": "2.1.6",
"webpack": "^1.13.2",
"webpack-dev-server": "^1.15.1",
"webpack-node-externals": "^1.5.4"

View File

@ -128,10 +128,6 @@ export default {
}
},
render() {
return (<div>{ this._t('default') }</div>);
},
data() {
return {
isSubColumn: false,
@ -162,9 +158,7 @@ export default {
created() {
this.customRender = this.$options.render;
this.$options.render = (h) => {
return (<div>{ this._t('default') }</div>);
};
this.$options.render = h => h('div', this.$slots.default);
let columnId = this.columnId = this.columnKey || ((this.$parent.tableId || (this.$parent.columnId + '_')) + 'column_' + columnIdSeed++);
@ -233,7 +227,6 @@ export default {
if (Object.prototype.toString.call(data._self) === '[object Object]') {
for (let prop in data._self) {
if (!data.hasOwnProperty(prop)) {
// _self.$set(data, prop, data._self[prop]);
data[prop] = data._self[prop];
}
}
@ -243,6 +236,8 @@ export default {
data.$options.staticRenderFns = _self.$options.staticRenderFns;
return _self.customRender.call(data);
};
} else if (_self.$scopedSlots.default) {
renderCell = () => _self.$scopedSlots.default(data);
}
if (!renderCell) {