Skip to content

Commit

Permalink
feat(comp:tree-select): add searchPlaceholder prop (#1617)
Browse files Browse the repository at this point in the history
  • Loading branch information
danranVm committed Jul 26, 2023
1 parent 53c9131 commit 3a2687e
Show file tree
Hide file tree
Showing 9 changed files with 260 additions and 2 deletions.
1 change: 1 addition & 0 deletions packages/components/cascader/docs/Api.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
| `searchable` | 是否可搜索 | `boolean \| 'overlay'` | `false` | - | 当为 `true` 时搜索功能集成在选择器上,当为 `overlay` 时,搜索功能集成在悬浮层上 |
| `searchFn` | 根据搜索的文本进行筛选 | `boolean \| SelectSearchFn` | `true` | - |`true` 时使用默认的搜索规则, 如果使用远程搜索,应该设置为 `false` |
| `separator` | 设置分割符 | `string` | `/` | - | - |
| `searchPlaceholder` | 下拉菜单搜索框的默认文本 | `string` | - | - | - |
| `size` | 设置选择器大小 | `'sm' \| 'md' \| 'lg'` | `md` || - |
| `status` | 手动指定校验状态 | `valid \| invalid \| validating` | - | - | - |
| `strategy` | 设置级联策略 | `'all' \| 'parent' \| 'child' \| 'off'` | `'all'` | - | 具体用法参见 [级联策略](#components-cascader-demo-Strategy) |
Expand Down
3 changes: 2 additions & 1 deletion packages/components/cascader/src/Cascader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ export default defineComponent({
props.searchable && callEmit(props.onSearch, '')
}
const renderContent = () => {
const { searchable, overlayRender } = props
const { searchable, overlayRender, searchPlaceholder } = props
const searchValue = inputValue.value
const prefixCls = mergedPrefixCls.value
const panelSlots = { empty: slots.empty, optionLabel: slots.optionLabel }
Expand All @@ -182,6 +182,7 @@ export default defineComponent({
size="sm"
suffix="search"
value={searchValue}
placeholder={searchPlaceholder}
onClear={handleSearchClear}
onInput={handleSearchInput}
/>
Expand Down
1 change: 1 addition & 0 deletions packages/components/cascader/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ export const cascaderProps = {
strategy: { type: String as PropType<CascaderStrategy>, default: 'all' },
suffix: { type: String, default: undefined },
virtual: { type: Boolean, default: false },
searchPlaceholder: { type: String, default: undefined },

// events
'onUpdate:value': [Function, Array] as PropType<MaybeArray<(value: any) => void>>,
Expand Down
14 changes: 14 additions & 0 deletions packages/components/table/demo/ScrollLoad.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
title:
zh: 滚动加载
en: Scroll load
order: 22
---

## zh

滚动加载表格

## en

scroll load table
225 changes: 225 additions & 0 deletions packages/components/table/demo/ScrollLoad.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
<template>
<IxInput v-model:value="searchParams.searchValue" style="width: 200px; margin-bottom: 8px"></IxInput>
<h4>Virtual scrolling + scroll loading, load data by listening to the scrolledBottom event.</h4>
<IxTable
ref="virtualTableRef"
virtual
:columns="columns"
:dataSource="dataSource"
:pagination="false"
:scroll="scroll"
:spin="spinning"
@scrolled-bottom="onLoadMore"
></IxTable>

<h4>Scroll loading, load data by listening to the scroll event.</h4>
<IxTable
ref="normalTableRef"
:columns="columns"
:dataSource="dataSource"
:pagination="false"
:scroll="scroll"
:spin="spinning"
@scroll="onNormalTableScroll"
></IxTable>
</template>

<script lang="ts" setup>
import { computed, ref, watch } from 'vue'
import { debounce, isEmpty } from 'lodash-es'
import { TableColumn, TableInstance } from '@idux/components/table'
interface Data {
key: number
name: string
age: number
address: string
}
interface ResponseData {
data: Data[]
total: number
}
interface SearchParams {
pageIndex: number
pageSize: number
searchValue: string
}
const columns: TableColumn<Data>[] = [
{
title: 'Name',
dataKey: 'name',
customCell: 'name',
},
{
title: 'Age',
dataKey: 'age',
},
{
title: 'Address',
dataKey: 'address',
},
]
const scroll = { height: 200 }
/** Enumeration of loading states. */
enum MORE_STATUS_ENUM {
more,
noMore,
loading,
}
const loadStatus = ref(MORE_STATUS_ENUM.more)
const spinning = computed(() => loadStatus.value === MORE_STATUS_ENUM.loading)
const currentPage = ref(0)
const dataSource = ref<Data[]>([])
const virtualTableRef = ref<TableInstance>()
/** Reset the data source for table initialization loading and search condition changes. */
const onResetLoad = () => {
currentPage.value = 0
loadData(currentPage.value, {
succFn: (data: Data[]) => {
dataSource.value = data ?? []
},
failedFn: () => {
dataSource.value = []
},
})
}
/**
* Load more data for scroll loading.
* When virtual scrolling is enabled, you can directly call this method by listening to the scrolledBottom event.
* When virtual scrolling is disabled, you need to listen to the scroll event of the table, judge whether it has reached the bottom, and then call this method to implement it. See onNormalTableScroll for details
*/
const onLoadMore = debounce(
() => {
if ([MORE_STATUS_ENUM.noMore, MORE_STATUS_ENUM.loading].includes(loadStatus.value)) {
return
}
currentPage.value++
loadData(currentPage.value, {
succFn: (data: Data[]) => {
if (isEmpty(data)) {
dataSource.value = []
} else {
dataSource.value.push(...data)
}
},
})
},
300,
{
leading: true,
},
)
const loadData = debounce(
async (
pageIndex: number,
options?: {
succFn?: (data: Data[]) => void
failedFn?: () => void
},
) => {
loadStatus.value = MORE_STATUS_ENUM.loading
const responseData = await loadDataFunc(pageIndex)
const { succFn, failedFn } = options ?? {}
if (isEmpty(responseData.data)) {
loadStatus.value = MORE_STATUS_ENUM.noMore
failedFn?.()
}
loadStatus.value = isMoreFunc(responseData) ? MORE_STATUS_ENUM.more : MORE_STATUS_ENUM.noMore
succFn?.(responseData.data)
},
300,
{
leading: true,
},
)
const searchParams = ref<SearchParams>({
pageIndex: 0,
pageSize: 20,
searchValue: '',
})
/** Method for loading data. */
const loadDataFunc = async (pageIndex: number) => {
searchParams.value.pageIndex = pageIndex
return await getData(searchParams.value)
}
/** Callback to determine if there is more data. */
const isMoreFunc = (responseData: ResponseData) => {
return responseData.total > searchParams.value.pageSize * (searchParams.value.pageIndex + 1)
}
const MockData: Data[] = new Array(1000).fill(0).map((item, index) => ({
name: `name${index}`,
address: `address${index}`,
age: index + 1,
key: index,
}))
const getData = (params: SearchParams) => {
return new Promise<ResponseData>(resolve => {
setTimeout(() => {
const { searchValue, pageIndex, pageSize } = params
const start = pageIndex * pageSize
const end = start + pageSize
const filterDate = MockData.filter(item =>
item.name.toLocaleLowerCase().includes(searchValue.toLocaleLowerCase()),
)
resolve({
data: filterDate.slice(start, end),
total: filterDate.length,
})
}, 1000)
})
}
watch(
() => searchParams.value.searchValue,
() => {
onResetLoad()
virtualTableRef.value?.scrollTo(0)
},
{ immediate: true },
)
/** Scroll loading without virtual scrolling --start-- */
const normalTableRef = ref<TableInstance>()
/** Listen to the scroll event of the table without virtual scrolling. */
const onNormalTableScroll = (e: Event) => {
const target = e.target
if (target instanceof HTMLDivElement) {
const scrollPosition = target.scrollTop + target.clientHeight
const totalHeight = target.scrollHeight
if (scrollPosition >= totalHeight) {
onLoadMore()
}
}
}
watch(
() => searchParams.value.searchValue,
() => {
onResetLoad()
normalTableRef.value?.scrollTo(0)
},
{ immediate: true },
)
/** Scroll loading without virtual scrolling --end-- */
</script>
2 changes: 2 additions & 0 deletions packages/components/tree-select/docs/Api.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,12 @@
| `searchable` | 是否开启搜索功能 | `boolean \| 'overlay'` | - | - | 当为 `true` 时搜索功能集成在选择器上,当为 `overlay` 时,搜索功能集成在悬浮层上 |
| `showLine` | 是否显示连接线 | `boolean` | `false` | - | 此属性为`tree`的全局配置,修改其即可生效 |
| `size` | 设置选择器大小 | `'sm' \| 'md' \| 'lg'` | `md` || - |
| `spin` | 是否显示加载中状态 | `boolean \| SpinPublicProps` | `undefined` | - | - |
| `status` | 手动指定校验状态 | `valid \| invalid \| validating` | - | - | - |
| `suffix` | 设置后缀图标 | `string \| #suffix` | `down` || - |
| `treeDisabled` | 树的禁用节点的函数 | 参考 [Tree](/components/tree/zh#API) | - | - | - |
| `virtual` | 是否开启虚拟滚动 | `boolean` | `false` | - | - |
| `searchPlaceholder` | 下拉菜单搜索框的默认文本 | `string` | - | - | - |
| `onChange` | 选择值发生变化时触发 | `(value: any, oldValue: any) => void` | - | - | - |
| `onCheck` | 选择框勾选状态发生变化时触发 | `(checked: boolean, node: TreeSelectNode) => void` | - | - | - |
| `onDragStart` | `dragstart` 触发时调用 | `(options: TreeDragDropOptions) => void` | - | - | - |
Expand Down
11 changes: 10 additions & 1 deletion packages/components/tree-select/src/TreeSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

import { computed, defineComponent, normalizeClass, provide, ref, watch } from 'vue'

import { isBoolean } from 'lodash-es'

import { useAccessorAndControl } from '@idux/cdk/forms'
import { type VirtualScrollToFn } from '@idux/cdk/scroll'
import { type VKey, useControlledProp, useState } from '@idux/cdk/utils'
Expand All @@ -15,6 +17,7 @@ import { ɵSelector, type ɵSelectorInstance } from '@idux/components/_private/s
import { useGlobalConfig } from '@idux/components/config'
import { useFormItemRegister, useFormSize, useFormStatus } from '@idux/components/form'
import { ɵUseOverlayState } from '@idux/components/select'
import { IxSpin } from '@idux/components/spin'
import { type TreeInstance } from '@idux/components/tree'
import { useGetKey } from '@idux/components/utils'

Expand Down Expand Up @@ -172,7 +175,13 @@ export default defineComponent({
/>
)

const renderContent = () => <Content onClick={handleOverlayClick} />
const renderLoading = (children: JSX.Element) => {
const { spin } = props
const spinProps = isBoolean(spin) ? { spinning: spin } : spin
return spinProps ? <IxSpin {...spinProps}>{children}</IxSpin> : children
}

const renderContent = () => renderLoading(<Content onClick={handleOverlayClick} />)

return () => {
const overlayProps = {
Expand Down
2 changes: 2 additions & 0 deletions packages/components/tree-select/src/content/Content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ export default defineComponent({
virtual,
searchable,
showLine,
searchPlaceholder,
onDragstart,
onDragend,
onDragenter,
Expand Down Expand Up @@ -247,6 +248,7 @@ export default defineComponent({
size="sm"
suffix="search"
value={value}
placeholder={searchPlaceholder}
onClear={handleClear}
onInput={handleInput}
/>
Expand Down
3 changes: 3 additions & 0 deletions packages/components/tree-select/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import type { ExtractInnerPropTypes, ExtractPublicPropTypes, MaybeArray, VKey }
import type { CascaderStrategy } from '@idux/components/cascader'
import type { EmptyProps } from '@idux/components/empty'
import type { FormSize } from '@idux/components/form'
import type { SpinProps } from '@idux/components/spin'
import type {
TreeCustomAdditional,
TreeDragDropOptions,
Expand Down Expand Up @@ -77,6 +78,7 @@ export const treeSelectProps = {
default: true,
},
size: { type: String as PropType<FormSize>, default: undefined },
spin: { type: [Boolean, Object] as PropType<boolean | SpinProps>, default: undefined },
showLine: { type: Boolean, default: undefined },
status: String as PropType<ValidateStatus>,
suffix: { type: String, default: undefined },
Expand All @@ -85,6 +87,7 @@ export const treeSelectProps = {
default: undefined,
},
virtual: { type: Boolean, default: false },
searchPlaceholder: { type: String, default: undefined },

// events
'onUpdate:value': [Function, Array] as PropType<MaybeArray<(value: any) => void>>,
Expand Down

0 comments on commit 3a2687e

Please sign in to comment.