mirror of https://github.com/ElemeFE/element
insert autocomplete suggestions to body
parent
7d3bbc8ad4
commit
3c0a784aca
|
@ -117,7 +117,8 @@
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.my-autocomplete {
|
}
|
||||||
|
.el-autocomplete__suggestions.my-autocomplete {
|
||||||
li {
|
li {
|
||||||
line-height: normal;
|
line-height: normal;
|
||||||
padding: 7px *;
|
padding: 7px *;
|
||||||
|
@ -136,7 +137,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
## Input
|
## Input
|
||||||
|
@ -326,7 +326,7 @@ export default {
|
||||||
```
|
```
|
||||||
:::
|
:::
|
||||||
|
|
||||||
### Auto complete
|
### Autocomplete
|
||||||
|
|
||||||
You can get some recommended tips based on the current input.
|
You can get some recommended tips based on the current input.
|
||||||
|
|
||||||
|
@ -406,7 +406,7 @@ Customize how suggestions are displayed.
|
||||||
:::demo
|
:::demo
|
||||||
```html
|
```html
|
||||||
<el-autocomplete
|
<el-autocomplete
|
||||||
class="my-autocomplete"
|
popper-class="my-autocomplete"
|
||||||
v-model="state3"
|
v-model="state3"
|
||||||
:fetch-suggestions="querySearch"
|
:fetch-suggestions="querySearch"
|
||||||
custom-item="my-item-en"
|
custom-item="my-item-en"
|
||||||
|
@ -587,6 +587,7 @@ Attribute | Description | Type | Options | Default
|
||||||
|value | binding value | string | — | — |
|
|value | binding value | string | — | — |
|
||||||
|custom-item | component name of your customized suggestion list item | string | — | — |
|
|custom-item | component name of your customized suggestion list item | string | — | — |
|
||||||
|fetch-suggestions | a method to fetch input suggestions. When suggestions are ready, invoke `callback(data:[])` to return them to Autocomplete | Function(queryString, callback) | — | — |
|
|fetch-suggestions | a method to fetch input suggestions. When suggestions are ready, invoke `callback(data:[])` to return them to Autocomplete | Function(queryString, callback) | — | — |
|
||||||
|
| popper-class | custom class name for autocomplete's dropdown | string | — | — |
|
||||||
|
|
||||||
### Autocomplete Events
|
### Autocomplete Events
|
||||||
|
|
||||||
|
|
|
@ -158,7 +158,8 @@
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.my-autocomplete {
|
}
|
||||||
|
.el-autocomplete__suggestions.my-autocomplete {
|
||||||
li {
|
li {
|
||||||
line-height: normal;
|
line-height: normal;
|
||||||
padding: 7px *;
|
padding: 7px *;
|
||||||
|
@ -177,7 +178,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
## Input 输入框
|
## Input 输入框
|
||||||
|
@ -483,7 +483,7 @@ export default {
|
||||||
::: demo
|
::: demo
|
||||||
```html
|
```html
|
||||||
<el-autocomplete
|
<el-autocomplete
|
||||||
class="my-autocomplete"
|
popper-class="my-autocomplete"
|
||||||
v-model="state3"
|
v-model="state3"
|
||||||
:fetch-suggestions="querySearch"
|
:fetch-suggestions="querySearch"
|
||||||
custom-item="my-item-zh"
|
custom-item="my-item-zh"
|
||||||
|
@ -748,6 +748,7 @@ export default {
|
||||||
| value | 必填值输入绑定值 | string | — | — |
|
| value | 必填值输入绑定值 | string | — | — |
|
||||||
| custom-item | 通过该参数指定自定义的输入建议列表项的组件名 | string | — | — |
|
| custom-item | 通过该参数指定自定义的输入建议列表项的组件名 | string | — | — |
|
||||||
| fetch-suggestions | 返回输入建议的方法,仅当你的输入建议数据 resolve 时,通过调用 callback(data:[]) 来返回它 | Function(queryString, callback) | — | — |
|
| fetch-suggestions | 返回输入建议的方法,仅当你的输入建议数据 resolve 时,通过调用 callback(data:[]) 来返回它 | Function(queryString, callback) | — | — |
|
||||||
|
| popper-class | Autocomplete 下拉列表的类名 | string | — | — |
|
||||||
|
|
||||||
### Autocomplete Events
|
### Autocomplete Events
|
||||||
| 事件名称 | 说明 | 回调参数 |
|
| 事件名称 | 说明 | 回调参数 |
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
<template>
|
||||||
|
<transition name="el-zoom-in-top" @after-leave="doDestroy">
|
||||||
|
<ul
|
||||||
|
v-show="showPopper"
|
||||||
|
class="el-autocomplete__suggestions"
|
||||||
|
:class="{ 'is-loading': parent.loading }"
|
||||||
|
:style="{ width: dropdownWidth }"
|
||||||
|
>
|
||||||
|
<li v-if="parent.loading"><i class="el-icon-loading"></i></li>
|
||||||
|
<template v-for="(item, index) in suggestions" v-else>
|
||||||
|
<li
|
||||||
|
v-if="!parent.customItem"
|
||||||
|
:class="{'highlighted': parent.highlightedIndex === index}"
|
||||||
|
@click="parent.select(index)"
|
||||||
|
>
|
||||||
|
{{item.value}}
|
||||||
|
</li>
|
||||||
|
<component
|
||||||
|
v-else
|
||||||
|
:class="{'highlighted': parent.highlightedIndex === index}"
|
||||||
|
@click="parent.select(index)"
|
||||||
|
:is="parent.customItem"
|
||||||
|
:item="item"
|
||||||
|
:index="index">
|
||||||
|
</component>
|
||||||
|
</template>
|
||||||
|
</ul>
|
||||||
|
</transition>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import Popper from 'element-ui/src/utils/vue-popper';
|
||||||
|
export default {
|
||||||
|
mixins: [Popper],
|
||||||
|
|
||||||
|
componentName: 'ElAutocompleteSuggestions',
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
parent: this.$parent,
|
||||||
|
dropdownWidth: ''
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
suggestions: Array,
|
||||||
|
options: {
|
||||||
|
default() {
|
||||||
|
return {
|
||||||
|
forceAbsolute: true,
|
||||||
|
gpuAcceleration: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.popperElm = this.$el;
|
||||||
|
this.referenceElm = this.$parent.$el;
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
this.$on('visible', (val, inputWidth) => {
|
||||||
|
this.dropdownWidth = inputWidth + 'px';
|
||||||
|
this.showPopper = val;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -19,47 +19,34 @@
|
||||||
<slot name="append"></slot>
|
<slot name="append"></slot>
|
||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
<transition name="el-zoom-in-top">
|
<el-autocomplete-suggestions
|
||||||
<ul
|
:class="[popperClass ? popperClass : '']"
|
||||||
v-if="suggestionVisible"
|
|
||||||
class="el-autocomplete__suggestions"
|
|
||||||
:class="{ 'is-loading': loading }"
|
|
||||||
ref="suggestions"
|
ref="suggestions"
|
||||||
|
:suggestions="suggestions"
|
||||||
>
|
>
|
||||||
<li v-if="loading"><i class="el-icon-loading"></i></li>
|
</el-autocomplete-suggestions>
|
||||||
<template v-for="(item, index) in suggestions" v-else>
|
|
||||||
<li
|
|
||||||
v-if="!customItem"
|
|
||||||
:class="{'highlighted': highlightedIndex === index}"
|
|
||||||
@click="select(index)"
|
|
||||||
>
|
|
||||||
{{item.value}}
|
|
||||||
</li>
|
|
||||||
<component
|
|
||||||
v-else
|
|
||||||
:class="{'highlighted': highlightedIndex === index}"
|
|
||||||
@click="select(index)"
|
|
||||||
:is="customItem"
|
|
||||||
:item="item"
|
|
||||||
:index="index">
|
|
||||||
</component>
|
|
||||||
</template>
|
|
||||||
</ul>
|
|
||||||
</transition>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import ElInput from 'element-ui/packages/input';
|
import ElInput from 'element-ui/packages/input';
|
||||||
import Clickoutside from 'element-ui/src/utils/clickoutside';
|
import Clickoutside from 'element-ui/src/utils/clickoutside';
|
||||||
|
import ElAutocompleteSuggestions from './autocomplete-suggestions.vue';
|
||||||
|
import Emitter from 'element-ui/src/mixins/emitter';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ElAutocomplete',
|
name: 'ElAutocomplete',
|
||||||
|
|
||||||
|
mixins: [Emitter],
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
ElInput
|
ElInput,
|
||||||
|
ElAutocompleteSuggestions
|
||||||
},
|
},
|
||||||
|
|
||||||
directives: { Clickoutside },
|
directives: { Clickoutside },
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
|
popperClass: String,
|
||||||
placeholder: String,
|
placeholder: String,
|
||||||
disabled: Boolean,
|
disabled: Boolean,
|
||||||
name: String,
|
name: String,
|
||||||
|
@ -80,8 +67,10 @@
|
||||||
highlightedIndex: -1
|
highlightedIndex: -1
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
watch: {
|
||||||
this.$parent.popperElm = this.popperElm = this.$el;
|
suggestionVisible(val) {
|
||||||
|
this.broadcast('ElAutocompleteSuggestions', 'visible', [val, this.$el.offsetWidth]);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleChange(value) {
|
handleChange(value) {
|
||||||
|
@ -107,7 +96,6 @@
|
||||||
},
|
},
|
||||||
hideSuggestions() {
|
hideSuggestions() {
|
||||||
this.suggestionVisible = false;
|
this.suggestionVisible = false;
|
||||||
this.suggestions = [];
|
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
},
|
},
|
||||||
showSuggestions(value) {
|
showSuggestions(value) {
|
||||||
|
@ -129,8 +117,8 @@
|
||||||
} else if (index >= this.suggestions.length) {
|
} else if (index >= this.suggestions.length) {
|
||||||
index = this.suggestions.length - 1;
|
index = this.suggestions.length - 1;
|
||||||
}
|
}
|
||||||
|
var elSuggestions = this.$refs.suggestions.$el;
|
||||||
|
|
||||||
var elSuggestions = this.$refs.suggestions;
|
|
||||||
var elSelect = elSuggestions.children[index];
|
var elSelect = elSuggestions.children[index];
|
||||||
var scrollTop = elSuggestions.scrollTop;
|
var scrollTop = elSuggestions.scrollTop;
|
||||||
var offsetTop = elSelect.offsetTop;
|
var offsetTop = elSelect.offsetTop;
|
||||||
|
@ -144,6 +132,9 @@
|
||||||
|
|
||||||
this.highlightedIndex = index;
|
this.highlightedIndex = index;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
this.$refs.suggestions.$destroy();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 110%;
|
top: 110%;
|
||||||
margin: 0;
|
margin: 5px 0 0;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border: 1px solid #D3DCE6;
|
border: 1px solid #D3DCE6;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
|
@ -9,6 +9,7 @@ describe('Autocomplete', () => {
|
||||||
vm = createVue({
|
vm = createVue({
|
||||||
template: `
|
template: `
|
||||||
<el-autocomplete
|
<el-autocomplete
|
||||||
|
ref="autocomplete"
|
||||||
v-model="state"
|
v-model="state"
|
||||||
:fetch-suggestions="querySearch"
|
:fetch-suggestions="querySearch"
|
||||||
placeholder="请输入内容autocomplete1"
|
placeholder="请输入内容autocomplete1"
|
||||||
|
@ -51,12 +52,12 @@ describe('Autocomplete', () => {
|
||||||
expect(inputElm.getAttribute('placeholder')).to.be.equal('请输入内容autocomplete1');
|
expect(inputElm.getAttribute('placeholder')).to.be.equal('请输入内容autocomplete1');
|
||||||
|
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
let suggestionsList = elm.querySelector('.el-autocomplete__suggestions');
|
let suggestionsList = vm.$refs.autocomplete.$refs.suggestions.$el;
|
||||||
expect(suggestionsList).to.exist;
|
expect(suggestionsList.style.display).to.not.equal('none');
|
||||||
expect(suggestionsList.children.length).to.be.equal(4);
|
expect(suggestionsList.children.length).to.be.equal(4);
|
||||||
document.body.click();
|
document.body.click();
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
expect(elm.querySelector('.el-autocomplete__suggestions')).to.not.exist;
|
expect(document.querySelector('.el-autocomplete__suggestions').style.display).to.be.equal('none');
|
||||||
done();
|
done();
|
||||||
}, 500);
|
}, 500);
|
||||||
}, 500);
|
}, 500);
|
||||||
|
@ -66,6 +67,7 @@ describe('Autocomplete', () => {
|
||||||
template: `
|
template: `
|
||||||
<el-autocomplete
|
<el-autocomplete
|
||||||
v-model="state"
|
v-model="state"
|
||||||
|
ref="autocomplete"
|
||||||
:fetch-suggestions="querySearch"
|
:fetch-suggestions="querySearch"
|
||||||
placeholder="请输入内容autocomplete2"
|
placeholder="请输入内容autocomplete2"
|
||||||
@select="handleSelect"
|
@select="handleSelect"
|
||||||
|
@ -110,7 +112,7 @@ describe('Autocomplete', () => {
|
||||||
inputElm.focus();
|
inputElm.focus();
|
||||||
|
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
let suggestionsList = elm.querySelector('.el-autocomplete__suggestions');
|
let suggestionsList = vm.$refs.autocomplete.$refs.suggestions.$el;
|
||||||
suggestionsList.children[1].click();
|
suggestionsList.children[1].click();
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
expect(inputElm.value).to.be.equal('Hot honey 首尔炸鸡(仙霞路)');
|
expect(inputElm.value).to.be.equal('Hot honey 首尔炸鸡(仙霞路)');
|
||||||
|
@ -191,7 +193,7 @@ describe('Autocomplete', () => {
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
vm.$refs.autocomplete.highlight(8);
|
vm.$refs.autocomplete.highlight(8);
|
||||||
vm.$nextTick(_ => {
|
vm.$nextTick(_ => {
|
||||||
let suggestionsList = elm.querySelector('.el-autocomplete__suggestions');
|
let suggestionsList = vm.$refs.autocomplete.$refs.suggestions.$el;
|
||||||
let highlightedItem = suggestionsList.children[8];
|
let highlightedItem = suggestionsList.children[8];
|
||||||
expect(highlightedItem.className).to.be.equal('highlighted');
|
expect(highlightedItem.className).to.be.equal('highlighted');
|
||||||
expect(suggestionsList.scrollTop === highlightedItem.scrollHeight).to.be.true;
|
expect(suggestionsList.scrollTop === highlightedItem.scrollHeight).to.be.true;
|
||||||
|
@ -261,7 +263,7 @@ describe('Autocomplete', () => {
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
vm.$refs.autocomplete.highlight(15);
|
vm.$refs.autocomplete.highlight(15);
|
||||||
vm.$nextTick(_ => {
|
vm.$nextTick(_ => {
|
||||||
let suggestionsList = elm.querySelector('.el-autocomplete__suggestions');
|
let suggestionsList = vm.$refs.autocomplete.$refs.suggestions.$el;
|
||||||
let highlightedItem = suggestionsList.children[11];
|
let highlightedItem = suggestionsList.children[11];
|
||||||
expect(highlightedItem.className).to.be.equal('highlighted');
|
expect(highlightedItem.className).to.be.equal('highlighted');
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue