Merge pull request #1 from ElemeFE/dev

update to new
pull/1406/head
Leon Zhang 2016-11-28 10:01:36 +08:00 committed by GitHub
commit 640ac48ef5
55 changed files with 642 additions and 342 deletions

View File

@ -14,6 +14,7 @@
- [Home Page](http://element.eleme.io/) - [Home Page](http://element.eleme.io/)
- [Docs](http://element.eleme.io/#/component) - [Docs](http://element.eleme.io/#/component)
- [FAQ](./FAQ.md) - [FAQ](./FAQ.md)
- [Customize Theme](http://element.eleme.io/#/en-US/component/custom-theme)
- Starter Kit - Starter Kit
- [element-starter](https://github.com/ElementUI/element-starter) - [element-starter](https://github.com/ElementUI/element-starter)
- [element-cooking-starter](https://github.com/ElementUI/element-cooking-starter) - [element-cooking-starter](https://github.com/ElementUI/element-cooking-starter)

View File

@ -1,10 +1,10 @@
## Custom theme ## Custom theme
Element uses BEM-styled CSS so that you can override styles easily. But if you need to replace styles at a large scale, e.g. change the theme color from blue to orange or green, maybe overriding them one by one is not a good idea, and this is where our theme customization tool kicks in. Element uses BEM-styled CSS so that you can override styles easily. But if you need to replace styles at a large scale, e.g. change the theme color from blue to orange or green, maybe overriding them one by one is not a good idea, and this is where our theme customization tool kicks in.
### Install related tool ### Install related tool
First install the theme generator globally or locally. Local install is recommended because in this way, when others clone your project, npm will automatically install it for them. First install the theme generator globally or locally. Local install is recommended because in this way, when others clone your project, npm will automatically install it for them.
```shell ```shell
npm i element-theme -D npm i element-theme -g
``` ```
Then install the default theme from npm or GitHub. Then install the default theme from npm or GitHub.
@ -20,7 +20,7 @@ npm i https://github.com/ElementUI/theme-default -D
After successfully installing the above packages, a command named `et` is available in CLI (if the packages are installed locally, use `node_modules/.bin/et` instead). Run `-i` to initialize the variable file which outputs to `element-variables.css` by default. And you can specify its output directory as you will. After successfully installing the above packages, a command named `et` is available in CLI (if the packages are installed locally, use `node_modules/.bin/et` instead). Run `-i` to initialize the variable file which outputs to `element-variables.css` by default. And you can specify its output directory as you will.
```shell ```shell
node_modules/.bin/et -i [custom output directory] et -i [custom output directory]
> ✔ Generator variables file > ✔ Generator variables file
``` ```
@ -53,7 +53,7 @@ Just edit `element-variables.css`, e.g. changing the theme color to red:
### Build theme ### Build theme
After saving the variable file, use `et` to build your theme. You can activate `watch` mode by adding a parameter `-w`: After saving the variable file, use `et` to build your theme. You can activate `watch` mode by adding a parameter `-w`:
```shell ```shell
node_modules/.bin/et et
> ✔ build theme font > ✔ build theme font
> ✔ build element theme > ✔ build element theme

View File

@ -6,10 +6,10 @@
return callback(new Error('Please input the age')); return callback(new Error('Please input the age'));
} }
setTimeout(() => { setTimeout(() => {
if (!Number.isInteger(age)) { if (!Number.isInteger(value)) {
callback(new Error('Please input digits')); callback(new Error('Please input digits'));
} else{ } else {
if (age < 18) { if (value < 18) {
callback(new Error('Age must be greater than 18')); callback(new Error('Age must be greater than 18'));
} else { } else {
callback(); callback();
@ -117,7 +117,7 @@
{ validator: validaePass2, trigger: 'blur' } { validator: validaePass2, trigger: 'blur' }
], ],
age: [ age: [
{ validator: checkAge, trigger: 'change', trigger: 'blur' } { validator: checkAge, trigger: 'blur' }
] ]
}, },
dynamicForm: { dynamicForm: {
@ -172,6 +172,9 @@
handleReset2() { handleReset2() {
this.$refs.ruleForm2.resetFields(); this.$refs.ruleForm2.resetFields();
}, },
handleReset3() {
this.$refs.dynamicForm.resetFields();
},
handleValidate(prop, errorMsg) { handleValidate(prop, errorMsg) {
console.log(prop, errorMsg); console.log(prop, errorMsg);
}, },
@ -632,7 +635,7 @@ Form component allows you to verify your data, helping you find and correct erro
<el-input type="password" v-model="ruleForm2.checkPass" auto-complete="off"></el-input> <el-input type="password" v-model="ruleForm2.checkPass" auto-complete="off"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="Age" prop="age"> <el-form-item label="Age" prop="age">
<el-input v-model="ruleForm2.age"></el-input> <el-input v-model.number="ruleForm2.age"></el-input>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleSubmit2">Submit</el-button> <el-button type="primary" @click="handleSubmit2">Submit</el-button>
@ -647,10 +650,10 @@ Form component allows you to verify your data, helping you find and correct erro
return callback(new Error('Please input the age')); return callback(new Error('Please input the age'));
} }
setTimeout(() => { setTimeout(() => {
if (!Number.isInteger(age)) { if (!Number.isInteger(value)) {
callback(new Error('Please input digits')); callback(new Error('Please input digits'));
} else{ } else {
if (age < 18) { if (value < 18) {
callback(new Error('Age must be greater than 18')); callback(new Error('Age must be greater than 18'));
} else { } else {
callback(); callback();
@ -691,7 +694,7 @@ Form component allows you to verify your data, helping you find and correct erro
{ validator: validaePass2, trigger: 'blur' } { validator: validaePass2, trigger: 'blur' }
], ],
age: [ age: [
{ validator: checkAge, trigger: 'change', trigger: 'blur' } { validator: checkAge, trigger: 'blur' }
] ]
} }
}; };
@ -729,12 +732,9 @@ Form component allows you to verify your data, helping you find and correct erro
v-for="(domain, index) in dynamicForm.domains" v-for="(domain, index) in dynamicForm.domains"
:label="'Domain' + index" :label="'Domain' + index"
:key="domain.key" :key="domain.key"
:prop="'domains:' + index" :prop="'domains.' + index + '.value'"
:rules="{ :rules="{
type: 'object', required: true, required: true, message: 'domain can not be null', trigger: 'blur'
fields: {
value: { required: true, message: 'domain can not be null', trigger: 'blur' }
}
}" }"
> >
<el-input v-model="domain.value"></el-input><el-button @click.prevent="removeDomain(domain)">Delete</el-button> <el-input v-model="domain.value"></el-input><el-button @click.prevent="removeDomain(domain)">Delete</el-button>
@ -742,6 +742,7 @@ Form component allows you to verify your data, helping you find and correct erro
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleSubmit3">Submit</el-button> <el-button type="primary" @click="handleSubmit3">Submit</el-button>
<el-button @click="addDomain">New domain</el-button> <el-button @click="addDomain">New domain</el-button>
<el-button @click="handleReset3">Reset</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
<script> <script>
@ -774,15 +775,18 @@ Form component allows you to verify your data, helping you find and correct erro
} }
}); });
}, },
handleReset3() {
this.$refs.dynamicForm.resetFields();
},
removeDomain(item) { removeDomain(item) {
var index = this.dynamicForm.domains.indexOf(item) var index = this.dynamicForm.domains.indexOf(item);
if (index !== -1) { if (index !== -1) {
this.dynamicForm.domains.splice(index, 1) this.dynamicForm.domains.splice(index, 1);
} }
}, },
addDomain() { addDomain() {
this.dynamicForm.domains.push({ this.dynamicForm.domains.push({
key: this.dynamicForm.domains.length, key: Date.now(),
value: '' value: ''
}); });
} }

View File

@ -110,17 +110,14 @@
display: inline-block; display: inline-block;
} }
.inline-input { .inline-input {
.el-input { &.el-input {
display: inline-block; display: inline-block;
vertical-align: top; vertical-align: top;
margin: 10px 5px; margin: 10px 5px;
} }
.el-autocomplete { &.el-autocomplete {
display: inline-block;
margin: 10px 0 0; margin: 10px 0 0;
.el-input {
margin: 0;
}
} }
} }
.tac { .tac {
@ -306,22 +303,26 @@ export default {
::: demo Add `size` attribute to change the size of Input. In addition to the default size, there are three other options: `large`, `small` and `mini`. ::: demo Add `size` attribute to change the size of Input. In addition to the default size, there are three other options: `large`, `small` and `mini`.
```html ```html
<div class="inline-input"> <div>
<el-input <el-input
class="inline-input"
size="large" size="large"
placeholder="Please input" placeholder="Please input"
v-model="input6"> v-model="input6">
</el-input> </el-input>
<el-input <el-input
class="inline-input"
placeholder="Please input" placeholder="Please input"
v-model="input7"> v-model="input7">
</el-input> </el-input>
<el-input <el-input
class="inline-input"
size="small" size="small"
placeholder="Please input" placeholder="Please input"
v-model="input8"> v-model="input8">
</el-input> </el-input>
<el-input <el-input
class="inline-input"
size="mini" size="mini"
placeholder="Please input" placeholder="Please input"
v-model="input9"> v-model="input9">
@ -349,10 +350,11 @@ You can get some recommended tips based on the current input.
::: demo Autocomplete component provides input suggestions. The `fetch-suggestions` attribute is a method that returns suggested input. In this example, `querySearch(queryString, cb)` returns suggestions to Autocomplete via `cb(data)` when suggestions are ready. ::: demo Autocomplete component provides input suggestions. The `fetch-suggestions` attribute is a method that returns suggested input. In this example, `querySearch(queryString, cb)` returns suggestions to Autocomplete via `cb(data)` when suggestions are ready.
```html ```html
<el-row class="inline-input border-grid"> <el-row class="border-grid">
<el-col :span="12" class="tac"> <el-col :span="12" class="tac">
<div class="text">list suggestions when activated</div> <div class="text">list suggestions when activated</div>
<el-autocomplete <el-autocomplete
class="inline-input"
v-model="state1" v-model="state1"
:fetch-suggestions="querySearch" :fetch-suggestions="querySearch"
placeholder="Please input" placeholder="Please input"
@ -362,6 +364,7 @@ You can get some recommended tips based on the current input.
<el-col :span="12" class="tac"> <el-col :span="12" class="tac">
<div class="text">list suggestions on input</div> <div class="text">list suggestions on input</div>
<el-autocomplete <el-autocomplete
class="inline-input"
v-model="state2" v-model="state2"
:fetch-suggestions="querySearch" :fetch-suggestions="querySearch"
placeholder="Please input" placeholder="Please input"

View File

@ -1,7 +1,7 @@
## Installation ## Installation
### npm ### npm
Installing with npm is recommended, for it works seamlessly with [webpack](https://webpack.js.org/). Installing with npm is recommended and it works seamlessly with [webpack](https://webpack.js.org/).
```shell ```shell
npm i element-ui -D npm i element-ui -D
@ -50,4 +50,4 @@ If you are using CDN, a hello-world page is easy with Element. [Online Demo](htt
</script> </script>
</html> </html>
``` ```
If you are using npm and wish to apply webpack, please continue to the next page: Quick Start. If you are using npm and wish to apply webpack, please continue to the next page: Quick Start.

View File

@ -22,7 +22,7 @@ Menu that provides navigation for your website.
Top bar NavMenu can be used in a variety of scenarios. Top bar NavMenu can be used in a variety of scenarios.
::: demo ::: demo By default Menu is vertical, but you can change it to horizontal by setting the mode prop to 'horizontal'. In addition, you can use the submenu component to create a second level menu.
```html ```html
<el-menu theme="dark" default-active="1" class="el-menu-demo" mode="horizontal" @select="handleSelect"> <el-menu theme="dark" default-active="1" class="el-menu-demo" mode="horizontal" @select="handleSelect">
<el-menu-item index="1">Processing Center</el-menu-item> <el-menu-item index="1">Processing Center</el-menu-item>
@ -62,7 +62,7 @@ Top bar NavMenu can be used in a variety of scenarios.
Vertical NavMenu with sub-menus. Vertical NavMenu with sub-menus.
::: demo ::: demo You can use the el-menu-item-group component to create a menu group, and the name of the group is determined by the title prop or a named slot.
```html ```html
<el-row class="tac"> <el-row class="tac">
<el-col :span="8"> <el-col :span="8">

View File

@ -137,5 +137,7 @@ change | triggers when the bound value changes | the label value of the chosen r
---- | ---- | ---- | ---- | ---- ---- | ---- | ---- | ---- | ----
label | the value of radio | string/number | — | — label | the value of radio | string/number | — | —
disabled | whether radio is disabled | boolean | — | false disabled | whether radio is disabled | boolean | — | false
fill | border and background color when button is active | string | — | #20a0ff |
text-color | font color when button is active | string | — | #ffffff |

View File

@ -1183,7 +1183,8 @@ Customize table column so it can be integrated with other components.
| fit | whether width of column automatically fits its container | boolean | — | true | | fit | whether width of column automatically fits its container | boolean | — | true |
| show-header | whether table header is visible | boolean | - | true | | show-header | whether table header is visible | boolean | - | true |
| highlight-current-row | whether current row is highlighted | boolean | — | false | | highlight-current-row | whether current row is highlighted | boolean | — | false |
| row-class-name | function that returns custom class names for a row | Function(row, index) | — | — | | row-class-name | function that returns custom class names for a row, or a string assigning class names for every row | Function(row, index)/String | — | — |
| row-style | function that returns custom style for a row, or a string assigning custom style for every row | Function(row, index)/Object | — | — |
| row-key | key of row data, used for optimizing rendering. Required if `reserve-selection` is on | Function(row)/String | — | — | | row-key | key of row data, used for optimizing rendering. Required if `reserve-selection` is on | Function(row)/String | — | — |
| context | context of Table, e.g. `_self` refers to the current context, `$parent` parent context, `$root` root context, can be overridden by `context` in `el-table-column` | Object | - | current context where Table lies | | context | context of Table, e.g. `_self` refers to the current context, `$parent` parent context, `$root` root context, can be overridden by `context` in `el-table-column` | Object | - | current context where Table lies |

View File

@ -1,5 +1,10 @@
<script> <script>
export default { export default {
data() {
return {
fileList: [{name: 'food.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}, {name: 'food2.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}]
};
},
methods: { methods: {
handleChange(file, fileList, event) { handleChange(file, fileList, event) {
console.log(file, fileList, event); console.log(file, fileList, event);
@ -37,12 +42,18 @@ Upload files by clicking or drag-and-drop
<el-upload <el-upload
action="//jsonplaceholder.typicode.com/posts/" action="//jsonplaceholder.typicode.com/posts/"
:on-preview="handlePreview" :on-preview="handlePreview"
:on-remove="handleRemove"> :on-remove="handleRemove"
:default-file-list="fileList">
<el-button size="small" type="primary">Click to upload</el-button> <el-button size="small" type="primary">Click to upload</el-button>
<div class="el-upload__tip" slot="tip">jpg/png files with a size less than 500kb</div> <div class="el-upload__tip" slot="tip">jpg/png files with a size less than 500kb</div>
</el-upload> </el-upload>
<script> <script>
export default { export default {
data() {
return {
fileList: [{name: 'food.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}, {name: 'food2.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}]
};
},
methods: { methods: {
handleRemove(file, fileList) { handleRemove(file, fileList) {
console.log(file, fileList); console.log(file, fileList);
@ -70,6 +81,7 @@ You can drag your file to a certain area to upload it.
:on-remove="handleRemove" :on-remove="handleRemove"
:on-success="handleSuccess" :on-success="handleSuccess"
:on-error="handleError" :on-error="handleError"
:default-file-list="fileList"
> >
<i class="el-icon-upload"></i> <i class="el-icon-upload"></i>
<div class="el-dragger__text">Drop file here or <em>click to upload</em></div> <div class="el-dragger__text">Drop file here or <em>click to upload</em></div>
@ -77,6 +89,11 @@ You can drag your file to a certain area to upload it.
</el-upload> </el-upload>
<script> <script>
export default { export default {
data() {
return {
fileList: [{name: 'food.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}, {name: 'food2.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}]
};
},
methods: { methods: {
handleRemove(file, fileList) { handleRemove(file, fileList) {
console.log(file, fileList); console.log(file, fileList);
@ -102,6 +119,7 @@ This mode is specifically for image uploading, and the thumbnail will display in
:thumbnail-mode="true" :thumbnail-mode="true"
:on-preview="handlePreview" :on-preview="handlePreview"
:on-remove="handleRemove" :on-remove="handleRemove"
:default-file-list="fileList"
> >
<i class="el-icon-upload"></i> <i class="el-icon-upload"></i>
<div class="el-dragger__text">Drop file here or <em>click to upload</em></div> <div class="el-dragger__text">Drop file here or <em>click to upload</em></div>
@ -109,6 +127,11 @@ This mode is specifically for image uploading, and the thumbnail will display in
</el-upload> </el-upload>
<script> <script>
export default { export default {
data() {
return {
fileList: [{name: 'food.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}, {name: 'food2.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}]
};
},
methods: { methods: {
handleRemove(file, fileList) { handleRemove(file, fileList) {
console.log(file, fileList); console.log(file, fileList);
@ -140,6 +163,7 @@ on-success | hook function when uploaded successfully | function(response, file,
on-error | hook function when some errors occurs | function(err, response, file) | — | — on-error | hook function when some errors occurs | function(err, response, file) | — | —
before-upload | hook function before uploading with the file to be uploaded as its parameter. If `false` or a `Promise` is returned, uploading will be aborted | function(file) | — | — before-upload | hook function before uploading with the file to be uploaded as its parameter. If `false` or a `Promise` is returned, uploading will be aborted | function(file) | — | —
thumbnail-mode | whether thumbnail is displayed | boolean | — | false thumbnail-mode | whether thumbnail is displayed | boolean | — | false
default-file-list | default uploaded files, i.e: [{name: 'food.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}] | array | — | []
### Events ### Events
| Event Name | Description | Parameters | | Event Name | Description | Parameters |

View File

@ -2,9 +2,9 @@
Element 默认提供一套主题CSS 命名采用 BEM 的风格方便使用者覆盖样式。如果你想完全替换主题色或者部分样式,可以使用下面方法。 Element 默认提供一套主题CSS 命名采用 BEM 的风格方便使用者覆盖样式。如果你想完全替换主题色或者部分样式,可以使用下面方法。
### 安装工具 ### 安装工具
首先安装「主题生成工具」,可以全局安装或者安装在当前项目下,推荐安装在项目里,方便别人 clone 项目时能直接安装依赖并启动。 首先安装「主题生成工具」,可以全局安装或者安装在当前项目下,推荐安装在项目里,方便别人 clone 项目时能直接安装依赖并启动,这里以全局安装做演示
```shell ```shell
npm i element-theme -D npm i element-theme -g
``` ```
安装默认主题,可以从 npm 安装或者从 GitHub 拉取最新代码。 安装默认主题,可以从 npm 安装或者从 GitHub 拉取最新代码。
@ -20,7 +20,7 @@ npm i https://github.com/ElementUI/theme-default -D
主题生成工具安装成功后,如果全局安装可以在命令行里通过 `et` 调用工具,如果安装在当前目录下,需要通过 `node_modules/.bin/et` 访问到命令。执行 `-i` 初始化变量文件。默认输出到 `element-variables.css`,当然你可以传参数指定文件输出目录。 主题生成工具安装成功后,如果全局安装可以在命令行里通过 `et` 调用工具,如果安装在当前目录下,需要通过 `node_modules/.bin/et` 访问到命令。执行 `-i` 初始化变量文件。默认输出到 `element-variables.css`,当然你可以传参数指定文件输出目录。
```shell ```shell
node_modules/.bin/et -i [可以自定义变量文件目录] et -i [可以自定义变量文件目录]
> ✔ Generator variables file > ✔ Generator variables file
``` ```
@ -53,7 +53,7 @@ node_modules/.bin/et -i [可以自定义变量文件目录]
### 编译主题 ### 编译主题
保存文件后,到命令行里执行 `et` 编译主题,如果你想启用 `watch` 模式,实时编译主题,增加 `-w` 参数。 保存文件后,到命令行里执行 `et` 编译主题,如果你想启用 `watch` 模式,实时编译主题,增加 `-w` 参数。
```shell ```shell
node_modules/.bin/et et
> ✔ build theme font > ✔ build theme font
> ✔ build element theme > ✔ build element theme

View File

@ -122,8 +122,8 @@
}, },
dynamicForm: { dynamicForm: {
domains: [{ domains: [{
key: Date.now(), value: '',
value: '' key: Date.now()
}], }],
email: '' email: ''
}, },
@ -172,6 +172,9 @@
handleReset2() { handleReset2() {
this.$refs.ruleForm2.resetFields(); this.$refs.ruleForm2.resetFields();
}, },
handleReset3() {
this.$refs.dynamicForm.resetFields();
},
handleValidate(prop, errorMsg) { handleValidate(prop, errorMsg) {
console.log(prop, errorMsg); console.log(prop, errorMsg);
}, },
@ -189,8 +192,8 @@
}, },
addDomain() { addDomain() {
this.dynamicForm.domains.push({ this.dynamicForm.domains.push({
key: Date.now(), value: '',
value: '' key: Date.now()
}); });
} }
} }
@ -720,12 +723,9 @@
v-for="(domain, index) in dynamicForm.domains" v-for="(domain, index) in dynamicForm.domains"
:label="'域名' + index" :label="'域名' + index"
:key="domain.key" :key="domain.key"
:prop="'domains:' + index" :prop="'domains.' + index + '.value'"
:rules="{ :rules="{
type: 'object', required: true, required: true, message: '域名不能为空', trigger: 'blur'
fields: {
value: { required: true, message: '域名不能为空', trigger: 'blur' }
}
}" }"
> >
<el-input v-model="domain.value"></el-input><el-button @click.prevent="removeDomain(domain)">删除</el-button> <el-input v-model="domain.value"></el-input><el-button @click.prevent="removeDomain(domain)">删除</el-button>
@ -733,6 +733,7 @@
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleSubmit3">提交</el-button> <el-button type="primary" @click="handleSubmit3">提交</el-button>
<el-button @click="addDomain">新增域名</el-button> <el-button @click="addDomain">新增域名</el-button>
<el-button @click="handleReset3">重置</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
<script> <script>
@ -741,7 +742,6 @@
return { return {
dynamicForm: { dynamicForm: {
domains: [{ domains: [{
key: 1,
value: '' value: ''
}], }],
email: '' email: ''
@ -765,6 +765,9 @@
} }
}); });
}, },
handleReset3() {
this.$refs.dynamicForm.resetFields();
},
removeDomain(item) { removeDomain(item) {
var index = this.dynamicForm.domains.indexOf(item) var index = this.dynamicForm.domains.indexOf(item)
if (index !== -1) { if (index !== -1) {
@ -773,8 +776,8 @@
}, },
addDomain() { addDomain() {
this.dynamicForm.domains.push({ this.dynamicForm.domains.push({
key: this.dynamicForm.domains.length, value: '',
value: '' key: Date.now()
}); });
} }
} }

View File

@ -151,17 +151,14 @@
display: inline-block; display: inline-block;
} }
.inline-input { .inline-input {
.el-input { &.el-input {
display: inline-block; display: inline-block;
vertical-align: top; vertical-align: top;
margin: 10px 5px; margin: 10px 5px;
} }
.el-autocomplete { &.el-autocomplete {
display: inline-block;
margin: 10px 0 0; margin: 10px 0 0;
.el-input {
margin: 0;
}
} }
} }
.tac { .tac {
@ -349,22 +346,26 @@ export default {
::: demo 可通过 `size` 属性指定输入框的尺寸,除了默认的大小外,还提供了 large、small 和 mini 三种尺寸。 ::: demo 可通过 `size` 属性指定输入框的尺寸,除了默认的大小外,还提供了 large、small 和 mini 三种尺寸。
```html ```html
<div class="inline-input"> <div>
<el-input <el-input
class="inline-input"
size="large" size="large"
placeholder="请输入内容" placeholder="请输入内容"
v-model="input6"> v-model="input6">
</el-input> </el-input>
<el-input <el-input
class="inline-input"
placeholder="请输入内容" placeholder="请输入内容"
v-model="input7"> v-model="input7">
</el-input> </el-input>
<el-input <el-input
class="inline-input"
size="small" size="small"
placeholder="请输入内容" placeholder="请输入内容"
v-model="input8"> v-model="input8">
</el-input> </el-input>
<el-input <el-input
class="inline-input"
size="mini" size="mini"
placeholder="请输入内容" placeholder="请输入内容"
v-model="input9"> v-model="input9">
@ -392,10 +393,11 @@ export default {
::: demo autocomplete 是一个可带输入建议的输入框组件,`fetch-suggestions` 是一个返回输入建议的方法属性,如 querySearch(queryString, cb),在该方法中你可以在你的输入建议数据准备好时通过 cb(data) 返回到 autocomplete 组件中。 ::: demo autocomplete 是一个可带输入建议的输入框组件,`fetch-suggestions` 是一个返回输入建议的方法属性,如 querySearch(queryString, cb),在该方法中你可以在你的输入建议数据准备好时通过 cb(data) 返回到 autocomplete 组件中。
```html ```html
<el-row class="inline-input border-grid"> <el-row class="border-grid">
<el-col :span="12" class="tac"> <el-col :span="12" class="tac">
<div class="text">激活即列出输入建议</div> <div class="text">激活即列出输入建议</div>
<el-autocomplete <el-autocomplete
class="inline-input"
v-model="state1" v-model="state1"
:fetch-suggestions="querySearch" :fetch-suggestions="querySearch"
placeholder="请输入内容" placeholder="请输入内容"
@ -405,6 +407,7 @@ export default {
<el-col :span="12" class="tac"> <el-col :span="12" class="tac">
<div class="text">输入后匹配输入建议</div> <div class="text">输入后匹配输入建议</div>
<el-autocomplete <el-autocomplete
class="inline-input"
v-model="state2" v-model="state2"
:fetch-suggestions="querySearch" :fetch-suggestions="querySearch"
placeholder="请输入内容" placeholder="请输入内容"

View File

@ -52,7 +52,7 @@
适用广泛的基础用法。 适用广泛的基础用法。
::: demo ::: demo 导航菜单默认为垂直模式,通过 `mode` 属性可以使导航菜单变更为水平模式。另外,在菜单中通过 `submenu` 组件可以生成二级菜单。
```html ```html
<el-menu theme="dark" default-active="1" class="el-menu-demo" mode="horizontal" @select="handleSelect"> <el-menu theme="dark" default-active="1" class="el-menu-demo" mode="horizontal" @select="handleSelect">
<el-menu-item index="1">处理中心</el-menu-item> <el-menu-item index="1">处理中心</el-menu-item>
@ -92,7 +92,7 @@
垂直菜单,可内嵌子菜单。 垂直菜单,可内嵌子菜单。
::: demo ::: demo 通过 `el-menu-item-group` 组件可以实现菜单进行分组,分组名可以通过 `title` 属性直接设定也可以通过具名 slot 来设定。
```html ```html
<el-row class="tac"> <el-row class="tac">
<el-col :span="8"> <el-col :span="8">
@ -100,7 +100,8 @@
<el-menu default-active="2" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose"> <el-menu default-active="2" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose">
<el-submenu index="1"> <el-submenu index="1">
<template slot="title"><i class="el-icon-message"></i>导航一</template> <template slot="title"><i class="el-icon-message"></i>导航一</template>
<el-menu-item-group title="分组一"> <el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="1-1">选项1</el-menu-item> <el-menu-item index="1-1">选项1</el-menu-item>
<el-menu-item index="1-2">选项2</el-menu-item> <el-menu-item index="1-2">选项2</el-menu-item>
</el-menu-item-group> </el-menu-item-group>

View File

@ -138,3 +138,5 @@
|---------- |-------- |---------- |------------- |-------- | |---------- |-------- |---------- |------------- |-------- |
| label | Radio 的 value | string,number | — | — | | label | Radio 的 value | string,number | — | — |
| disabled | 是否禁用 | boolean | — | false | | disabled | 是否禁用 | boolean | — | false |
| fill | 按钮激活时的填充色和边框色 | string | — | #20a0ff |
| text-color | 按钮激活时的文本颜色 | string | — | #ffffff |

View File

@ -1188,7 +1188,8 @@
| fit | 列的宽度是否自撑开 | boolean | — | true | | fit | 列的宽度是否自撑开 | boolean | — | true |
| show-header | 是否显示表头 | boolean | - | true | | show-header | 是否显示表头 | boolean | - | true |
| highlight-current-row | 是否要高亮当前行 | boolean | — | false | | highlight-current-row | 是否要高亮当前行 | boolean | — | false |
| row-class-name | 行的 className 的回调。 | Function(row, index) | — | — | | row-class-name | 行的 className 的回调方法,也可以使用字符串为所有行设置一个固定的 className。 | Function(row, index)/String | — | — |
| row-style | 行的 style 的回调方法,也可以使用一个固定的 Object 为所有行设置一样的 Style。 | Function(row, index)/Object | — | — |
| row-key | 行数据的 Key用来优化 Table 的渲染;在使用 reserve-selection 功能的情况下,该属性是必填的 | Function(row)/String | — | — | | row-key | 行数据的 Key用来优化 Table 的渲染;在使用 reserve-selection 功能的情况下,该属性是必填的 | Function(row)/String | — | — |
| context | 设置上下文环境,例如设置当前上下文就是 `_self`,父级就是 `$parent`,根组件 `$root`。优先读取 column 的 context 属性。 | Object | - | Table 所处上下文 | | context | 设置上下文环境,例如设置当前上下文就是 `_self`,父级就是 `$parent`,根组件 `$root`。优先读取 column 的 context 属性。 | Object | - | Table 所处上下文 |

View File

@ -10,6 +10,11 @@
</style> </style>
<script> <script>
export default { export default {
data() {
return {
fileList: [{name: 'food.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}, {name: 'food2.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}]
};
},
methods: { methods: {
handleChange(file, fileList, event) { handleChange(file, fileList, event) {
console.log(file, fileList, event); console.log(file, fileList, event);
@ -48,12 +53,18 @@
<el-upload <el-upload
action="//jsonplaceholder.typicode.com/posts/" action="//jsonplaceholder.typicode.com/posts/"
:on-preview="handlePreview" :on-preview="handlePreview"
:on-remove="handleRemove"> :on-remove="handleRemove"
:default-file-list="fileList">
<el-button size="small" type="primary">点击上传</el-button> <el-button size="small" type="primary">点击上传</el-button>
<div class="el-upload__tip" slot="tip">只能上传jpg/png文件且不超过500kb</div> <div class="el-upload__tip" slot="tip" @click="changeFiles">只能上传jpg/png文件且不超过500kb</div>
</el-upload> </el-upload>
<script> <script>
export default { export default {
data() {
return {
fileList: [{name: 'food.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}, {name: 'food2.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}]
};
},
methods: { methods: {
handleRemove(file, fileList) { handleRemove(file, fileList) {
console.log(file, fileList); console.log(file, fileList);
@ -81,6 +92,7 @@
:on-remove="handleRemove" :on-remove="handleRemove"
:on-success="handleSuccess" :on-success="handleSuccess"
:on-error="handleError" :on-error="handleError"
:default-file-list="fileList"
> >
<i class="el-icon-upload"></i> <i class="el-icon-upload"></i>
<div class="el-dragger__text">将文件拖到此处,或<em>点击上传</em></div> <div class="el-dragger__text">将文件拖到此处,或<em>点击上传</em></div>
@ -88,6 +100,11 @@
</el-upload> </el-upload>
<script> <script>
export default { export default {
data() {
return {
fileList: [{name: 'food.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}, {name: 'food2.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}]
};
},
methods: { methods: {
handleRemove(file, fileList) { handleRemove(file, fileList) {
console.log(file, fileList); console.log(file, fileList);
@ -113,6 +130,7 @@
:thumbnail-mode="true" :thumbnail-mode="true"
:on-preview="handlePreview" :on-preview="handlePreview"
:on-remove="handleRemove" :on-remove="handleRemove"
:default-file-list="fileList"
> >
<i class="el-icon-upload"></i> <i class="el-icon-upload"></i>
<div class="el-dragger__text">将文件拖到此处,或<em>点击上传</em></div> <div class="el-dragger__text">将文件拖到此处,或<em>点击上传</em></div>
@ -120,6 +138,11 @@
</el-upload> </el-upload>
<script> <script>
export default { export default {
data() {
return {
fileList: [{name: 'food.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}, {name: 'food2.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}]
};
},
methods: { methods: {
handleRemove(file, fileList) { handleRemove(file, fileList) {
console.log(file, fileList); console.log(file, fileList);
@ -151,6 +174,7 @@
| on-error | 可选参数, 文件上传失败时的钩子 | function(err, response, file) | — | — | | on-error | 可选参数, 文件上传失败时的钩子 | function(err, response, file) | — | — |
| before-upload | 可选参数, 上传文件之前的钩子,参数为上传的文件,若返回 false 或者 Promise 则停止上传。 | function(file) | — | — | | before-upload | 可选参数, 上传文件之前的钩子,参数为上传的文件,若返回 false 或者 Promise 则停止上传。 | function(file) | — | — |
| thumbnail-mode | 是否设置为图片模式,该模式下会显示图片缩略图 | boolean | — | false | | thumbnail-mode | 是否设置为图片模式,该模式下会显示图片缩略图 | boolean | — | false |
| default-file-list | 默认已上传的文件列表, 例如: [{name: 'food.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}] | array | — | [] |
### Upload Methods ### Upload Methods
| 方法名 | 说明 | 参数 | | 方法名 | 说明 | 参数 |

View File

@ -11,7 +11,14 @@
@keydown.up.native="highlight(highlightedIndex - 1)" @keydown.up.native="highlight(highlightedIndex - 1)"
@keydown.down.native="highlight(highlightedIndex + 1)" @keydown.down.native="highlight(highlightedIndex + 1)"
@keydown.enter.native="select(highlightedIndex)" @keydown.enter.native="select(highlightedIndex)"
></el-input> >
<template slot="prepend" v-if="$slots.prepend">
<slot name="prepend"></slot>
</template>
<template slot="append" v-if="$slots.append">
<slot name="append"></slot>
</template>
</el-input>
<transition name="md-fade-bottom"> <transition name="md-fade-bottom">
<ul <ul
v-if="suggestionVisible" v-if="suggestionVisible"

View File

@ -15,8 +15,13 @@
watch: { watch: {
value(value) { value(value) {
this.$emit('change', value); this.$emit('change', value);
this.dispatch('form-item', 'el.form.change', [value]); this.dispatch('ElFormItem', 'el.form.change', [value]);
this.broadcast('ElCheckbox', 'initData', [value]);
} }
},
mounted() {
this.broadcast('ElCheckbox', 'initData', [this.value]);
} }
}; };
</script> </script>

View File

@ -17,11 +17,10 @@
:disabled="disabled" :disabled="disabled"
:true-value="trueLabel" :true-value="trueLabel"
:false-value="falseLabel" :false-value="falseLabel"
v-model="_value" v-model="model"
@change="$emit('change', $event)"
@focus="focus = true" @focus="focus = true"
@blur="focus = false" @blur="focus = false">
@change="handleChange"
ref="checkbox">
<input <input
v-else v-else
class="el-checkbox__original" class="el-checkbox__original"
@ -29,10 +28,10 @@
:disabled="disabled" :disabled="disabled"
:value="label" :value="label"
:name="name" :name="name"
v-model="_value" v-model="model"
@change="$emit('change', $event)"
@focus="focus = true" @focus="focus = true"
@blur="focus = false" @blur="focus = false">
@change="handleChange">
</span> </span>
<span class="el-checkbox__label" v-if="$slots.default || label"> <span class="el-checkbox__label" v-if="$slots.default || label">
<slot></slot> <slot></slot>
@ -48,9 +47,37 @@
mixins: [Emitter], mixins: [Emitter],
componentName: 'ElCheckbox',
computed: {
model: {
get() {
return this.isGroup ? this.store : this.value;
},
set(val) {
if (this.isGroup) {
this.dispatch('ElCheckboxGroup', 'input', [val]);
} else {
this.$emit('input', val);
}
}
},
isChecked() {
if ({}.toString.call(this.model) === '[object Boolean]') {
return this.model;
} else if (Array.isArray(this.model)) {
return this.model.indexOf(this.label) > -1;
} else if (this.model !== null && this.model !== undefined) {
return this.model === this.trueLabel;
}
}
},
props: { props: {
value: {}, value: {},
label: String, label: {},
indeterminate: Boolean, indeterminate: Boolean,
disabled: Boolean, disabled: Boolean,
checked: Boolean, checked: Boolean,
@ -59,59 +86,30 @@
falseLabel: [String, Number] falseLabel: [String, Number]
}, },
computed: {
_value: {
get() {
return !this.wrapInGroup ? this.value : this.$parent.value;
},
set(newValue) {
if (!this.wrapInGroup) {
this.$emit('input', newValue);
} else {
this.$parent.$emit('input', newValue);
}
}
},
isChecked() {
var type = Object.prototype.toString.call(this._value);
if (type === '[object Boolean]') {
return this._value;
} else if (type === '[object Array]') {
return this._value.indexOf(this.label) > -1;
} else if (type === '[object String]' || type === '[object Number]') {
return this._value === this.trueLabel;
}
}
},
data() { data() {
return { return {
focus: false, store: [],
wrapInGroup: this.$parent.$options.componentName === 'ElCheckboxGroup' isGroup: false
}; };
}, },
watch: { methods: {
checked: { addToStore() {
immediate: true, if (Array.isArray(this.model)) {
handler(value) { this.model.indexOf(this.label) === -1 && this.model.push(this.label);
if (value) { } else {
let type = Object.prototype.toString.call(this._value); this.model = this.trueLabel || true;
if (type !== '[object Array]') {
this._value = this.trueLabel || true;
} else {
this._value.push(this.label);
}
}
} }
} }
}, },
methods: { created() {
handleChange(ev) { this.checked && this.addToStore();
this.$emit('change', ev); this.$on('initData', data => {
} this.store = data;
this.isGroup = true;
this.checked && this.addToStore();
});
} }
}; };
</script> </script>

View File

@ -50,9 +50,7 @@
props: { props: {
disabledDate: {}, disabledDate: {},
date: {}, date: {},
year: { year: {}
type: Number
}
}, },
computed: { computed: {
@ -86,7 +84,7 @@
const target = event.target; const target = event.target;
if (target.tagName === 'A') { if (target.tagName === 'A') {
if (hasClass(target.parentNode, 'disabled')) return; if (hasClass(target.parentNode, 'disabled')) return;
const year = parseInt(target.textContent || target.innerText, 10); const year = target.textContent || target.innerText;
this.$emit('pick', year); this.$emit('pick', year);
} }
} }

View File

@ -20,7 +20,7 @@
@click="handleShortcutClick(shortcut)">{{ shortcut.text }}</button> @click="handleShortcutClick(shortcut)">{{ shortcut.text }}</button>
</div> </div>
<div class="el-picker-panel__body"> <div class="el-picker-panel__body">
<div class="el-date-picker__time-header" v-if="showTime"> <div class="el-date-picker__time-header" v-if="showTime">
<span class="el-date-picker__editor-wrap"> <span class="el-date-picker__editor-wrap">
<input <input
:placehoder="t('el.datepicker.selectDate')" :placehoder="t('el.datepicker.selectDate')"
@ -183,7 +183,7 @@
methods: { methods: {
handleClear() { handleClear() {
this.date = new Date(); this.date = new Date();
this.$emit('pick'); this.$emit('pick', '');
}, },
resetDate() { resetDate() {
@ -310,7 +310,7 @@
this.date.setFullYear(year); this.date.setFullYear(year);
if (this.selectionMode === 'year') { if (this.selectionMode === 'year') {
this.$emit('pick', year); this.$emit('pick', new Date(year));
} else { } else {
this.currentView = 'month'; this.currentView = 'month';
} }

View File

@ -84,7 +84,7 @@
}, },
handleClear() { handleClear() {
this.$emit('pick'); this.$emit('pick', '');
} }
}, },

View File

@ -101,7 +101,7 @@
methods: { methods: {
handleClear() { handleClear() {
this.handleCancel(); this.$emit('pick', '');
}, },
handleCancel() { handleCancel() {

View File

@ -58,7 +58,8 @@ const DEFAULT_FORMATS = {
time: 'HH:mm:ss', time: 'HH:mm:ss',
timerange: 'HH:mm:ss', timerange: 'HH:mm:ss',
daterange: 'yyyy-MM-dd', daterange: 'yyyy-MM-dd',
datetimerange: 'yyyy-MM-dd HH:mm:ss' datetimerange: 'yyyy-MM-dd HH:mm:ss',
year: 'yyyy'
}; };
const HAVE_TRIGGER_TYPES = [ const HAVE_TRIGGER_TYPES = [
'date', 'date',
@ -163,16 +164,8 @@ const TYPE_VALUE_RESOLVER_MAP = {
parser: DATE_PARSER parser: DATE_PARSER
}, },
year: { year: {
formatter(value) { formatter: DATE_FORMATTER,
if (!value) return ''; parser: DATE_PARSER
return '' + value;
},
parser(text) {
const year = Number(text);
if (!isNaN(year)) return year;
return null;
}
}, },
number: { number: {
formatter(value) { formatter(value) {
@ -236,7 +229,7 @@ export default {
if (!val && this.picker && typeof this.picker.handleClear === 'function') { if (!val && this.picker && typeof this.picker.handleClear === 'function') {
this.picker.handleClear(); this.picker.handleClear();
} }
this.dispatch('form-item', 'el.form.change'); this.dispatch('ElFormItem', 'el.form.change');
}, },
value: { value: {
immediate: true, immediate: true,
@ -358,7 +351,7 @@ export default {
handleBlur() { handleBlur() {
this.$emit('blur', this); this.$emit('blur', this);
this.dispatch('form-item', 'el.form.blur'); this.dispatch('ElFormItem', 'el.form.blur');
}, },
handleKeydown(event) { handleKeydown(event) {

View File

@ -21,10 +21,33 @@
function noop() {} function noop() {}
function getPropByPath(obj, path) {
let tempObj = obj;
path = path.replace(/\[(\w+)\]/g, '.$1');
path = path.replace(/^\./, '');
let keyArr = path.split('.');
let i = 0;
for (let len = keyArr.length; i < len - 1; ++i) {
let key = keyArr[i];
if (key in tempObj) {
tempObj = tempObj[key];
} else {
throw new Error('please transfer a valid prop path to form item!');
}
}
return {
o: tempObj,
k: keyArr[i],
v: tempObj[keyArr[i]]
};
}
export default { export default {
name: 'ElFormItem', name: 'ElFormItem',
componentName: 'form-item', componentName: 'ElFormItem',
mixins: [emitter], mixins: [emitter],
@ -65,7 +88,7 @@
}, },
form() { form() {
var parent = this.$parent; var parent = this.$parent;
while (parent.$options.componentName !== 'form') { while (parent.$options.componentName !== 'ElForm') {
parent = parent.$parent; parent = parent.$parent;
} }
return parent; return parent;
@ -76,11 +99,12 @@
var model = this.form.model; var model = this.form.model;
if (!model || !this.prop) { return; } if (!model || !this.prop) { return; }
var temp = this.prop.split(':'); var path = this.prop;
if (path.indexOf(':') !== -1) {
path = path.replace(/:/, '.');
}
return temp.length > 1 return getPropByPath(model, path).v;
? model[temp[0]][temp[1]]
: model[this.prop];
} }
} }
}, },
@ -124,13 +148,19 @@
let model = this.form.model; let model = this.form.model;
let value = this.fieldValue; let value = this.fieldValue;
let path = this.prop;
if (path.indexOf(':') !== -1) {
path = path.replace(/:/, '.');
}
let prop = getPropByPath(model, path);
if (Array.isArray(value) && value.length > 0) { if (Array.isArray(value) && value.length > 0) {
this.validateDisabled = true; this.validateDisabled = true;
model[this.prop] = []; prop.o[prop.k] = [];
} else if (value) { } else if (value) {
this.validateDisabled = true; this.validateDisabled = true;
model[this.prop] = this.initialValue; prop.o[prop.k] = this.initialValue;
} }
}, },
getRules() { getRules() {
@ -162,10 +192,10 @@
}, },
mounted() { mounted() {
if (this.prop) { if (this.prop) {
this.dispatch('form', 'el.form.addField', [this]); this.dispatch('ElForm', 'el.form.addField', [this]);
Object.defineProperty(this, 'initialValue', { Object.defineProperty(this, 'initialValue', {
value: this.form.model[this.prop] value: this.fieldValue
}); });
let rules = this.getRules(); let rules = this.getRules();
@ -183,7 +213,7 @@
} }
}, },
beforeDestroy() { beforeDestroy() {
this.dispatch('form', 'el.form.removeField', [this]); this.dispatch('ElForm', 'el.form.removeField', [this]);
} }
}; };
</script> </script>

View File

@ -10,7 +10,7 @@
export default { export default {
name: 'ElForm', name: 'ElForm',
componentName: 'form', componentName: 'ElForm',
props: { props: {
model: Object, model: Object,
@ -23,51 +23,50 @@
}, },
inline: Boolean inline: Boolean
}, },
watch: {
rules() {
this.validate();
}
},
data() { data() {
return { return {
fields: {}, fields: []
fieldLength: 0
}; };
}, },
created() { created() {
this.$on('el.form.addField', (field) => { this.$on('el.form.addField', (field) => {
this.fields[field.prop] = field; if (field) {
this.fieldLength++; this.fields.push(field);
}
}); });
/* istanbul ignore next */ /* istanbul ignore next */
this.$on('el.form.removeField', (field) => { this.$on('el.form.removeField', (field) => {
if (this.fields[field.prop]) { if (field.prop) {
delete this.fields[field.prop]; this.fields.splice(this.fields.indexOf(field), 1);
this.fieldLength--;
} }
}); });
}, },
methods: { methods: {
resetFields() { resetFields() {
for (let prop in this.fields) { this.fields.forEach(field => {
let field = this.fields[prop];
field.resetField(); field.resetField();
} });
}, },
validate(callback) { validate(callback) {
var count = 0; let valid = true;
var valid = true; this.fields.forEach((field, index) => {
for (let prop in this.fields) {
let field = this.fields[prop];
field.validate('', errors => { field.validate('', errors => {
if (errors) { if (errors) {
valid = false; valid = false;
} }
if (typeof callback === 'function' && index === this.fields.length - 1) {
if (++count === this.fieldLength) {
callback(valid); callback(valid);
} }
}); });
} });
}, },
validateField(prop, cb) { validateField(prop, cb) {
var field = this.fields[prop]; var field = this.fields.filter(field => field.prop === prop)[0];
if (!field) { throw new Error('must call validateField with valid prop string!'); } if (!field) { throw new Error('must call validateField with valid prop string!'); }
field.validate('', cb); field.validate('', cb);

View File

@ -68,6 +68,8 @@
export default { export default {
name: 'ElInput', name: 'ElInput',
componentName: 'ElInput',
mixins: [emitter], mixins: [emitter],
props: { props: {
@ -105,7 +107,7 @@
methods: { methods: {
handleBlur(event) { handleBlur(event) {
this.$emit('blur', event); this.$emit('blur', event);
this.dispatch('form-item', 'el.form.blur', [this.currentValue]); this.dispatch('ElFormItem', 'el.form.blur', [this.currentValue]);
}, },
inputSelect() { inputSelect() {
this.$refs.input.select(); this.$refs.input.select();
@ -148,7 +150,7 @@
computed: { computed: {
validating() { validating() {
return this.$parent.validating; return this.$parent.validateState === 'validating';
} }
}, },
@ -162,7 +164,7 @@
}); });
this.$emit('input', val); this.$emit('input', val);
this.$emit('change', val); this.$emit('change', val);
this.dispatch('form-item', 'el.form.change', [val]); this.dispatch('ElFormItem', 'el.form.change', [val]);
} }
} }
}; };

View File

@ -6,8 +6,7 @@
props: { props: {
title: { title: {
type: String, type: String
required: true
} }
}, },
data() { data() {
@ -39,7 +38,10 @@
<template> <template>
<li class="el-menu-item-group"> <li class="el-menu-item-group">
<div class="el-menu-item-group__title" :style="{'padding-left': paddingLeft + 'px'}">{{title}}</div> <div class="el-menu-item-group__title" :style="{'padding-left': paddingLeft + 'px'}">
<template v-if="!$slots.title">{{title}}</template>
<slot v-else name="title"></slot>
</div>
<ul> <ul>
<slot></slot> <slot></slot>
</ul> </ul>

View File

@ -54,7 +54,7 @@ export default {
jumper: <jumper></jumper>, jumper: <jumper></jumper>,
pager: <pager currentPage={ this.internalCurrentPage } pageCount={ this.internalPageCount } on-change={ this.handleCurrentChange }></pager>, pager: <pager currentPage={ this.internalCurrentPage } pageCount={ this.internalPageCount } on-change={ this.handleCurrentChange }></pager>,
next: <next></next>, next: <next></next>,
sizes: <sizes></sizes>, sizes: <sizes pageSizes={ this.pageSizes }></sizes>,
slot: <slot></slot>, slot: <slot></slot>,
total: <total></total> total: <total></total>
}; };
@ -119,11 +119,20 @@ export default {
Sizes: { Sizes: {
mixins: [Locale], mixins: [Locale],
created() { props: {
if (Array.isArray(this.$parent.pageSizes)) { pageSizes: Array
this.$parent.internalPageSize = this.$parent.pageSizes.indexOf(this.$parent.pageSize) > -1 },
? this.$parent.pageSize
: this.$parent.pageSizes[0]; watch: {
pageSizes: {
immediate: true,
handler(value) {
if (Array.isArray(value)) {
this.$parent.internalPageSize = value.indexOf(this.$parent.pageSize) > -1
? this.$parent.pageSize
: this.pageSizes[0];
}
}
} }
}, },
@ -136,7 +145,7 @@ export default {
on-change={ this.handleChange } on-change={ this.handleChange }
width={ 110 }> width={ 110 }>
{ {
this.$parent.pageSizes.map(item => this.pageSizes.map(item =>
<el-option <el-option
value={ item } value={ item }
label={ item + ' ' + this.t('el.pagination.pagesize') }> label={ item + ' ' + this.t('el.pagination.pagesize') }>

View File

@ -23,6 +23,13 @@
set(newValue) { set(newValue) {
this.$parent.$emit('input', newValue); this.$parent.$emit('input', newValue);
} }
},
activeStyle() {
return {
backgroundColor: this.$parent.fill,
borderColor: this.$parent.fill,
color: this.$parent.textColor
};
} }
} }
}; };
@ -43,7 +50,7 @@
v-model="value" v-model="value"
:name="name" :name="name"
:disabled="disabled"> :disabled="disabled">
<span class="el-radio-button__inner"> <span class="el-radio-button__inner" :style="value === label ? activeStyle : null">
<slot></slot> <slot></slot>
<template v-if="!$slots.default">{{label}}</template> <template v-if="!$slots.default">{{label}}</template>
</span> </span>

View File

@ -4,19 +4,31 @@
export default { export default {
name: 'ElRadioGroup', name: 'ElRadioGroup',
componentName: 'radio-group', componentName: 'ElRadioGroup',
mixins: [Emitter], mixins: [Emitter],
props: { props: {
value: [String, Number], value: [String, Number],
size: String size: String,
fill: {
type: String,
default: '#20a0ff'
},
textColor: {
type: String,
default: '#fff'
}
}, },
watch: { watch: {
value(value) { value(value) {
this.$emit('change', value); this.$emit('change', value);
this.dispatch('form-item', 'el.form.change', [this.value]); this.broadcast('ElRadio', 'initData', value);
this.dispatch('ElFormItem', 'el.form.change', [this.value]);
} }
},
mounted() {
this.broadcast('ElRadio', 'initData', this.value);
} }
}; };
</script> </script>

View File

@ -4,14 +4,14 @@
<span class="el-radio__inner" <span class="el-radio__inner"
:class="{ :class="{
'is-disabled': disabled, 'is-disabled': disabled,
'is-checked': _value === label, 'is-checked': store === label,
'is-focus': focus 'is-focus': focus
}"></span> }"></span>
<input <input
class="el-radio__original" class="el-radio__original"
:value="label" :value="label"
type="radio" type="radio"
v-model="_value" v-model="store"
@focus="focus = true" @focus="focus = true"
@blur="focus = false" @blur="focus = false"
:name="name" :name="name"
@ -24,9 +24,15 @@
</label> </label>
</template> </template>
<script> <script>
import Emitter from 'element-ui/src/mixins/emitter';
export default { export default {
name: 'ElRadio', name: 'ElRadio',
mixins: [Emitter],
componentName: 'ElRadio',
props: { props: {
value: [String, Number], value: [String, Number],
label: { label: {
@ -36,24 +42,34 @@
disabled: Boolean, disabled: Boolean,
name: String name: String
}, },
data() { data() {
return { return {
focus: false focus: false,
isGroup: false,
store: this.value
}; };
}, },
computed: {
_value: { watch: {
get() { store(store) {
return this.value !== undefined ? this.value : this.$parent.value; if (this.isGroup) {
}, this.dispatch('ElRadioGroup', 'input', store);
set(newValue) { } else {
if (this.value !== undefined) { this.$emit('input', store);
this.$emit('input', newValue);
} else {
this.$parent.$emit('input', newValue);
}
} }
},
value(val) {
this.store = val;
} }
},
created() {
this.$on('initData', data => {
this.store = data;
this.isGroup = true;
});
} }
}; };
</script> </script>

View File

@ -27,13 +27,13 @@
watch: { watch: {
disabled(val) { disabled(val) {
this.broadcast('option', 'handleGroupDisabled', val); this.broadcast('ElOption', 'handleGroupDisabled', val);
} }
}, },
mounted() { mounted() {
if (this.disabled) { if (this.disabled) {
this.broadcast('option', 'handleGroupDisabled', this.disabled); this.broadcast('ElOption', 'handleGroupDisabled', this.disabled);
} }
} }
}; };

View File

@ -19,7 +19,7 @@
name: 'el-option', name: 'el-option',
componentName: 'option', componentName: 'ElOption',
props: { props: {
value: { value: {
@ -50,6 +50,10 @@
return this.label || ((typeof this.value === 'string' || typeof this.value === 'number') ? this.value : ''); return this.label || ((typeof this.value === 'string' || typeof this.value === 'number') ? this.value : '');
}, },
currentValue() {
return this.value || this.label || '';
},
parent() { parent() {
let result = this.$parent; let result = this.$parent;
while (!result.isSelect) { while (!result.isSelect) {
@ -74,7 +78,7 @@
watch: { watch: {
currentSelected(val) { currentSelected(val) {
if (val === true) { if (val === true) {
this.dispatch('select', 'addOptionToValue', this); this.dispatch('ElSelect', 'addOptionToValue', this);
} }
} }
}, },
@ -92,7 +96,7 @@
selectOptionClick() { selectOptionClick() {
if (this.disabled !== true && this.groupDisabled !== true) { if (this.disabled !== true && this.groupDisabled !== true) {
this.dispatch('select', 'handleOptionClick', this); this.dispatch('ElSelect', 'handleOptionClick', this);
} }
}, },
@ -119,7 +123,7 @@
this.index = this.parent.options.indexOf(this); this.index = this.parent.options.indexOf(this);
if (this.currentSelected === true) { if (this.currentSelected === true) {
this.dispatch('select', 'addOptionToValue', [this, true]); this.dispatch('ElSelect', 'addOptionToValue', [this, true]);
} }
this.$on('queryChange', this.queryChange); this.$on('queryChange', this.queryChange);
@ -128,7 +132,7 @@
}, },
beforeDestroy() { beforeDestroy() {
this.dispatch('select', 'onOptionDestroy', this); this.dispatch('ElSelect', 'onOptionDestroy', this);
} }
}; };
</script> </script>

View File

@ -13,7 +13,7 @@
export default { export default {
name: 'el-select-dropdown', name: 'el-select-dropdown',
componentName: 'select-dropdown', componentName: 'ElSelectDropdown',
mixins: [Popper], mixins: [Popper],

View File

@ -82,7 +82,7 @@
name: 'ElSelect', name: 'ElSelect',
componentName: 'select', componentName: 'ElSelect',
computed: { computed: {
iconClass() { iconClass() {
@ -97,16 +97,19 @@
let criteria = this.clearable && this.inputHovering && !this.multiple && this.options.indexOf(this.selected) > -1; let criteria = this.clearable && this.inputHovering && !this.multiple && this.options.indexOf(this.selected) > -1;
if (!this.$el) return false; if (!this.$el) return false;
let icon = this.$el.querySelector('.el-input__icon'); this.$nextTick(() => {
if (icon) { let icon = this.$el.querySelector('.el-input__icon');
if (criteria) { if (icon) {
icon.addEventListener('click', this.deleteSelected); if (criteria) {
addClass(icon, 'is-show-close'); icon.addEventListener('click', this.deleteSelected);
} else { addClass(icon, 'is-show-close');
icon.removeEventListener('click', this.deleteSelected); } else {
removeClass(icon, 'is-show-close'); icon.removeEventListener('click', this.deleteSelected);
removeClass(icon, 'is-show-close');
}
} }
} });
return criteria; return criteria;
}, },
@ -239,7 +242,7 @@
this.$emit('input', result); this.$emit('input', result);
this.$emit('change', result); this.$emit('change', result);
this.dispatch('form-item', 'el.form.change', val); this.dispatch('ElFormItem', 'el.form.change', val);
if (this.filterable) { if (this.filterable) {
this.query = ''; this.query = '';
this.hoverIndex = -1; this.hoverIndex = -1;
@ -259,7 +262,7 @@
query(val) { query(val) {
this.$nextTick(() => { this.$nextTick(() => {
this.broadcast('select-dropdown', 'updatePopper'); this.broadcast('ElSelectDropdown', 'updatePopper');
}); });
if (this.multiple && this.filterable) { if (this.multiple && this.filterable) {
this.resetInputHeight(); this.resetInputHeight();
@ -268,12 +271,12 @@
this.hoverIndex = -1; this.hoverIndex = -1;
this.remoteMethod(val); this.remoteMethod(val);
this.voidRemoteQuery = val === ''; this.voidRemoteQuery = val === '';
this.broadcast('option', 'resetIndex'); this.broadcast('ElOption', 'resetIndex');
} else if (typeof this.filterMethod === 'function') { } else if (typeof this.filterMethod === 'function') {
this.filterMethod(val); this.filterMethod(val);
} else { } else {
this.filteredOptionsCount = this.optionsCount; this.filteredOptionsCount = this.optionsCount;
this.broadcast('option', 'queryChange', val); this.broadcast('ElOption', 'queryChange', val);
} }
}, },
@ -283,7 +286,7 @@
if (this.$el.querySelector('.el-input__icon')) { if (this.$el.querySelector('.el-input__icon')) {
removeClass(this.$el.querySelector('.el-input__icon'), 'is-reverse'); removeClass(this.$el.querySelector('.el-input__icon'), 'is-reverse');
} }
this.broadcast('select-dropdown', 'destroyPopper'); this.broadcast('ElSelectDropdown', 'destroyPopper');
if (this.$refs.input) { if (this.$refs.input) {
this.$refs.input.blur(); this.$refs.input.blur();
} }
@ -301,13 +304,13 @@
if (icon && !hasClass(icon, 'el-icon-circle-close')) { if (icon && !hasClass(icon, 'el-icon-circle-close')) {
addClass(this.$el.querySelector('.el-input__icon'), 'is-reverse'); addClass(this.$el.querySelector('.el-input__icon'), 'is-reverse');
} }
this.broadcast('select-dropdown', 'updatePopper'); this.broadcast('ElSelectDropdown', 'updatePopper');
if (this.filterable) { if (this.filterable) {
this.query = this.selectedLabel; this.query = this.selectedLabel;
if (this.multiple) { if (this.multiple) {
this.$refs.input.focus(); this.$refs.input.focus();
} else { } else {
this.broadcast('input', 'inputSelect'); this.broadcast('ElInput', 'inputSelect');
} }
} }
if (!this.dropdownUl) { if (!this.dropdownUl) {
@ -395,7 +398,7 @@
let inputChildNodes = this.$refs.reference.$el.childNodes; let inputChildNodes = this.$refs.reference.$el.childNodes;
let input = [].filter.call(inputChildNodes, item => item.tagName === 'INPUT')[0]; let input = [].filter.call(inputChildNodes, item => item.tagName === 'INPUT')[0];
input.style.height = Math.max(this.$refs.tags.clientHeight + 6, this.size === 'small' ? 28 : 36) + 'px'; input.style.height = Math.max(this.$refs.tags.clientHeight + 6, this.size === 'small' ? 28 : 36) + 'px';
this.broadcast('select-dropdown', 'updatePopper'); this.broadcast('ElSelectDropdown', 'updatePopper');
}); });
}, },
@ -421,7 +424,7 @@
} else { } else {
let optionIndex = -1; let optionIndex = -1;
this.selected.forEach((item, index) => { this.selected.forEach((item, index) => {
if (item === option || item.currentLabel === option.currentLabel) { if (item === option || item.currentValue === option.currentValue) {
optionIndex = index; optionIndex = index;
} }
}); });
@ -522,7 +525,7 @@
if (index > -1) { if (index > -1) {
this.options.splice(index, 1); this.options.splice(index, 1);
} }
this.broadcast('option', 'resetIndex'); this.broadcast('ElOption', 'resetIndex');
}, },
resetInputWidth() { resetInputWidth() {

View File

@ -10,6 +10,7 @@ export default {
required: true required: true
}, },
rowClassName: [String, Function], rowClassName: [String, Function],
rowStyle: [Object, Function],
fixed: String, fixed: String,
highlight: Boolean highlight: Boolean
}, },
@ -33,6 +34,7 @@ export default {
{ {
this._l(this.data, (row, $index) => this._l(this.data, (row, $index) =>
<tr <tr
style={ this.rowStyle ? this.getRowStyle(row, $index) : null }
key={ this.$parent.rowKey ? this.getKeyOfRow(row, $index) : $index } key={ this.$parent.rowKey ? this.getKeyOfRow(row, $index) : $index }
on-click={ ($event) => this.handleClick($event, row) } on-click={ ($event) => this.handleClick($event, row) }
on-mouseenter={ _ => this.handleMouseEnter($index) } on-mouseenter={ _ => this.handleMouseEnter($index) }
@ -140,6 +142,14 @@ export default {
} }
}, },
getRowStyle(row, index) {
const rowStyle = this.rowStyle;
if (typeof rowStyle === 'function') {
return rowStyle.call(null, row, index);
}
return rowStyle;
},
getRowClass(row, index) { getRowClass(row, index) {
const classes = []; const classes = [];
@ -147,7 +157,7 @@ export default {
if (typeof rowClassName === 'string') { if (typeof rowClassName === 'string') {
classes.push(rowClassName); classes.push(rowClassName);
} else if (typeof rowClassName === 'function') { } else if (typeof rowClassName === 'function') {
classes.push(rowClassName.apply(null, [row, index]) || ''); classes.push(rowClassName.call(null, row, index) || '');
} }
return classes.join(' '); return classes.join(' ');

View File

@ -24,6 +24,7 @@
:store="store" :store="store"
:layout="layout" :layout="layout"
:row-class-name="rowClassName" :row-class-name="rowClassName"
:row-style="rowStyle"
:highlight="highlightCurrentRow" :highlight="highlightCurrentRow"
:style="{ width: layout.bodyWidth ? layout.bodyWidth - (layout.scrollY ? layout.gutterWidth : 0 ) + 'px' : '' }"> :style="{ width: layout.bodyWidth ? layout.bodyWidth - (layout.scrollY ? layout.gutterWidth : 0 ) + 'px' : '' }">
</table-body> </table-body>
@ -56,6 +57,7 @@
:layout="layout" :layout="layout"
:highlight="highlightCurrentRow" :highlight="highlightCurrentRow"
:row-class-name="rowClassName" :row-class-name="rowClassName"
:row-style="rowStyle"
:style="{ width: layout.fixedWidth ? layout.fixedWidth + 'px' : '' }"> :style="{ width: layout.fixedWidth ? layout.fixedWidth + 'px' : '' }">
</table-body> </table-body>
</div> </div>
@ -85,6 +87,7 @@
:store="store" :store="store"
:layout="layout" :layout="layout"
:row-class-name="rowClassName" :row-class-name="rowClassName"
:row-style="rowStyle"
:highlight="highlightCurrentRow" :highlight="highlightCurrentRow"
:style="{ width: layout.rightFixedWidth ? layout.rightFixedWidth + 'px' : '' }"> :style="{ width: layout.rightFixedWidth ? layout.rightFixedWidth + 'px' : '' }">
</table-body> </table-body>
@ -145,6 +148,8 @@
rowClassName: [String, Function], rowClassName: [String, Function],
rowStyle: [Object, Function],
highlightCurrentRow: Boolean, highlightCurrentRow: Boolean,
emptyText: { emptyText: {

View File

@ -60,11 +60,6 @@
top: 100%; top: 100%;
left: 0; left: 0;
} }
& .el-button + .el-button,
& .el-checkbox + .el-checkbox,
& .el-radio + .el-radio {
margin-left: 10px;
}
@when required { @when required {
.el-form-item__label:before { .el-form-item__label:before {

View File

@ -40,6 +40,7 @@
width: 35px; width: 35px;
height: 100%; height: 100%;
right: 0; right: 0;
top: 0;
text-align: center; text-align: center;
color: var(--input-icon-color); color: var(--input-icon-color);

View File

@ -160,15 +160,6 @@
z-index: -1; z-index: -1;
left: -999px; left: -999px;
&:checked {
& + .el-radio-button__inner {
z-index: 1;
background-color: var(--color-primary);
border-color: @background-color;
color: #fff;
}
}
&:disabled { &:disabled {
& + .el-radio-button__inner { & + .el-radio-button__inner {
color: var(--button-disabled-color); color: var(--button-disabled-color);

View File

@ -145,7 +145,7 @@
& img { & img {
display: block; display: block;
width: 100%; width: 100%;
height: auto; height: 100%;
} }
@e progress { @e progress {

View File

@ -97,15 +97,7 @@ export default class Node {
const defaultExpandedKeys = store.defaultExpandedKeys; const defaultExpandedKeys = store.defaultExpandedKeys;
const key = store.key; const key = store.key;
if (key && defaultExpandedKeys && defaultExpandedKeys.indexOf(this.key) !== -1) { if (key && defaultExpandedKeys && defaultExpandedKeys.indexOf(this.key) !== -1) {
if (store.autoExpandParent) { this.expand(null, store.autoExpandParent);
let parent = this.parent;
while (parent.level > 0) {
parent.expanded = true;
parent = parent.parent;
}
}
this.expand();
} }
if (store.lazy) { if (store.lazy) {
@ -213,17 +205,27 @@ export default class Node {
} }
} }
expand(callback) { expand(callback, expandParent) {
const done = () => {
if (expandParent) {
let parent = this.parent;
while (parent.level > 0) {
parent.expanded = true;
parent = parent.parent;
}
}
this.expanded = true;
if (callback) callback();
};
if (this.shouldLoadData()) { if (this.shouldLoadData()) {
this.loadData((data) => { this.loadData((data) => {
if (data instanceof Array) { if (data instanceof Array) {
this.expanded = true; done();
if (callback) callback();
} }
}); });
} else { } else {
this.expanded = true; done();
if (callback) callback();
} }
} }

View File

@ -66,30 +66,30 @@ export default class TreeStore {
} }
} }
getNodeByData(data) { getNode(data) {
const key = typeof data === 'string' ? data : getNodeKey(this.key, data); const key = typeof data !== 'object' ? data : getNodeKey(this.key, data);
return this.nodesMap[key]; return this.nodesMap[key];
} }
insertBefore(data, refData) { insertBefore(data, refData) {
const refNode = this.getNodeByData(refData); const refNode = this.getNode(refData);
refNode.parent.insertBefore({ data }, refNode); refNode.parent.insertBefore({ data }, refNode);
} }
insertAfter(data, refData) { insertAfter(data, refData) {
const refNode = this.getNodeByData(refData); const refNode = this.getNode(refData);
refNode.parent.insertAfter({ data }, refNode); refNode.parent.insertAfter({ data }, refNode);
} }
remove(data) { remove(data) {
const node = this.getNodeByData(data); const node = this.getNode(data);
if (node) { if (node) {
node.parent.removeChild(node); node.parent.removeChild(node);
} }
} }
append(data, parentData) { append(data, parentData) {
const parentNode = parentData ? this.getNodeByData(parentData) : this.root; const parentNode = parentData ? this.getNode(parentData) : this.root;
if (parentNode) { if (parentNode) {
parentNode.insertChild({ data }); parentNode.insertChild({ data });
@ -206,6 +206,7 @@ export default class TreeStore {
} }
setCheckedKeys(keys, leafOnly = true) { setCheckedKeys(keys, leafOnly = true) {
this.defaultCheckedKeys = keys;
const key = this.key; const key = this.key;
const checkedKeys = {}; const checkedKeys = {};
keys.forEach((key) => { keys.forEach((key) => {
@ -214,4 +215,14 @@ export default class TreeStore {
this._setCheckedKeys(key, leafOnly, checkedKeys); this._setCheckedKeys(key, leafOnly, checkedKeys);
} }
setDefaultExpandedKeys(keys) {
keys = keys || [];
this.defaultExpandedKeys = keys;
keys.forEach((key) => {
const node = this.getNode(key);
if (node) node.expand(null, this.autoExpandParent);
});
}
}; };

View File

@ -40,6 +40,7 @@
<script type="text/jsx"> <script type="text/jsx">
import CollapseTransition from './transition'; import CollapseTransition from './transition';
import ElCheckbox from 'element-ui/packages/checkbox'
export default { export default {
name: 'el-tree-node', name: 'el-tree-node',
@ -55,6 +56,7 @@
}, },
components: { components: {
ElCheckbox,
CollapseTransition, CollapseTransition,
NodeContent: { NodeContent: {
props: { props: {

View File

@ -106,11 +106,16 @@
}, },
watch: { watch: {
defaultCheckedKeys(newVal) {
this.store.defaultCheckedKeys = newVal;
this.store.setDefaultCheckedKey(newVal);
},
defaultExpandedKeys(newVal) {
this.store.defaultExpandedKeys = newVal;
this.store.setDefaultExpandedKeys(newVal);
},
data(newVal) { data(newVal) {
this.store.setData(newVal); this.store.setData(newVal);
},
defaultCheckedKeys(newVal) {
this.store.setDefaultCheckedKey(newVal);
} }
}, },

View File

@ -65,6 +65,12 @@ export default {
onError: { onError: {
type: Function, type: Function,
default: noop default: noop
},
defaultFileList: {
type: Array,
default() {
return [];
}
} }
}, },
@ -152,6 +158,20 @@ export default {
} }
}, },
watch: {
defaultFileList: {
immediate: true,
handler(fileList) {
this.fileList = fileList.map(item => {
item.status = 'finished';
item.percentage = 100;
item.uid = Date.now() + this.tempIndex++;
return item;
});
}
}
},
render(h) { render(h) {
var uploadList; var uploadList;

View File

@ -12,7 +12,7 @@ export default {
startTime: 'Horaire début', startTime: 'Horaire début',
endDate: 'Date fin', endDate: 'Date fin',
endTime: 'Horaire fin', endTime: 'Horaire fin',
year: 'Année', year: '',
month1: 'Janvier', month1: 'Janvier',
month2: 'Février', month2: 'Février',
month3: 'Mars', month3: 'Mars',

View File

@ -5,7 +5,7 @@ function broadcast(componentName, eventName, params) {
if (name === componentName) { if (name === componentName) {
child.$emit.apply(child, [eventName].concat(params)); child.$emit.apply(child, [eventName].concat(params));
} else { } else {
broadcast.apply(child, [componentName, eventName].concat(params)); broadcast.apply(child, [componentName, eventName].concat([params]));
} }
}); });
} }

View File

@ -152,5 +152,10 @@ export default {
this.popperElm && this.popperElm &&
this.popperElm.parentNode === document.body && this.popperElm.parentNode === document.body &&
document.body.removeChild(this.popperElm); document.body.removeChild(this.popperElm);
},
// call destroy in keep-alive mode
deactivated() {
this.$options.beforeDestroy[0].call(this);
} }
}; };

View File

@ -67,6 +67,33 @@ describe('Checkbox', () => {
done(); done();
}); });
}); });
it('nested group', done => {
vm = createVue({
template: `
<el-checkbox-group v-model="checkList">
<el-row>
<el-checkbox label="a" ref="a"></el-checkbox>
<el-checkbox label="b" ref="b"></el-checkbox>
<el-checkbox label="c" ref="c"></el-checkbox>
<el-checkbox label="d" ref="d"></el-checkbox>
</el-row>
</el-checkbox-group>
`,
data() {
return {
checkList: []
};
}
}, true);
expect(vm.checkList.length === 0).to.be.true;
vm.$refs.a.$el.click();
vm.$nextTick(_ => {
expect(vm.checkList.indexOf('a') !== -1).to.be.true;
done();
});
});
it('true false label', done => { it('true false label', done => {
vm = createVue({ vm = createVue({
template: ` template: `

View File

@ -192,7 +192,7 @@ describe('Form', () => {
vm = createVue({ vm = createVue({
template: ` template: `
<el-form :model="form" :rules="rules" ref="form"> <el-form :model="form" :rules="rules" ref="form">
<el-form-item label="活动名称" prop="name"> <el-form-item label="活动名称" prop="name" ref="field">
<el-input v-model="form.name"></el-input> <el-input v-model="form.name"></el-input>
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -216,18 +216,18 @@ describe('Form', () => {
} }
}, true); }, true);
vm.$refs.form.validate(valid => { vm.$refs.form.validate(valid => {
let fields = vm.$refs.form.fields; let field = vm.$refs.field;
expect(valid).to.not.true; expect(valid).to.not.true;
vm.$refs.form.$nextTick(_ => { vm.$refs.form.$nextTick(_ => {
expect(fields.name.validateMessage).to.equal('请输入活动名称'); expect(field.validateMessage).to.equal('请输入活动名称');
vm.setValue('aaaaa'); vm.setValue('aaaaa');
vm.$refs.form.$nextTick(_ => { vm.$refs.form.$nextTick(_ => {
expect(fields.name.validateMessage).to.equal(''); expect(field.validateMessage).to.equal('');
vm.setValue('aa'); vm.setValue('aa');
vm.$refs.form.$nextTick(_ => { vm.$refs.form.$nextTick(_ => {
expect(fields.name.validateMessage).to.equal('请输入活动名称'); expect(field.validateMessage).to.equal('请输入活动名称');
done(); done();
}); });
}); });
@ -238,7 +238,7 @@ describe('Form', () => {
vm = createVue({ vm = createVue({
template: ` template: `
<el-form :model="form" :rules="rules" ref="form"> <el-form :model="form" :rules="rules" ref="form">
<el-form-item label="活动名称" prop="name"> <el-form-item label="活动名称" prop="name" ref="field">
<el-input type="textarea" v-model="form.name"></el-input> <el-input type="textarea" v-model="form.name"></el-input>
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -262,18 +262,18 @@ describe('Form', () => {
} }
}, true); }, true);
vm.$refs.form.validate(valid => { vm.$refs.form.validate(valid => {
let fields = vm.$refs.form.fields; let field = vm.$refs.field;
expect(valid).to.not.true; expect(valid).to.not.true;
vm.$refs.form.$nextTick(_ => { vm.$refs.form.$nextTick(_ => {
expect(fields.name.validateMessage).to.equal('请输入活动名称'); expect(field.validateMessage).to.equal('请输入活动名称');
vm.setValue('aaaaa'); vm.setValue('aaaaa');
vm.$refs.form.$nextTick(_ => { vm.$refs.form.$nextTick(_ => {
expect(fields.name.validateMessage).to.equal(''); expect(field.validateMessage).to.equal('');
vm.setValue('aa'); vm.setValue('aa');
vm.$refs.form.$nextTick(_ => { vm.$refs.form.$nextTick(_ => {
expect(fields.name.validateMessage).to.equal('请输入活动名称'); expect(field.validateMessage).to.equal('请输入活动名称');
done(); done();
}); });
}); });
@ -284,7 +284,7 @@ describe('Form', () => {
vm = createVue({ vm = createVue({
template: ` template: `
<el-form :model="form" :rules="rules" ref="form"> <el-form :model="form" :rules="rules" ref="form">
<el-form-item label="记住密码" prop="region"> <el-form-item label="记住密码" prop="region" ref="field">
<el-select v-model="form.region" placeholder="请选择活动区域"> <el-select v-model="form.region" placeholder="请选择活动区域">
<el-option label="区域一" value="shanghai"></el-option> <el-option label="区域一" value="shanghai"></el-option>
<el-option label="区域二" value="beijing"></el-option> <el-option label="区域二" value="beijing"></el-option>
@ -311,15 +311,15 @@ describe('Form', () => {
} }
}, true); }, true);
vm.$refs.form.validate(valid => { vm.$refs.form.validate(valid => {
let fields = vm.$refs.form.fields; let field = vm.$refs.field;
expect(valid).to.true; expect(valid).to.true;
vm.setValue(''); vm.setValue('');
setTimeout(_ => { setTimeout(_ => {
expect(fields.region.validateMessage).to.equal('请选择活动区域'); expect(field.validateMessage).to.equal('请选择活动区域');
vm.setValue('shanghai'); vm.setValue('shanghai');
setTimeout(_ => { setTimeout(_ => {
expect(fields.region.validateMessage).to.equal(''); expect(field.validateMessage).to.equal('');
done(); done();
}, 100); }, 100);
}, 100); }, 100);
@ -329,7 +329,7 @@ describe('Form', () => {
vm = createVue({ vm = createVue({
template: ` template: `
<el-form :model="form" :rules="rules" ref="form"> <el-form :model="form" :rules="rules" ref="form">
<el-form-item label="记住密码" prop="date"> <el-form-item label="记住密码" prop="date" ref="field">
<el-date-picker type="date" placeholder="选择日期" v-model="form.date" style="width: 100%;"></el-date-picker> <el-date-picker type="date" placeholder="选择日期" v-model="form.date" style="width: 100%;"></el-date-picker>
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -353,15 +353,15 @@ describe('Form', () => {
} }
}, true); }, true);
vm.$refs.form.validate(valid => { vm.$refs.form.validate(valid => {
let fields = vm.$refs.form.fields; let field = vm.$refs.field;
expect(valid).to.not.true; expect(valid).to.not.true;
vm.$refs.form.$nextTick(_ => { vm.$refs.form.$nextTick(_ => {
expect(fields.date.validateMessage).to.equal('请选择日期'); expect(field.validateMessage).to.equal('请选择日期');
vm.setValue(new Date()); vm.setValue(new Date());
vm.$refs.form.$nextTick(_ => { vm.$refs.form.$nextTick(_ => {
expect(fields.date.validateMessage).to.equal(''); expect(field.validateMessage).to.equal('');
done(); done();
}); });
}); });
@ -371,7 +371,7 @@ describe('Form', () => {
vm = createVue({ vm = createVue({
template: ` template: `
<el-form :model="form" :rules="rules" ref="form"> <el-form :model="form" :rules="rules" ref="form">
<el-form-item label="记住密码" prop="date"> <el-form-item label="记住密码" prop="date" ref="field">
<el-time-picker type="fixed-time" placeholder="选择时间" v-model="form.date" style="width: 100%;"></el-time-picker> <el-time-picker type="fixed-time" placeholder="选择时间" v-model="form.date" style="width: 100%;"></el-time-picker>
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -395,14 +395,14 @@ describe('Form', () => {
} }
}, true); }, true);
vm.$refs.form.validate(valid => { vm.$refs.form.validate(valid => {
let fields = vm.$refs.form.fields; let field = vm.$refs.field;
expect(valid).to.not.true; expect(valid).to.not.true;
vm.$refs.form.$nextTick(_ => { vm.$refs.form.$nextTick(_ => {
expect(fields.date.validateMessage).to.equal('请选择时间'); expect(field.validateMessage).to.equal('请选择时间');
vm.setValue(new Date()); vm.setValue(new Date());
vm.$refs.form.$nextTick(_ => { vm.$refs.form.$nextTick(_ => {
expect(fields.date.validateMessage).to.equal(''); expect(field.validateMessage).to.equal('');
done(); done();
}); });
}); });
@ -412,7 +412,7 @@ describe('Form', () => {
vm = createVue({ vm = createVue({
template: ` template: `
<el-form :model="form" :rules="rules" ref="form"> <el-form :model="form" :rules="rules" ref="form">
<el-form-item label="活动名称" prop="type"> <el-form-item label="活动名称" prop="type" ref="field">
<el-checkbox-group v-model="form.type"> <el-checkbox-group v-model="form.type">
<el-checkbox label="美食/餐厅线上活动" name="type"></el-checkbox> <el-checkbox label="美食/餐厅线上活动" name="type"></el-checkbox>
<el-checkbox label="地推活动" name="type"></el-checkbox> <el-checkbox label="地推活动" name="type"></el-checkbox>
@ -441,14 +441,14 @@ describe('Form', () => {
} }
}, true); }, true);
vm.$refs.form.validate(valid => { vm.$refs.form.validate(valid => {
let fields = vm.$refs.form.fields; let field = vm.$refs.field;
expect(valid).to.not.true; expect(valid).to.not.true;
vm.$refs.form.$nextTick(_ => { vm.$refs.form.$nextTick(_ => {
expect(fields.type.validateMessage).to.equal('请选择活动类型'); expect(field.validateMessage).to.equal('请选择活动类型');
vm.setValue(['地推活动']); vm.setValue(['地推活动']);
vm.$refs.form.$nextTick(_ => { vm.$refs.form.$nextTick(_ => {
expect(fields.type.validateMessage).to.equal(''); expect(field.validateMessage).to.equal('');
done(); done();
}); });
}); });
@ -458,7 +458,7 @@ describe('Form', () => {
vm = createVue({ vm = createVue({
template: ` template: `
<el-form :model="form" :rules="rules" ref="form"> <el-form :model="form" :rules="rules" ref="form">
<el-form-item label="活动名称" prop="type"> <el-form-item label="活动名称" prop="type" ref="field">
<el-radio-group v-model="form.type"> <el-radio-group v-model="form.type">
<el-radio label="线上品牌商赞助"></el-radio> <el-radio label="线上品牌商赞助"></el-radio>
<el-radio label="线下场地免费"></el-radio> <el-radio label="线下场地免费"></el-radio>
@ -485,14 +485,14 @@ describe('Form', () => {
} }
}, true); }, true);
vm.$refs.form.validate(valid => { vm.$refs.form.validate(valid => {
let fields = vm.$refs.form.fields; let field = vm.$refs.field;
expect(valid).to.not.true; expect(valid).to.not.true;
vm.$refs.form.$nextTick(_ => { vm.$refs.form.$nextTick(_ => {
expect(fields.type.validateMessage).to.equal('请选择活动类型'); expect(field.validateMessage).to.equal('请选择活动类型');
vm.setValue('线下场地免费'); vm.setValue('线下场地免费');
vm.$refs.form.$nextTick(_ => { vm.$refs.form.$nextTick(_ => {
expect(fields.type.validateMessage).to.equal(''); expect(field.validateMessage).to.equal('');
done(); done();
}); });
}); });
@ -502,7 +502,7 @@ describe('Form', () => {
vm = createVue({ vm = createVue({
template: ` template: `
<el-form :model="form" :rules="rules" ref="form"> <el-form :model="form" :rules="rules" ref="form">
<el-form-item label="活动名称" prop="name"> <el-form-item label="活动名称" prop="name" ref="field">
<el-input v-model="form.name"></el-input> <el-input v-model="form.name"></el-input>
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -541,7 +541,7 @@ describe('Form', () => {
vm = createVue({ vm = createVue({
template: ` template: `
<el-form :model="form" :rules="rules" ref="form"> <el-form :model="form" :rules="rules" ref="form">
<el-form-item label="活动名称" prop="name"> <el-form-item label="活动名称" prop="name" ref="field">
<el-input v-model="form.name"></el-input> <el-input v-model="form.name"></el-input>
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -565,14 +565,14 @@ describe('Form', () => {
} }
}, true); }, true);
vm.$refs.form.validate(valid => { vm.$refs.form.validate(valid => {
let fields = vm.$refs.form.fields; let field = vm.$refs.field;
expect(valid).to.not.true; expect(valid).to.not.true;
vm.$refs.form.$nextTick(_ => { vm.$refs.form.$nextTick(_ => {
expect(fields.name.validateMessage).to.equal('长度至少为5'); expect(field.validateMessage).to.equal('长度至少为5');
vm.setValue('aaaaaa'); vm.setValue('aaaaaa');
vm.$refs.form.$nextTick(_ => { vm.$refs.form.$nextTick(_ => {
expect(fields.name.validateMessage).to.equal(''); expect(field.validateMessage).to.equal('');
done(); done();
}); });
}); });
@ -582,7 +582,7 @@ describe('Form', () => {
vm = createVue({ vm = createVue({
template: ` template: `
<el-form :model="form" :rules="rules" ref="form"> <el-form :model="form" :rules="rules" ref="form">
<el-form-item label="活动名称" prop="name" :error="error" ref="formitem"> <el-form-item label="活动名称" prop="name" :error="error" ref="field">
<el-input v-model="form.name"></el-input> <el-input v-model="form.name"></el-input>
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -607,13 +607,13 @@ describe('Form', () => {
} }
}, true); }, true);
vm.$refs.form.validate(valid => { vm.$refs.form.validate(valid => {
let fields = vm.$refs.form.fields; let field = vm.$refs.field;
expect(valid).to.true; expect(valid).to.true;
vm.error = '输入不合法'; vm.error = '输入不合法';
vm.$refs.formitem.$nextTick(_ => { vm.$refs.field.$nextTick(_ => {
expect(fields.name.validateState).to.equal('error'); expect(field.validateState).to.equal('error');
expect(fields.name.validateMessage).to.equal('输入不合法'); expect(field.validateMessage).to.equal('输入不合法');
done(); done();
}); });
}); });

View File

@ -65,37 +65,63 @@ describe('Radio', () => {
}; };
} }
}, true); }, true);
expect(vm.$refs.radio1.$el.querySelector('.is-checked')).to.be.ok; setTimeout(_ => {
let radioElm = vm.$refs.radio2.$el; expect(vm.$refs.radio1.$el.querySelector('.is-checked')).to.be.ok;
radioElm.click(); let radioElm = vm.$refs.radio2.$el;
vm.$nextTick(_ => { radioElm.click();
expect(radioElm.querySelector('.is-checked')).to.be.ok; vm.$nextTick(_ => {
expect(vm.radio === 6).to.be.true; expect(radioElm.querySelector('.is-checked')).to.be.ok;
done(); expect(vm.radio === 6).to.be.true;
}); done();
});
}, 50);
}); });
it('radio button', done => { describe('Radio', () => {
vm = createVue({ it('create', done => {
template: ` vm = createVue({
<el-radio-group v-model="radio"> template: `
<el-radio-button :label="3" ref="radio1">备选项</el-radio-button> <el-radio-group v-model="radio">
<el-radio-button :label="6" ref="radio2">备选项</el-radio-button> <el-radio-button :label="3" ref="radio1">备选项</el-radio-button>
<el-radio-button :label="9">备选项</el-radio-button> <el-radio-button :label="6" ref="radio2">备选项</el-radio-button>
</el-radio-group> <el-radio-button :label="9">备选项</el-radio-button>
`, </el-radio-group>
data() { `,
return { data() {
radio: 3 return {
}; radio: 3
} };
}, true); }
expect(vm.$refs.radio1.$el.classList.contains('is-active')).to.be.true; }, true);
let radio = vm.$refs.radio2; expect(vm.$refs.radio1.$el.classList.contains('is-active')).to.be.true;
radio.$el.click(); let radio = vm.$refs.radio2;
vm.$nextTick(_ => { radio.$el.click();
expect(radio.$el.classList.contains('is-active')).to.be.true; vm.$nextTick(_ => {
expect(vm.radio === 6).to.be.true; expect(radio.$el.classList.contains('is-active')).to.be.true;
done(); expect(vm.radio === 6).to.be.true;
done();
});
});
it('custom color', done => {
vm = createVue({
template: `
<el-radio-group v-model="radio" fill="#000" text-color="#ff0">
<el-radio-button :label="3" ref="radio1">备选项</el-radio-button>
<el-radio-button :label="6" ref="radio2">备选项</el-radio-button>
<el-radio-button :label="9">备选项</el-radio-button>
</el-radio-group>
`,
data() {
return {
radio: 3
};
}
}, true);
vm.$nextTick(_ => {
expect(vm.$refs.radio1.activeStyle.backgroundColor).to.equal('#000');
expect(vm.$refs.radio1.activeStyle.borderColor).to.equal('#000');
expect(vm.$refs.radio1.activeStyle.color).to.equal('#ff0');
done();
});
}); });
}); });
}); });

View File

@ -147,6 +147,37 @@ describe('Table', () => {
done(); done();
}, DELAY); }, DELAY);
}); });
it('tableRowStyle[Object]', done => {
const vm = createTable(':row-style="{ height: \'60px\' }"', {});
setTimeout(_ => {
expect(vm.$el.querySelector('.el-table__body tr').style.height).to.equal('60px');
destroyVM(vm);
done();
}, DELAY);
});
it('tableRowStyle[Function]', done => {
const vm = createTable(':row-style="tableRowStyle"', {
methods: {
tableRowStyle(row, index) {
if (index === 1) {
return { height: '60px' };
}
return null;
}
}
});
setTimeout(_ => {
expect(vm.$el.querySelector('.el-table__body tr:nth-child(1)').style.height).to.equal('');
expect(vm.$el.querySelector('.el-table__body tr:nth-child(2)').style.height).to.equal('60px');
destroyVM(vm);
done();
}, DELAY);
});
}); });
describe('filter', () => { describe('filter', () => {

View File

@ -127,6 +127,21 @@ describe('Tree', () => {
expect(vm.$el.querySelectorAll('.el-tree-node.is-expanded').length).to.equal(2); expect(vm.$el.querySelectorAll('.el-tree-node.is-expanded').length).to.equal(2);
}); });
it('defaultExpandedKeys set', (done) => {
vm = getTreeVm(':props="defaultProps" :default-expanded-keys="defaultExpandedKeys" node-key="id"', {
created() {
this.defaultExpandedKeys = [1, 3];
}
});
expect(vm.$el.querySelectorAll('.el-tree-node.is-expanded').length).to.equal(2);
vm.defaultExpandedKeys = [2];
vm.data = JSON.parse(JSON.stringify(vm.data));
setTimeout(() => {
expect(vm.$el.querySelectorAll('.el-tree-node.is-expanded').length).to.equal(1);
done();
}, 50);
});
it('filter-node-method', (done) => { it('filter-node-method', (done) => {
vm = getTreeVm(':props="defaultProps" :filter-node-method="filterNode"', { vm = getTreeVm(':props="defaultProps" :filter-node-method="filterNode"', {
methods: { methods: {