mirror of
https://github.com/element-plus/element-plus.git
synced 2026-03-13 07:51:17 +08:00
feat(components): [autocomplete] add loading slot (#15206)
* feat(components): [autocomplete] add `loading` slot * chore: Update autocomplete.md * docs(components): [autocomplete] modify loading slot description * Update docs/en-US/component/autocomplete.md Co-authored-by: btea <2356281422@qq.com> * Update docs/en-US/component/autocomplete.md --------- Co-authored-by: zhixiaotong <zhixiaotong.me@qq.com> Co-authored-by: btea <2356281422@qq.com>
This commit is contained in:
@@ -43,6 +43,16 @@ autocomplete/remote-search
|
||||
|
||||
:::
|
||||
|
||||
## Custom Loading ^(2.5.0)
|
||||
|
||||
Override loading content.
|
||||
|
||||
:::demo
|
||||
|
||||
autocomplete/custom-loading
|
||||
|
||||
:::
|
||||
|
||||
## API
|
||||
|
||||
### Attributes
|
||||
@@ -77,13 +87,14 @@ autocomplete/remote-search
|
||||
|
||||
### Slots
|
||||
|
||||
| Name | Description | Type |
|
||||
| ------- | ------------------------------------ | ---------------------------------------- |
|
||||
| default | custom content for input suggestions | ^[object]`{ item: Record<string, any> }` |
|
||||
| prefix | content as Input prefix | - |
|
||||
| suffix | content as Input suffix | - |
|
||||
| prepend | content to prepend before Input | - |
|
||||
| append | content to append after Input | - |
|
||||
| Name | Description | Type |
|
||||
| ---------------- | ------------------------------------ | ---------------------------------------- |
|
||||
| default | custom content for input suggestions | ^[object]`{ item: Record<string, any> }` |
|
||||
| prefix | content as Input prefix | - |
|
||||
| suffix | content as Input suffix | - |
|
||||
| prepend | content to prepend before Input | - |
|
||||
| append | content to append after Input | - |
|
||||
| loading ^(2.5.0) | override loading content | - |
|
||||
|
||||
### Exposes
|
||||
|
||||
|
||||
165
docs/examples/autocomplete/custom-loading.vue
Normal file
165
docs/examples/autocomplete/custom-loading.vue
Normal file
@@ -0,0 +1,165 @@
|
||||
<template>
|
||||
<el-row class="demo-autocomplete">
|
||||
<el-col :span="12">
|
||||
<div class="sub-title my-2 text-sm text-gray-600">loading icon1</div>
|
||||
<el-autocomplete
|
||||
v-model="state"
|
||||
:fetch-suggestions="querySearchAsync"
|
||||
placeholder="Please input"
|
||||
@select="handleSelect"
|
||||
>
|
||||
<template #loading>
|
||||
<svg class="circular" viewBox="0 0 50 50">
|
||||
<circle class="path" cx="25" cy="25" r="20" fill="none" />
|
||||
</svg>
|
||||
</template>
|
||||
</el-autocomplete>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="sub-title my-2 text-sm text-gray-600">loading icon2</div>
|
||||
<el-autocomplete
|
||||
v-model="state"
|
||||
:fetch-suggestions="querySearchAsync"
|
||||
placeholder="Please input"
|
||||
@select="handleSelect"
|
||||
>
|
||||
<template #loading>
|
||||
<el-icon class="is-loading">
|
||||
<svg class="circular" viewBox="0 0 20 20">
|
||||
<g
|
||||
class="path2 loading-path"
|
||||
stroke-width="0"
|
||||
style="animation: none; stroke: none"
|
||||
>
|
||||
<circle r="3.375" class="dot1" rx="0" ry="0" />
|
||||
<circle r="3.375" class="dot2" rx="0" ry="0" />
|
||||
<circle r="3.375" class="dot4" rx="0" ry="0" />
|
||||
<circle r="3.375" class="dot3" rx="0" ry="0" />
|
||||
</g>
|
||||
</svg>
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-autocomplete>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from 'vue'
|
||||
|
||||
const state = ref('')
|
||||
|
||||
interface LinkItem {
|
||||
value: string
|
||||
link: string
|
||||
}
|
||||
|
||||
const links = ref<LinkItem[]>([])
|
||||
|
||||
const loadAll = () => {
|
||||
return [
|
||||
{ value: 'vue', link: 'https://github.com/vuejs/vue' },
|
||||
{ value: 'element', link: 'https://github.com/ElemeFE/element' },
|
||||
{ value: 'cooking', link: 'https://github.com/ElemeFE/cooking' },
|
||||
{ value: 'mint-ui', link: 'https://github.com/ElemeFE/mint-ui' },
|
||||
{ value: 'vuex', link: 'https://github.com/vuejs/vuex' },
|
||||
{ value: 'vue-router', link: 'https://github.com/vuejs/vue-router' },
|
||||
{ value: 'babel', link: 'https://github.com/babel/babel' },
|
||||
]
|
||||
}
|
||||
|
||||
let timeout: ReturnType<typeof setTimeout>
|
||||
const querySearchAsync = (queryString: string, cb: (arg: any) => void) => {
|
||||
const results = queryString
|
||||
? links.value.filter(createFilter(queryString))
|
||||
: links.value
|
||||
|
||||
clearTimeout(timeout)
|
||||
timeout = setTimeout(() => {
|
||||
cb(results)
|
||||
}, 5000 * Math.random())
|
||||
}
|
||||
const createFilter = (queryString: string) => {
|
||||
return (restaurant: LinkItem) => {
|
||||
return (
|
||||
restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const handleSelect = (item: Record<string, any>) => {
|
||||
console.log(item)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
links.value = loadAll()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.circular {
|
||||
display: inline;
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
animation: loading-rotate 2s linear infinite;
|
||||
}
|
||||
.path {
|
||||
animation: loading-dash 1.5s ease-in-out infinite;
|
||||
stroke-dasharray: 90, 150;
|
||||
stroke-dashoffset: 0;
|
||||
stroke-width: 2;
|
||||
stroke: var(--el-color-primary);
|
||||
stroke-linecap: round;
|
||||
}
|
||||
.loading-path .dot1 {
|
||||
transform: translate(3.75px, 3.75px);
|
||||
fill: var(--el-color-primary);
|
||||
animation: custom-spin-move 1s infinite linear alternate;
|
||||
opacity: 0.3;
|
||||
}
|
||||
.loading-path .dot2 {
|
||||
transform: translate(calc(100% - 3.75px), 3.75px);
|
||||
fill: var(--el-color-primary);
|
||||
animation: custom-spin-move 1s infinite linear alternate;
|
||||
opacity: 0.3;
|
||||
animation-delay: 0.4s;
|
||||
}
|
||||
.loading-path .dot3 {
|
||||
transform: translate(3.75px, calc(100% - 3.75px));
|
||||
fill: var(--el-color-primary);
|
||||
animation: custom-spin-move 1s infinite linear alternate;
|
||||
opacity: 0.3;
|
||||
animation-delay: 1.2s;
|
||||
}
|
||||
.loading-path .dot4 {
|
||||
transform: translate(calc(100% - 3.75px), calc(100% - 3.75px));
|
||||
fill: var(--el-color-primary);
|
||||
animation: custom-spin-move 1s infinite linear alternate;
|
||||
opacity: 0.3;
|
||||
animation-delay: 0.8s;
|
||||
}
|
||||
@keyframes loading-rotate {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@keyframes loading-dash {
|
||||
0% {
|
||||
stroke-dasharray: 1, 200;
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
50% {
|
||||
stroke-dasharray: 90, 150;
|
||||
stroke-dashoffset: -40px;
|
||||
}
|
||||
100% {
|
||||
stroke-dasharray: 90, 150;
|
||||
stroke-dashoffset: -120px;
|
||||
}
|
||||
}
|
||||
@keyframes custom-spin-move {
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -77,9 +77,11 @@
|
||||
role="listbox"
|
||||
>
|
||||
<li v-if="suggestionLoading">
|
||||
<el-icon :class="ns.is('loading')">
|
||||
<Loading />
|
||||
</el-icon>
|
||||
<slot name="loading">
|
||||
<el-icon :class="ns.is('loading')">
|
||||
<Loading />
|
||||
</el-icon>
|
||||
</slot>
|
||||
</li>
|
||||
<template v-else>
|
||||
<li
|
||||
|
||||
Reference in New Issue
Block a user