mirror of https://github.com/ElemeFE/element
fix autocomplete
parent
de8c3b8b46
commit
1e7809106b
|
@ -3,9 +3,7 @@
|
||||||
.el-autocomplete {
|
.el-autocomplete {
|
||||||
width: 180px;
|
width: 180px;
|
||||||
}
|
}
|
||||||
.el-autocomplete__suggestions.my-autocomplete-suggestions {
|
.my-suggestions-item {
|
||||||
width: 300px;
|
|
||||||
|
|
||||||
& .remark {
|
& .remark {
|
||||||
float: right;
|
float: right;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
|
@ -14,8 +12,28 @@
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script>
|
<script>
|
||||||
var $q = require('q');
|
var Vue = require('vue');
|
||||||
|
Vue.component('my-item', {
|
||||||
|
functional: true,
|
||||||
|
render: function (h, ctx) {
|
||||||
|
var item = ctx.props.item;
|
||||||
|
return h('li', {
|
||||||
|
attrs: { class: 'my-suggestions-item' }
|
||||||
|
}, [
|
||||||
|
h('span', { attrs: { class: 'label' } }, ['选项' + ctx.props.index]),
|
||||||
|
h('span', { attrs: { class: 'remark' } }, [item.display])
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
item: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
index: {
|
||||||
|
type: Number
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -24,10 +42,7 @@
|
||||||
state2: '',
|
state2: '',
|
||||||
state3: '',
|
state3: '',
|
||||||
state4: '',
|
state4: '',
|
||||||
myPartial: {
|
timeout: null
|
||||||
name: 'my-autocomplete-suggestions',
|
|
||||||
template: '<span class="label">选项{{$index}}</span><span class="remark">{{item.display}}</span>'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -52,32 +67,28 @@
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
querySearch(query, simulateQuery) {
|
querySearch(queryString, cb) {
|
||||||
var states = this.states;
|
var states = this.states;
|
||||||
var results = query ? states.filter(this.createStateFilter(query)) : states,
|
var results = queryString ? states.filter(this.createStateFilter(queryString)) : states;
|
||||||
deferred;
|
|
||||||
|
|
||||||
if (simulateQuery) {
|
cb(results);
|
||||||
if (!query) { return []; }
|
|
||||||
|
|
||||||
deferred = $q.defer();
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
deferred.resolve(results);
|
|
||||||
}, Math.random() * 3000, false);
|
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
} else {
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
createStateFilter(query) {
|
querySearchAsync(queryString, cb) {
|
||||||
|
var states = this.states;
|
||||||
|
var results = queryString ? states.filter(this.createStateFilter(queryString)) : states;
|
||||||
|
|
||||||
|
clearTimeout(this.timeout);
|
||||||
|
this.timeout = setTimeout(() => {
|
||||||
|
cb(results);
|
||||||
|
}, 3000 * Math.random());
|
||||||
|
},
|
||||||
|
createStateFilter(queryString) {
|
||||||
return (state) => {
|
return (state) => {
|
||||||
return (state.value.indexOf(query.toLowerCase()) === 0);
|
return (state.value.indexOf(queryString.toLowerCase()) === 0);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ready() {
|
mounted() {
|
||||||
this.states = this.loadAll();
|
this.states = this.loadAll();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -87,24 +98,25 @@
|
||||||
|
|
||||||
<div class="demo-box">
|
<div class="demo-box">
|
||||||
<el-autocomplete
|
<el-autocomplete
|
||||||
:value.sync = "state1"
|
v-model="state1"
|
||||||
:suggestions = "querySearch(state1)"
|
:fetch-suggestions="querySearch"
|
||||||
placeholder = "请输入内容"
|
placeholder="请输入内容"
|
||||||
></el-autocomplete>
|
></el-autocomplete>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<template>
|
<template>
|
||||||
<el-autocomplete
|
<el-autocomplete
|
||||||
:value.sync = "state1"
|
v-model="state1"
|
||||||
:suggestions = "querySearch(state1)"
|
:fetch-suggestions="querySearch"
|
||||||
placeholder = "请输入内容"
|
placeholder="请输入内容"
|
||||||
></el-autocomplete>
|
></el-autocomplete>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
states: [],
|
||||||
state1: ''
|
state1: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -130,62 +142,71 @@
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
querySearch(query, simulateQuery) {
|
querySearch(queryString, callback) {
|
||||||
var states = this.states;
|
var states = this.states;
|
||||||
var results = query ? states.filter(this.createStateFilter(query)) : states,
|
var results = queryString ? states.filter(this.createStateFilter(queryString)) : states;
|
||||||
deferred;
|
|
||||||
|
|
||||||
if (simulateQuery) {
|
callback(results);
|
||||||
if (!query) { return []; }
|
|
||||||
|
|
||||||
deferred = $q.defer();
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
deferred.resolve(results);
|
|
||||||
}, Math.random() * 3000, false);
|
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
} else {
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
createStateFilter(query) {
|
createStateFilter(queryString) {
|
||||||
return (state) => {
|
return (state) => {
|
||||||
return (state.value.indexOf(query.toLowerCase()) === 0);
|
return (state.value.indexOf(queryString.toLowerCase()) === 0);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ready() {
|
mounted() {
|
||||||
this.states = this.loadAll();
|
this.states = this.loadAll();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
```
|
```
|
||||||
|
|
||||||
## 通过键盘控制下拉的显示
|
## 自定义模板
|
||||||
|
|
||||||
<div class="demo-box">
|
<div class="demo-box">
|
||||||
<el-autocomplete
|
<el-autocomplete
|
||||||
:value.sync = "state2"
|
v-model="state2"
|
||||||
:suggestions = "querySearch(state2)"
|
:fetch-suggestions="querySearch"
|
||||||
:show-on-up-down = "true"
|
custom-item="my-item"
|
||||||
placeholder = "请输入内容"
|
placeholder="请输入内容"
|
||||||
></el-autocomplete>
|
></el-autocomplete>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<template>
|
<el-autocomplete
|
||||||
<el-autocomplete
|
v-model="state2"
|
||||||
:value.sync = "state2"
|
:fetch-suggestions="querySearch"
|
||||||
:suggestions = "querySearch(state2)"
|
custom-item="my-item"
|
||||||
:show-on-up-down = "true"
|
placeholder="请输入内容"
|
||||||
placeholder = "请输入内容"
|
></el-autocomplete>
|
||||||
></el-autocomplete>
|
|
||||||
</template>
|
|
||||||
<script>
|
<script>
|
||||||
|
var Vue = require('vue');
|
||||||
|
Vue.component('my-item', {
|
||||||
|
functional: true,
|
||||||
|
render: function (h, ctx) {
|
||||||
|
var item = ctx.props.item;
|
||||||
|
return h('li', {
|
||||||
|
attrs: { class: 'my-suggestions-item' }
|
||||||
|
}, [
|
||||||
|
h('span', { attrs: { class: 'label' } }, ['选项' + ctx.props.index]),
|
||||||
|
h('span', { attrs: { class: 'remark' } }, [item.display])
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
item: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
index: {
|
||||||
|
type: Number
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
states: [],
|
||||||
state2: ''
|
state2: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -211,116 +232,19 @@
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
querySearch(query, simulateQuery) {
|
querySearch(queryString, cb) {
|
||||||
var states = this.states;
|
var states = this.states;
|
||||||
var results = query ? states.filter(this.createStateFilter(query)) : states,
|
var results = queryString ? states.filter(this.createStateFilter(queryString)) : states;
|
||||||
deferred;
|
|
||||||
|
|
||||||
if (simulateQuery) {
|
cb(results);
|
||||||
if (!query) { return []; }
|
|
||||||
|
|
||||||
deferred = $q.defer();
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
deferred.resolve(results);
|
|
||||||
}, Math.random() * 3000, false);
|
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
} else {
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
createStateFilter(query) {
|
createStateFilter(queryString) {
|
||||||
return (state) => {
|
return (state) => {
|
||||||
return (state.value.indexOf(query.toLowerCase()) === 0);
|
return (state.value.indexOf(queryString.toLowerCase()) === 0);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ready() {
|
mounted() {
|
||||||
this.states = this.loadAll();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
|
|
||||||
## 自定义模板
|
|
||||||
|
|
||||||
<div class="demo-box">
|
|
||||||
<el-autocomplete
|
|
||||||
:value.sync = "state3"
|
|
||||||
:suggestions = "querySearch(state3)"
|
|
||||||
:partial = "myPartial"
|
|
||||||
placeholder = "请输入内容"
|
|
||||||
></el-autocomplete>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
```html
|
|
||||||
<el-autocomplete
|
|
||||||
:value.sync = "state3"
|
|
||||||
:suggestions = "querySearch(state3)"
|
|
||||||
:partial = "myPartial"
|
|
||||||
placeholder = "请输入内容"
|
|
||||||
></el-autocomplete>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
state3: '',
|
|
||||||
myPartial: {
|
|
||||||
name: 'my-autocomplete-suggestions',
|
|
||||||
template: '<span class="label">选项{{$index}}</span><span class="remark">{{item.display}}</span>'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
loadAll() {
|
|
||||||
var allStates = 'Alabama, Alaska, Arizona, Arkansas, California, Colorado, Connecticut, Delaware,\
|
|
||||||
Florida, Georgia, Hawaii, Idaho, Illinois, Indiana, Iowa, Kansas, Kentucky, Louisiana,\
|
|
||||||
Maine, Maryland, Massachusetts, Michigan, Minnesota, Mississippi, Missouri, Montana,\
|
|
||||||
Nebraska, Nevada, New Hampshire, New Jersey, New Mexico, New York, North Carolina,\
|
|
||||||
North Dakota, Ohio, Oklahoma, Oregon, Pennsylvania, Rhode Island, South Carolina,\
|
|
||||||
South Dakota, Tennessee, Texas, Utah, Vermont, Virginia, Washington, West Virginia,\
|
|
||||||
Wisconsin, Wyoming';
|
|
||||||
var result = [];
|
|
||||||
|
|
||||||
allStates.split(/, +/g).forEach((state) => {
|
|
||||||
if (state) {
|
|
||||||
result.push({
|
|
||||||
value: state.toLowerCase(),
|
|
||||||
display: state
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
querySearch(query, simulateQuery) {
|
|
||||||
var states = this.states;
|
|
||||||
var results = query ? states.filter(this.createStateFilter(query)) : states,
|
|
||||||
deferred;
|
|
||||||
|
|
||||||
if (simulateQuery) {
|
|
||||||
if (!query) { return []; }
|
|
||||||
|
|
||||||
deferred = $q.defer();
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
deferred.resolve(results);
|
|
||||||
}, Math.random() * 3000, false);
|
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
} else {
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
createStateFilter(query) {
|
|
||||||
return (state) => {
|
|
||||||
return (state.value.indexOf(query.toLowerCase()) === 0);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ready() {
|
|
||||||
this.states = this.loadAll();
|
this.states = this.loadAll();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -331,27 +255,26 @@
|
||||||
|
|
||||||
<div class="demo-box">
|
<div class="demo-box">
|
||||||
<el-autocomplete
|
<el-autocomplete
|
||||||
:value.sync = "state4"
|
v-model="state3"
|
||||||
:suggestions = "querySearch(state4, true)"
|
|
||||||
:search-from-server = "true"
|
|
||||||
placeholder = "请输入内容"
|
placeholder = "请输入内容"
|
||||||
|
:fetch-Suggestions="querySearchAsync"
|
||||||
></el-autocomplete>
|
></el-autocomplete>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<el-autocomplete
|
<template>
|
||||||
:value.sync = "state4"
|
<el-autocomplete
|
||||||
:suggestions = "querySearch(state4, true)"
|
v-model="state3"
|
||||||
:search-from-server = "true"
|
|
||||||
placeholder = "请输入内容"
|
placeholder = "请输入内容"
|
||||||
></el-autocomplete>
|
:fetch-Suggestions="querySearchAsync"
|
||||||
|
></el-autocomplete>
|
||||||
|
</template>
|
||||||
<script>
|
<script>
|
||||||
var $q = require('q');
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
state4: ''
|
state3: '',
|
||||||
|
states: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -376,24 +299,15 @@
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
querySearch(query, simulateQuery) {
|
querySearchAsync(query, callback) {
|
||||||
var states = this.states;
|
var states = this.states;
|
||||||
var results = query ? states.filter(this.createStateFilter(query)) : states,
|
var results = query ? states.filter(this.createStateFilter(query)) : states;
|
||||||
deferred;
|
|
||||||
|
|
||||||
if (simulateQuery) {
|
|
||||||
if (!query) { return []; }
|
if (!query) { return []; }
|
||||||
|
|
||||||
deferred = $q.defer();
|
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
deferred.resolve(results);
|
callback(results);
|
||||||
}, Math.random() * 3000, false);
|
}, 3000 * Math.random());
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
} else {
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
createStateFilter(query) {
|
createStateFilter(query) {
|
||||||
return (state) => {
|
return (state) => {
|
||||||
|
@ -413,7 +327,6 @@
|
||||||
|------------- |---------------- |---------------- |---------------------- |-------- |
|
|------------- |---------------- |---------------- |---------------------- |-------- |
|
||||||
| placeholder | 输入框占位文本 | string | | |
|
| placeholder | 输入框占位文本 | string | | |
|
||||||
| disabled | 禁用 | boolean | true, false | false |
|
| disabled | 禁用 | boolean | true, false | false |
|
||||||
| suggestions | 建议列表 | array,object | | |
|
| value | 必填值输入绑定值 | string | | |
|
||||||
| value | 输入绑定值 | string | | |
|
|
||||||
| showOnUpDown | 是否通过键盘上下键控制建议列表 | boolean | | |
|
| showOnUpDown | 是否通过键盘上下键控制建议列表 | boolean | | |
|
||||||
| partial | 建议列表的自定义模板 | object | | |
|
| fetch-suggestions | 返回输入建议的方法,组件内部通过调用该方法来获得输入建议的数据,在该方法中,仅当你的输入建议数据 resolve 时再通过调用 callback(data:[]) 来返回它 | Function(queryString, callback) | | |
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel-helper-vue-jsx-merge-props": "^1.0.1",
|
"babel-helper-vue-jsx-merge-props": "^1.0.1",
|
||||||
"babel-plugin-syntax-jsx": "^6.8.0",
|
"babel-plugin-syntax-jsx": "^6.8.0",
|
||||||
"babel-plugin-transform-vue-jsx": "^1.1.1",
|
"babel-plugin-transform-vue-jsx": "^3.1.0",
|
||||||
"file-save": "^0.2.0",
|
"file-save": "^0.2.0",
|
||||||
"gh-pages": "^0.11.0",
|
"gh-pages": "^0.11.0",
|
||||||
"highlight.js": "^9.3.0",
|
"highlight.js": "^9.3.0",
|
||||||
|
@ -44,7 +44,7 @@
|
||||||
"purecss": "^0.6.0",
|
"purecss": "^0.6.0",
|
||||||
"q": "^1.4.1",
|
"q": "^1.4.1",
|
||||||
"uppercamelcase": "^1.1.0",
|
"uppercamelcase": "^1.1.0",
|
||||||
"vue": "^2.0.0-beta.5",
|
"vue": "^2.0.0-beta.8",
|
||||||
"vue-loader": "^9.2.3",
|
"vue-loader": "^9.2.3",
|
||||||
"vue-markdown-loader": "^0.4.0",
|
"vue-markdown-loader": "^0.4.0",
|
||||||
"vue-popup": "^0.2.1",
|
"vue-popup": "^0.2.1",
|
||||||
|
|
|
@ -12,5 +12,6 @@
|
||||||
"author": "haiping.zeng<haiping.zeng@ele.me>",
|
"author": "haiping.zeng<haiping.zeng@ele.me>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"vue-clickoutside": "^0.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,36 +1,54 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="el-autocomplete">
|
<div class="el-autocomplete" v-clickoutside="handleBlur">
|
||||||
<el-input
|
<el-input
|
||||||
:value="value"
|
:value="value"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
:placeholder="placeholder"
|
:placeholder="placeholder"
|
||||||
:name = 'name'
|
:name='name'
|
||||||
@onchange="handleChange"
|
@onchange="handleChange"
|
||||||
@onfocus="handleFocus()"
|
@onfocus="handleFocus"
|
||||||
@onblur="handleBlur()"
|
@keydown.up.native="highlight(highlightedIndex - 1)"
|
||||||
@keydown.up="highlight(highlightedIndex - 1)"
|
@keydown.down.native="highlight(highlightedIndex + 1)"
|
||||||
@keydown.down="highlight(highlightedIndex + 1)"
|
@keydown.enter.native="select(highlightedIndex)"
|
||||||
@keydown.enter="select(highlightedIndex)"
|
|
||||||
></el-input>
|
></el-input>
|
||||||
|
<transition name="md-fade-bottom">
|
||||||
<ul
|
<ul
|
||||||
v-show="showSuggestions && !loading && suggestions.length > 0"
|
v-show="suggestionVisible && !loading && suggestions.length > 0"
|
||||||
class="el-autocomplete__suggestions"
|
class="el-autocomplete__suggestions"
|
||||||
:class="[partial ? partial.name : '']"
|
ref="suggestions"
|
||||||
transition="md-fade-bottom"
|
|
||||||
v-el:suggestions
|
|
||||||
>
|
>
|
||||||
<li :class="{'highlighted': highlightedIndex === $index}" @click="select($index)" v-for="item in suggestions">{{item.display}}</li>
|
<li
|
||||||
|
v-if="!customItem"
|
||||||
|
:class="{'highlighted': highlightedIndex === index}"
|
||||||
|
@click="select(index)"
|
||||||
|
v-for="(item, index) in suggestions">
|
||||||
|
{{item.display}}
|
||||||
|
</li>
|
||||||
|
<component
|
||||||
|
v-else
|
||||||
|
:is="customItem"
|
||||||
|
@click.native="select(index)"
|
||||||
|
v-for="(item, index) in suggestions"
|
||||||
|
:item="item"
|
||||||
|
:index="index">
|
||||||
|
</component>
|
||||||
</ul>
|
</ul>
|
||||||
|
</transition>
|
||||||
|
<transition name="md-fade-bottom">
|
||||||
<div
|
<div
|
||||||
v-show="showSuggestions && loading"
|
v-show="suggestionVisible && loading"
|
||||||
class="el-autocomplete__suggestions is-loading"
|
class="el-autocomplete__suggestions is-loading"
|
||||||
>
|
>
|
||||||
<i class="el-icon-loading"></i>
|
<i class="el-icon-loading"></i>
|
||||||
</div>
|
</div>
|
||||||
|
</transition>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import ElInput from 'packages/input/index.js';
|
import ElInput from 'packages/input/index.js';
|
||||||
|
import Vue from 'vue';
|
||||||
|
import VueClickoutside from 'main/utils/clickoutside';
|
||||||
|
Vue.use(VueClickoutside);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ElAutocomplete',
|
name: 'ElAutocomplete',
|
||||||
|
@ -42,61 +60,58 @@
|
||||||
placeholder: String,
|
placeholder: String,
|
||||||
disabled: Boolean,
|
disabled: Boolean,
|
||||||
name: String,
|
name: String,
|
||||||
suggestions: [Array, Object],
|
|
||||||
value: String,
|
value: String,
|
||||||
showOnUpDown: Boolean,
|
fetchSuggestions: Function,
|
||||||
partial: Object
|
triggerOnfocus: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
customItem: String
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
showSuggestions: false,
|
suggestions: [],
|
||||||
|
suggestionVisible: false,
|
||||||
inputFocusing: false,
|
inputFocusing: false,
|
||||||
loading: false,
|
loading: false,
|
||||||
highlightedIndex: -1
|
highlightedIndex: -1
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
created() {
|
|
||||||
if (this.partial) {
|
|
||||||
this.$options.template = this.$options.template.replace(/(item\sin\ssuggestions">)(?:.|\s)*?(<)/, '$1' + this.partial.template + '$2');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
'suggestions'(val) {
|
|
||||||
if (val && val.then) {
|
|
||||||
this.loading = true;
|
|
||||||
this.suggestions.then((res) => {
|
|
||||||
this.loading = false;
|
|
||||||
this.suggestions = res;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
handleChange(value) {
|
handleChange(value) {
|
||||||
this.value = value;
|
this.$emit('input', value);
|
||||||
this.showSuggestions = true;
|
this.showSuggestions(value);
|
||||||
},
|
},
|
||||||
handleFocus() {
|
handleFocus() {
|
||||||
if (!this.showOnUpDown) {
|
if (this.triggerOnfocus) {
|
||||||
this.showSuggestions = true;
|
this.showSuggestions(this.value);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleBlur() {
|
handleBlur() {
|
||||||
this.showSuggestions = false;
|
this.suggestionVisible = false;
|
||||||
},
|
},
|
||||||
select(index) {
|
select(index) {
|
||||||
|
debugger;
|
||||||
if (this.suggestions && this.suggestions[index]) {
|
if (this.suggestions && this.suggestions[index]) {
|
||||||
this.value = this.suggestions[index].value;
|
this.$emit('input', this.suggestions[index].value);
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.showSuggestions = false;
|
this.suggestionVisible = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
showSuggestions(value) {
|
||||||
|
this.suggestionVisible = true;
|
||||||
|
this.loading = true;
|
||||||
|
this.fetchSuggestions(value, (suggestions) => {
|
||||||
|
this.loading = false;
|
||||||
|
this.suggestions = suggestions;
|
||||||
|
});
|
||||||
|
},
|
||||||
getSuggestionElement(index) {
|
getSuggestionElement(index) {
|
||||||
if (!this.suggestions || !this.suggestions[index]) {
|
if (!this.suggestions || !this.suggestions[index]) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return this.$els.suggestions.children[index];
|
return this.$refs.suggestions.children[index];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
highlight(index) {
|
highlight(index) {
|
||||||
|
@ -107,7 +122,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
var elSelect = this.getSuggestionElement(index);
|
var elSelect = this.getSuggestionElement(index);
|
||||||
var elSuggestions = this.$els.suggestions;
|
var elSuggestions = this.$refs.suggestions;
|
||||||
var scrollTop = elSuggestions.scrollTop;
|
var scrollTop = elSuggestions.scrollTop;
|
||||||
var offsetTop = elSelect.offsetTop;
|
var offsetTop = elSelect.offsetTop;
|
||||||
|
|
||||||
|
@ -121,7 +136,7 @@
|
||||||
this.highlightedIndex = index;
|
this.highlightedIndex = index;
|
||||||
|
|
||||||
if (this.showOnUpDown) {
|
if (this.showOnUpDown) {
|
||||||
this.showSuggestions = true;
|
this.suggestionVisible = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,28 +28,28 @@
|
||||||
transition: all .3s cubic-bezier(.55,0,.1,1);
|
transition: all .3s cubic-bezier(.55,0,.1,1);
|
||||||
}
|
}
|
||||||
.md-fade-center-enter,
|
.md-fade-center-enter,
|
||||||
.md-fade-center-leave {
|
.md-fade-center-leave,
|
||||||
opacity: 0;
|
|
||||||
transform: scaleY(0);
|
|
||||||
}
|
|
||||||
.md-fade-center-leave-active {
|
.md-fade-center-leave-active {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: scaleY(0);
|
transform: scaleY(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.md-fade-bottom-transition {
|
.md-fade-bottom-enter-active,
|
||||||
|
.md-fade-bottom-leave-active {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: scaleY(1);
|
transform: scaleY(1);
|
||||||
transition: var(--md-fade-transition);
|
transition: var(--md-fade-transition);
|
||||||
transform-origin: center top;
|
transform-origin: center top;
|
||||||
}
|
}
|
||||||
.md-fade-bottom-enter,
|
.md-fade-bottom-enter,
|
||||||
.md-fade-bottom-leave {
|
.md-fade-bottom-leave,
|
||||||
|
.md-fade-bottom-leave-active {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: scaleY(0);
|
transform: scaleY(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.md-fade-top-transition {
|
.md-fade-top-enter-active,
|
||||||
|
.md-fade-top-leave-active {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: scaleY(1);
|
transform: scaleY(1);
|
||||||
transition: var(--md-fade-transition);
|
transition: var(--md-fade-transition);
|
||||||
|
@ -57,40 +57,47 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.md-fade-top-enter,
|
.md-fade-top-enter,
|
||||||
.md-fade-top-leave {
|
.md-fade-top-leave,
|
||||||
|
.md-fade-top-leave-active {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: scaleY(0);
|
transform: scaleY(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.md-fade-left-transition {
|
.md-fade-left-enter-active,
|
||||||
|
.md-fade-left-leave-active {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: scaleX(1);
|
transform: scaleX(1);
|
||||||
transition: var(--md-fade-transition);
|
transition: var(--md-fade-transition);
|
||||||
transform-origin: right center;
|
transform-origin: right center;
|
||||||
}
|
}
|
||||||
.md-fade-left-enter,
|
.md-fade-left-enter,
|
||||||
.md-fade-left-leave {
|
.md-fade-left-leave,
|
||||||
|
.md-fade-left-leave-active {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: scaleX(0);
|
transform: scaleX(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.md-fade-right-transition {
|
.md-fade-right-enter-active,
|
||||||
|
.md-fade-right-leave-active {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: scaleX(1);
|
transform: scaleX(1);
|
||||||
transition: var(--md-fade-transition);
|
transition: var(--md-fade-transition);
|
||||||
transform-origin: left center;
|
transform-origin: left center;
|
||||||
}
|
}
|
||||||
.md-fade-right-enter,
|
.md-fade-right-enter,
|
||||||
.md-fade-right-leave {
|
.md-fade-right-leave,
|
||||||
|
.md-fade-right-leave-active {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: scaleX(0);
|
transform: scaleX(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.fade-enter-active, .fade-leave-active {
|
.fade-enter-active,
|
||||||
|
.fade-leave-active {
|
||||||
transition: opacity .3s cubic-bezier(.645,.045,.355,1);
|
transition: opacity .3s cubic-bezier(.645,.045,.355,1);
|
||||||
}
|
}
|
||||||
.fade-enter,
|
.fade-enter,
|
||||||
.fade-leave {
|
.fade-leave,
|
||||||
|
.fade-leave-active {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue