feat: select add fieldNames

feat-css-var
tangjinzhou 2022-03-06 16:59:49 +08:00
parent 72e5afab9f
commit 741ec4c835
8 changed files with 125 additions and 21 deletions

View File

@ -1,17 +1,17 @@
import type { App, Plugin, ExtractPropTypes, PropType } from 'vue';
import type { App, Plugin, ExtractPropTypes, PropType, HTMLAttributes } from 'vue';
import { provide, defineComponent, ref, watch, computed, toRef } from 'vue';
import PropTypes, { withUndefined } from '../_util/vue-types';
import PropTypes from '../_util/vue-types';
import type { SpinProps } from '../spin';
import Spin from '../spin';
import type { PaginationConfig } from '../pagination';
import Pagination, { paginationConfig } from '../pagination';
import Pagination from '../pagination';
import { Row } from '../grid';
import Item from './Item';
import { flattenChildren } from '../_util/props-util';
import initDefaultProps from '../_util/props-util/initDefaultProps';
import type { Key } from '../_util/type';
import { tuple } from '../_util/type';
import ItemMeta from './ItemMeta';
import useConfigInject from '../_util/hooks/useConfigInject';
import useBreakpoint from '../_util/hooks/useBreakpoint';
@ -36,41 +36,41 @@ export interface ListGridType {
xxxl?: ColumnCount;
}
export const ListSize = tuple('small', 'default', 'large');
export type ListSize = 'small' | 'default' | 'large';
export type ListItemLayout = 'horizontal' | 'vertical';
export const listProps = {
export const listProps = () => ({
bordered: PropTypes.looseBool,
dataSource: PropTypes.array,
extra: PropTypes.any,
grid: { type: Object as PropType<ListGridType>, default: undefined },
itemLayout: PropTypes.oneOf(tuple('horizontal', 'vertical')),
loading: withUndefined(PropTypes.oneOfType([PropTypes.looseBool, PropTypes.object])),
itemLayout: String as PropType<ListItemLayout>,
loading: {
type: [Boolean, Object] as PropType<boolean | (SpinProps & HTMLAttributes)>,
default: undefined as boolean | (SpinProps & HTMLAttributes),
},
loadMore: PropTypes.any,
pagination: withUndefined(
PropTypes.oneOfType([
PropTypes.shape<PaginationConfig>(paginationConfig()).loose,
PropTypes.looseBool,
]),
),
prefixCls: PropTypes.string,
pagination: {
type: [Boolean, Object] as PropType<false | PaginationConfig>,
default: undefined as false | PaginationConfig,
},
prefixCls: String,
rowKey: [String, Number, Function] as PropType<Key | ((item: any) => Key)>,
renderItem: PropTypes.any,
size: PropTypes.oneOf(ListSize),
size: String as PropType<ListSize>,
split: PropTypes.looseBool,
header: PropTypes.any,
footer: PropTypes.any,
locale: {
type: Object as PropType<ListLocale>,
},
};
});
export interface ListLocale {
emptyText: any;
}
export type ListProps = Partial<ExtractPropTypes<typeof listProps>>;
export type ListProps = Partial<ExtractPropTypes<ReturnType<typeof listProps>>>;
import { ListContextKey } from './contextKey';
import type { RenderEmptyHandler } from '../config-provider/renderEmpty';
@ -78,7 +78,7 @@ import type { RenderEmptyHandler } from '../config-provider/renderEmpty';
const List = defineComponent({
name: 'AList',
Item,
props: initDefaultProps(listProps, {
props: initDefaultProps(listProps(), {
dataSource: [],
bordered: false,
split: true,

View File

@ -153,6 +153,17 @@ exports[`renders ./components/select/demo/custom-dropdown-menu.vue correctly 1`]
</div>
`;
exports[`renders ./components/select/demo/field-names.vue correctly 1`] = `
<div style="width: 120px;" class="ant-select ant-select-single ant-select-show-arrow">
<!---->
<!---->
<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" style="opacity: 0;" 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" readonly="" unselectable="on" type="search"></span><span class="ant-select-selection-item" title="Lucy">Lucy</span>
<!---->
</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>
`;
exports[`renders ./components/select/demo/hide-selected.vue correctly 1`] = `
<div style="width: 100%;" class="ant-select ant-select-multiple ant-select-show-search">
<!---->

View File

@ -0,0 +1,81 @@
<docs>
---
order: 0
title:
zh-CN: 自定义 labelvalueoptions 字段
en-US: Custom `label` `value` `options` field
---
## zh-CN
方便数据结构转换
仅支持 options 传递不支持 a-select-option 构造节点
## en-US
Easy data structure conversion.
Only options passing is supported, a-select-option construction node is not supported.
</docs>
<template>
<a-select
ref="select"
v-model:value="value"
style="width: 120px"
:options="options"
:field-names="{ label: 'name', value: 'id', options: 'children' }"
@focus="focus"
@change="handleChange"
></a-select>
</template>
<script lang="ts">
import type { SelectProps } from 'ant-design-vue';
import { defineComponent, ref } from 'vue';
export default defineComponent({
setup() {
const options = ref<SelectProps['options']>([
{
id: 'jack',
name: 'Jack',
children: [
{
id: 'small jack',
name: 'samll Jack',
},
],
},
{
id: 'lucy',
name: 'Lucy',
},
{
id: 'disabled',
name: 'Disabled',
disabled: true,
},
{
id: 'yiminghe',
name: 'Yiminghe',
},
]);
const focus = () => {
console.log('focus');
};
const handleChange = (value: string) => {
console.log(`selected ${value}`);
};
return {
focus,
handleChange,
value: ref('lucy'),
options,
};
},
});
</script>

View File

@ -17,6 +17,7 @@
<CustomDropdownMenu />
<OptionLabelProp />
<BigData />
<fieldNamesVue />
</demo-sort>
</template>
<script lang="ts">
@ -37,6 +38,7 @@ import CustomDropdownMenu from './custom-dropdown-menu.vue';
import OptionLabelProp from './option-label-prop.vue';
import BigData from './big-data.vue';
import Responsive from './responsive.vue';
import fieldNamesVue from './field-names.vue';
import CN from '../index.zh-CN.md';
import US from '../index.en-US.md';
import { defineComponent } from 'vue';
@ -44,6 +46,7 @@ export default defineComponent({
CN,
US,
components: {
fieldNamesVue,
Basic,
Size,
Tags,

View File

@ -35,6 +35,7 @@ Select component to select value from options.
| dropdownRender | Customize dropdown content | ({menuNode: VNode, props}) => VNode \| v-slot | - | |
| dropdownStyle | style of dropdown menu | object | - | |
| dropdownMenuStyle | additional style applied to dropdown menu | object | - | |
| fieldNames | Customize node label, value, options field name | object | { label: `label`, value: `value`, options: `options` } | 3.0 |
| filterOption | If true, filter options by input, if function, filter options against it. The function will receive two arguments, `inputValue` and `option`, if the function returns `true`, the option will be included in the filtered set; Otherwise, it will be excluded. | boolean or function(inputValue, option) | true | |
| firstActiveValue | Value of action option by default | string\|string\[] | - | |
| getPopupContainer | Parent Node which the selector should be rendered to. Default to `body`. When position issues happen, try to modify it into scrollable content and position it relative. | function(triggerNode) | () => document.body | |

View File

@ -27,7 +27,13 @@ export interface LabeledValue {
export type SelectValue = RawValue | RawValue[] | LabeledValue | LabeledValue[] | undefined;
export const selectProps = () => ({
...omit(vcSelectProps<SelectValue>(), ['inputIcon', 'mode', 'getInputElement', 'backfill']),
...omit(vcSelectProps<SelectValue>(), [
'inputIcon',
'mode',
'getInputElement',
'getRawInputElement',
'backfill',
]),
value: {
type: [Array, Object, String, Number] as PropType<SelectValue>,
},

View File

@ -36,6 +36,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/_0XzgOis7/Select.svg
| dropdownRender | 自定义下拉框内容 | ({menuNode: VNode, props}) => VNode \| v-slot | - | |
| dropdownStyle | 下拉菜单的 style 属性 | object | - | |
| dropdownMenuStyle | dropdown 菜单自定义样式 | object | - | |
| fieldNames | 自定义节点 label、value、options 的字段 | object | { label: `label`, value: `value`, options: `options` } | 3.0 |
| filterOption | 是否根据输入项进行筛选。当其为一个函数时,会接收 `inputValue` `option` 两个参数,当 `option` 符合筛选条件时,应返回 `true`,反之则返回 `false`。 | boolean or function(inputValue, option) | true | |
| firstActiveValue | 默认高亮的选项 | string\|string\[] | - | |
| getPopupContainer | 菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位。 | Function(triggerNode) | () => document.body | |

View File

@ -193,6 +193,7 @@
"prettier": "^2.2.0",
"pretty-quick": "^3.0.0",
"prismjs": "^1.23.0",
"qs": "^6.10.3",
"query-string": "^7.0.1",
"querystring": "^0.2.0",
"raw-loader": "^4.0.2",