Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: CascaderView support fieldNames #6242

Merged
merged 2 commits into from
Jul 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 31 additions & 18 deletions src/components/cascader-view/cascader-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,22 @@ import { useConfig } from '../config-provider'
import { optionSkeleton } from './option-skeleton'
import Skeleton from '../skeleton'
import { useUpdateEffect } from 'ahooks'
import { useFieldNames } from '../../hooks'
import type { FieldNamesType } from '../../hooks'

const classPrefix = `adm-cascader-view`

export type CascaderValue = string

type BaseOptionType = {
[key: string]: any
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

一般会做成泛型让用户填,默认就还是原样的。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

新的 commit 加了默认的 ,看看行不行

}
export type CascaderOption = {
label: string
value: string
disabled?: boolean
children?: CascaderOption[]
}
} & BaseOptionType

export type CascaderValueExtend = {
items: (CascaderOption | null)[]
Expand All @@ -36,47 +41,49 @@ export type CascaderViewProps = {
onTabsChange?: (index: number) => void
activeIcon?: ReactNode
loading?: boolean
fieldNames?: FieldNamesType
} & NativeProps<'--height'>

const defaultProps = {
defaultValue: [],
}

export const CascaderView: FC<CascaderViewProps> = p => {
const { locale } = useConfig()
const props = mergeProps(defaultProps, p)
const placeholder = props.placeholder || locale.Cascader.placeholder

const { locale } = useConfig()
const generateValueExtend = useCascaderValueExtend(props.options)
const [labelName, valueName, disabledName, childrenName] = useFieldNames(
props.fieldNames
)

const [value, setValue] = usePropsValue({
...props,
onChange: val => {
props.onChange?.(val, generateValueExtend(val))
},
})
const [tabActiveIndex, setTabActiveIndex] = useState<number>(0)
useUpdateEffect(() => {
props.onTabsChange?.(tabActiveIndex)
}, [tabActiveIndex])

const generateValueExtend = useCascaderValueExtend(props.options)
const [tabActiveIndex, setTabActiveIndex] = useState(0)

const levels = useMemo(() => {
const ret: {
selected: CascaderOption | undefined
options: CascaderOption[]
}[] = []

let currentOptions = props.options
let reachedEnd = false
for (const v of value) {
const target = currentOptions.find(option => option.value === v)
const target = currentOptions.find(option => option[valueName] === v)
ret.push({
selected: target,
options: currentOptions,
})
if (!target || !target.children) {
if (!target || !target[childrenName]) {
reachedEnd = true
break
}
currentOptions = target.children
currentOptions = target[childrenName]
}
if (!reachedEnd) {
ret.push({
Expand All @@ -87,6 +94,9 @@ export const CascaderView: FC<CascaderViewProps> = p => {
return ret
}, [value, props.options])

useUpdateEffect(() => {
props.onTabsChange?.(tabActiveIndex)
}, [tabActiveIndex])
useEffect(() => {
setTabActiveIndex(levels.length - 1)
}, [value])
Expand All @@ -104,9 +114,12 @@ export const CascaderView: FC<CascaderViewProps> = p => {
}
setValue(next)
}

const whetherLoading = <T extends unknown[]>(options: T) =>
props.loading || options === optionSkeleton

const placeholder = props.placeholder || locale.Cascader.placeholder

return withNativeProps(
props,
<div className={classPrefix}>
Expand All @@ -127,7 +140,7 @@ export const CascaderView: FC<CascaderViewProps> = p => {
title={
<div className={`${classPrefix}-header-title`}>
{selected
? selected.label
? selected[labelName]
: typeof placeholder === 'function'
? placeholder(index)
: placeholder}
Expand Down Expand Up @@ -164,17 +177,17 @@ export const CascaderView: FC<CascaderViewProps> = p => {
activeIcon={props.activeIcon}
>
{level.options.map(option => {
const active = value[index] === option.value
const active = value[index] === option[valueName]
return (
<CheckList.Item
value={option.value}
key={option.value}
disabled={option.disabled}
value={option[valueName]}
key={option[valueName]}
disabled={option[disabledName]}
className={classNames(`${classPrefix}-item`, {
[`${classPrefix}-item-active`]: active,
})}
>
{option.label}
{option[labelName]}
</CheckList.Item>
)
})}
Expand Down
1 change: 1 addition & 0 deletions src/components/cascader-view/index.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ CascaderView is the content area of [Cascader](/components/cascader).
| --- | --- | --- | --- |
| activeIcon | The icon displayed when selected | `ReactNode` | - |
| defaultValue | Default selected options | `CascaderValue[]` | `[]` |
| fieldNames | Custom field name for label and value and disabled and children | `{ label: string, value: string, disabled: string, children: string }` | `{ label: 'label', value: 'value',disabled:'disabled', children: 'children' }` |
| onChange | Triggered when the selected options are changed | `(value: CascaderValue[], extend: CascaderValueExtend) => void` | - |
| onTabsChange | Callback when switching panel | `(index: number) => void` | - |
| options | Data of the cascade options | `CascaderOption[]` | - |
Expand Down
1 change: 1 addition & 0 deletions src/components/cascader-view/index.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ CascaderView 是 [Cascader](/zh/components/cascader) 的内容区域。
| --- | --- | --- | --- |
| activeIcon | 选中图标 | `ReactNode` | - |
| defaultValue | 默认选中项 | `CascaderValue[]` | `[]` |
| fieldNames | 自定义 options 中 label value disabled children 的字段 | `{ label: string, value: string, disabled: string, children: string }` | `{ label: 'label', value: 'value',disabled:'disabled', children: 'children' }` |
| onChange | 选项改变时触发 | `(value: CascaderValue[], extend: CascaderValueExtend) => void` | - |
| onTabsChange | 切换面板的回调 | `(index: number) => void` | - |
| options | 配置每一列的选项 | `CascaderOption[]` | - |
Expand Down
Loading
Loading