feat: autocomplete support option slot

v2.3
tangjinzhou 2021-09-22 22:11:48 +08:00
parent e35730354d
commit cb3c002e17
9 changed files with 79 additions and 70 deletions

View File

@ -1,10 +1,10 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders ./components/auto-complete/demo/basic.vue correctly 1`] = `
<div style="width: 200px;" class="ant-select ant-select-show-search ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search">
<div style="width: 200px;" class="ant-select ant-select-show-search ant-select-auto-complete ant-select-single ant-select-show-search">
<!---->
<!---->
<div class="ant-select-selector"><span class="ant-select-selection-search"><input id="rc_select_TEST_OR_SSR" type="search" autocomplete="off" class="ant-input ant-select-selection-search-input" role="combobox" aria-haspopup="listbox" aria-owns="rc_select_TEST_OR_SSR_list" aria-autocomplete="list" aria-controls="rc_select_TEST_OR_SSR_list" aria-activedescendant="rc_select_TEST_OR_SSR_list_0"></span>
<div class="ant-select-selector"><span class="ant-select-selection-search"><input id="rc_select_TEST_OR_SSR" autocomplete="off" class="ant-select-selection-search-input" role="combobox" aria-haspopup="listbox" aria-owns="rc_select_TEST_OR_SSR_list" aria-autocomplete="list" aria-controls="rc_select_TEST_OR_SSR_list" aria-activedescendant="rc_select_TEST_OR_SSR_list_0" type="search"></span>
<!----><span class="ant-select-selection-placeholder">input here</span>
</div>
<!---->
@ -39,10 +39,10 @@ exports[`renders ./components/auto-complete/demo/custom.vue correctly 1`] = `
`;
exports[`renders ./components/auto-complete/demo/non-case-sensitive.vue correctly 1`] = `
<div style="width: 200px;" class="ant-select ant-select-show-search ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search">
<div style="width: 200px;" class="ant-select ant-select-show-search ant-select-auto-complete ant-select-single ant-select-show-search">
<!---->
<!---->
<div class="ant-select-selector"><span class="ant-select-selection-search"><input id="rc_select_TEST_OR_SSR" type="search" autocomplete="off" class="ant-input ant-select-selection-search-input" role="combobox" aria-haspopup="listbox" aria-owns="rc_select_TEST_OR_SSR_list" aria-autocomplete="list" aria-controls="rc_select_TEST_OR_SSR_list" aria-activedescendant="rc_select_TEST_OR_SSR_list_0"></span>
<div class="ant-select-selector"><span class="ant-select-selection-search"><input id="rc_select_TEST_OR_SSR" autocomplete="off" class="ant-select-selection-search-input" role="combobox" aria-haspopup="listbox" aria-owns="rc_select_TEST_OR_SSR_list" aria-autocomplete="list" aria-controls="rc_select_TEST_OR_SSR_list" aria-activedescendant="rc_select_TEST_OR_SSR_list_0" type="search"></span>
<!----><span class="ant-select-selection-placeholder">input here</span>
</div>
<!---->
@ -51,10 +51,10 @@ exports[`renders ./components/auto-complete/demo/non-case-sensitive.vue correctl
`;
exports[`renders ./components/auto-complete/demo/options.vue correctly 1`] = `
<div style="width: 200px;" class="ant-select ant-select-show-search ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search">
<div style="width: 200px;" class="ant-select ant-select-show-search ant-select-auto-complete ant-select-single ant-select-show-search">
<!---->
<!---->
<div class="ant-select-selector"><span class="ant-select-selection-search"><input id="rc_select_TEST_OR_SSR" type="search" autocomplete="off" class="ant-input ant-select-selection-search-input" role="combobox" aria-haspopup="listbox" aria-owns="rc_select_TEST_OR_SSR_list" aria-autocomplete="list" aria-controls="rc_select_TEST_OR_SSR_list" aria-activedescendant="rc_select_TEST_OR_SSR_list_0"></span>
<div class="ant-select-selector"><span class="ant-select-selection-search"><input id="rc_select_TEST_OR_SSR" autocomplete="off" class="ant-select-selection-search-input" role="combobox" aria-haspopup="listbox" aria-owns="rc_select_TEST_OR_SSR_list" aria-autocomplete="list" aria-controls="rc_select_TEST_OR_SSR_list" aria-activedescendant="rc_select_TEST_OR_SSR_list_0" type="search"></span>
<!----><span class="ant-select-selection-placeholder">input here</span>
</div>
<!---->

View File

@ -26,28 +26,23 @@ Lookup-Patterns - Certain Category.
size="large"
style="width: 100%"
option-label-prop="value"
:options="dataSource"
>
<template #dataSource>
<a-select-opt-group v-for="group in dataSource" :key="group.title">
<template #label>
<span>
{{ group.title }}
<a
style="float: right"
href="https://www.google.com/search?q=antd"
target="_blank"
rel="noopener noreferrer"
>
more
</a>
</span>
</template>
<a-select-option v-for="opt in group.children" :key="opt.title" :value="opt.title">
{{ opt.title }}
<span class="certain-search-item-count">{{ opt.count }} people</span>
</a-select-option>
</a-select-opt-group>
<a-select-option key="all" disabled class="show-all">
<template #option="item">
<template v-if="item.options">
<span>
{{ item.value }}
<a
style="float: right"
href="https://www.google.com/search?q=antd"
target="_blank"
rel="noopener noreferrer"
>
more
</a>
</span>
</template>
<template v-else-if="item.value === 'all'">
<a
href="https://www.google.com/search?q=ant-design-vue"
target="_blank"
@ -55,7 +50,11 @@ Lookup-Patterns - Certain Category.
>
View all results
</a>
</a-select-option>
</template>
<template v-else>
{{ item.title }}
<span class="certain-search-item-count">{{ item.count }} people</span>
</template>
</template>
<a-input placeholder="input here">
<template #suffix><search-outlined class="certain-category-icon" /></template>
@ -69,40 +68,43 @@ import { SearchOutlined } from '@ant-design/icons-vue';
import { defineComponent, ref } from 'vue';
const dataSource = [
{
title: 'Libraries',
children: [
value: 'Libraries',
options: [
{
title: 'AntDesign',
value: 'AntDesign',
count: 10000,
},
{
title: 'AntDesign UI',
value: 'AntDesign UI',
count: 10600,
},
],
},
{
title: 'Solutions',
children: [
value: 'Solutions',
options: [
{
title: 'AntDesign UI FAQ',
value: 'AntDesign UI FAQ',
count: 60100,
},
{
title: 'AntDesign FAQ',
value: 'AntDesign FAQ',
count: 30010,
},
],
},
{
title: 'Articles',
children: [
value: 'Articles',
options: [
{
title: 'AntDesign design language',
value: 'AntDesign design language',
count: 100000,
},
],
},
{
value: 'all',
},
];
export default defineComponent({
components: {

View File

@ -8,11 +8,11 @@ title:
## zh-CN
也可以直接传递 #dataSource Option
3.0 以上版本可以传递 `v-slot:option` 来自定义 Option
## en-US
You could pass `#dataSource` as children of `AutoComplete`, instead of using `dataSource`.
For 3.0+, You could pass `v-slot:option` to custom option.
</docs>
<template>
@ -20,12 +20,12 @@ You could pass `#dataSource` as children of `AutoComplete`, instead of using `da
v-model:value="value"
style="width: 200px"
placeholder="input here"
:options="options"
@search="handleSearch"
>
<template #dataSource>
<a-select-option v-for="email in result" :key="email">
{{ email }}
</a-select-option>
<template #option="{ value: val }">
{{ val.split('@')[0] }} @
<span style="font-weight: bold">{{ val.split('@')[1] }}</span>
</template>
</a-auto-complete>
</template>
@ -36,20 +36,20 @@ import { defineComponent, ref } from 'vue';
export default defineComponent({
setup() {
const value = ref('');
const result = ref<string[]>([]);
const options = ref<{ value: string }[]>([]);
const handleSearch = (val: string) => {
let res: string[];
let res: { value: string }[];
if (!val || val.indexOf('@') >= 0) {
res = [];
} else {
res = ['gmail.com', '163.com', 'qq.com'].map(domain => `${val}@${domain}`);
res = ['gmail.com', '163.com', 'qq.com'].map(domain => ({ value: `${val}@${domain}` }));
}
result.value = res;
options.value = res;
};
return {
value,
result,
options,
handleSearch,
};
},

View File

@ -23,21 +23,20 @@ Lookup-Patterns - Uncertain Category.
size="large"
style="width: 100%"
option-label-prop="title"
:options="dataSource"
@select="onSelect"
@search="handleSearch"
>
<template #dataSource>
<a-select-option v-for="item in dataSource" :key="item.category" :title="item.category">
Found {{ item.query }} on
<a
:href="`https://s.taobao.com/search?q=${item.query}`"
target="_blank"
rel="noopener noreferrer"
>
{{ item.category }}
</a>
<span class="global-search-item-count">{{ item.count }} results</span>
</a-select-option>
<template #option="item">
Found {{ item.query }} on
<a
:href="`https://s.taobao.com/search?q=${item.query}`"
target="_blank"
rel="noopener noreferrer"
>
{{ item.category }}
</a>
<span class="global-search-item-count">{{ item.count }} results</span>
</template>
<a-input-search size="large" placeholder="input here" enter-button></a-input-search>
</a-auto-complete>
@ -49,6 +48,7 @@ import { defineComponent, ref } from 'vue';
interface Option {
query: string;
category: string;
value: string;
count: number;
}
export default defineComponent({
@ -67,9 +67,10 @@ export default defineComponent({
return new Array(getRandomInt(5))
.join('.')
.split('.')
.map((item, idx) => ({
.map((_item, idx) => ({
query,
category: `${query}${idx}`,
value: `${query}${idx}`,
count: getRandomInt(200, 100),
}));
};

View File

@ -25,6 +25,7 @@ When there is a need for autocomplete functionality.
| backfill | backfill selected item the input when using keyboard | boolean | false | |
| #default (for customize input element) | customize input element | HTMLInputElement / HTMLTextAreaElement | `<Input />` | |
| options | Data source for autocomplete | slot \| [DataSourceItemType](https://github.com/vueComponent/ant-design-vue/blob/724d53b907e577cf5880c1e6742d4c3f924f8f49/components/auto-complete/index.vue#L9)\[] | | |
| option | custom render option by slot | v-slot:option="{value, label, [disabled, key, title]}" | - | 3.0 |
| dropdownMenuStyle | additional style applied to dropdown menu | object | | 1.5.0 |
| defaultActiveFirstOption | Whether active first option by default | boolean | true | |
| disabled | Whether disabled select | boolean | false | |
@ -38,7 +39,7 @@ When there is a need for autocomplete functionality.
### events
| Events Name | Description | Arguments | Version |
| --- | --- | --- | --- |
| --- | --- | --- | --- | --- |
| change | Called when select an option or input value change, or value of input is changed | function(value) | |
| blur | Called when leaving the component. | function() | |
| focus | Called when entering the component | function() | |

View File

@ -1,7 +1,6 @@
import type { App, Plugin, VNode, ExtractPropTypes } from 'vue';
import { defineComponent, inject, provide } from 'vue';
import Select, { selectProps } from '../select';
import Input from '../input';
import PropTypes from '../_util/vue-types';
import { defaultConfigProvider } from '../config-provider';
import { getComponent, getOptionProps, isValidElement, getSlot } from '../_util/props-util';
@ -44,6 +43,7 @@ const AutoComplete = defineComponent({
defaultActiveFirstOption: PropTypes.looseBool.def(true),
},
emits: ['change', 'select', 'focus', 'blur'],
slots: ['option'],
Option,
OptGroup,
setup(props, { slots }) {
@ -70,7 +70,7 @@ const AutoComplete = defineComponent({
},
getInputElement() {
const children = getSlot(this);
const element = children.length ? children[0] : <Input lazy={false} />;
const element = children.length ? children[0] : undefined;
return element;
},
@ -144,7 +144,11 @@ const AutoComplete = defineComponent({
class: cls,
ref: this.saveSelect,
};
return <Select {...selectProps}>{optionChildren}</Select>;
return (
<Select {...selectProps} v-slots={{ option: this.$slots.option }}>
{optionChildren}
</Select>
);
},
});

View File

@ -32,6 +32,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/qtJm4yt45/AutoComplete.svg
| backfill | 使用键盘选择选项的时候把选中项回填到输入框中 | boolean | false | |
| #default (自定义输入框) | 自定义输入框 | HTMLInputElement / HTMLTextAreaElement | `<Input />` | |
| options | 自动完成的数据源 | slot \| [DataSourceItemType](https://github.com/vueComponent/ant-design-vue/blob/724d53b907e577cf5880c1e6742d4c3f924f8f49/components/auto-complete/index.vue#L9)\[] | | |
| option | 通过 option 插槽,自定义节点 | v-slot:option="{value, label, [disabled, key, title]}" | - | 3.0 |
| dropdownMenuStyle | dropdown 菜单自定义样式 | object | | 1.5.0 |
| defaultActiveFirstOption | 是否默认高亮第一个选项。 | boolean | true | |
| disabled | 是否禁用 | boolean | false | |

View File

@ -63,10 +63,10 @@ exports[`renders ./components/input/demo/group.vue correctly 1`] = `
</div><span class="ant-select-arrow" style="user-select: none;" unselectable="on" aria-hidden="true"><span role="img" aria-label="down" class="anticon anticon-down ant-select-suffix"><svg focusable="false" class="" data-icon="down" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"></path></svg></span></span>
<!---->
</div>
<div style="width: 200px;" class="ant-select ant-select-show-search ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search">
<div style="width: 200px;" class="ant-select ant-select-show-search ant-select-auto-complete ant-select-single ant-select-show-search">
<!---->
<!---->
<div class="ant-select-selector"><span class="ant-select-selection-search"><input id="rc_select_TEST_OR_SSR" type="search" autocomplete="off" class="ant-input ant-select-selection-search-input" role="combobox" aria-haspopup="listbox" aria-owns="rc_select_TEST_OR_SSR_list" aria-autocomplete="list" aria-controls="rc_select_TEST_OR_SSR_list" aria-activedescendant="rc_select_TEST_OR_SSR_list_0"></span>
<div class="ant-select-selector"><span class="ant-select-selection-search"><input id="rc_select_TEST_OR_SSR" autocomplete="off" class="ant-select-selection-search-input" role="combobox" aria-haspopup="listbox" aria-owns="rc_select_TEST_OR_SSR_list" aria-autocomplete="list" aria-controls="rc_select_TEST_OR_SSR_list" aria-activedescendant="rc_select_TEST_OR_SSR_list_0" type="search"></span>
<!----><span class="ant-select-selection-placeholder">Email</span>
</div>
<!---->

View File

@ -1,5 +1,5 @@
// debugger tsx
import Demo from '../../components/form/demo/customized-form-controls.vue';
import Demo from '../../components/auto-complete/demo/index.vue';
export default {
render() {