Skip to content

Commit

Permalink
fix(SearchTree): 子节点全部选中,父节点没有自动勾选问题 (#558)
Browse files Browse the repository at this point in the history
* fix(Form): 修复ref获取不到表单方法

* fix(Form):使用useLayoutEffect替换useEffect绑定绑定ForwardedRef

* refactor:(Form) 修改Ref类型定义

* fix(Form): 修复无法重置(initialValue)表单问题

* fix(Form): 类型导出错误

* feat(search-select):增加多选功能

* fix(form):增加设置表单值方法

* feat(form):增加必传表单项标注 #534

* fix(search-select):增加Tag依赖

* fix(form):增加获取异常信息方法

* fix(form):修复afterSubmit回调失效问题

* fix(search-select):缺失依赖

* refactor(search-select):重命名类型名称

* style(search-select): 多选select样式

* style(search-select): 多选select下拉弹层样式

* fix(Table):data不支持对象内包含布尔类型 #517

* style(search-select):规范样式命名

* style(SearchSelect): 规范命名

* ifx(SearchSelect): 增加value受控支持,多选模式下为数组

* fix(SearchSelect): 修复defaultValue支持

* fix(Tree):修复autoExpandParent参数时效,无法展开父节点

* feat(SearchSelect): 增加参数控制tag可见数量,多余显示省略

* feat(SearchSelect): 增加参数控制tag可见数量,多余显示省略

* fix(SearchSelect): 防止对选择的循序排序

* fix(SearchSelect): 增加labelInValue,控制value的格式

* style(SearchSelec): 样式调整与组件库一直

* fix(SearchSelect):存在tag时不显示 placeholder

* docs(SearchSelect):labelInValue, value参数说明

* fix(Form): #544 使用转json方式深拷贝状态值导致,某些类型Object变为了字符串,例如Date

* fix(SearchSelect): 修复删除键没有触发更新回调问题

* SearchTree

* SearchTree

* 暂存

* feat(SearhTree): 增加带搜索的树形选择控件

* revert: 撤销package.json更改

* docs(SearchTree): 单词拼写错误

* feat(SearchTree): 增加搜索功能,隐藏不匹配节点

* docs(Searchtree): 文档修改

* fix(SerachTree):删除冗余代码

* fix(SearchTree): 文件名更变

* fix(SearchTree): 样式调整

* fix(SearchTree): 子节点全部选中父节点没有自动勾选问题

* docs(SearchTree): 增加Form中使用实例文档
  • Loading branch information
nullptr-z committed Feb 25, 2022
1 parent d931dfe commit 51d768e
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 16 deletions.
2 changes: 1 addition & 1 deletion packages/react-search-select/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ export default function SearchSelect(props: SearchSelectProps) {
key={index}
closable
onClose={() => handleItemsClick(index, item)}
color="#ccc"
color="#393E48"
>
{item.label}
</Tag>
Expand Down
124 changes: 120 additions & 4 deletions packages/react-search-tree/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import SearchTree from '@uiw/react-search-tree';
<!--rehype:bgWhite=true&codeSandbox=true&codePen=true-->
```jsx
import ReactDOM from 'react-dom';
import { TreeChecked, SearchTree, Card, Row, Col } from 'uiw';
import { SearchTree } from 'uiw';

const data = [
{
Expand Down Expand Up @@ -63,22 +63,138 @@ const Demo = () => (
allowClear={true}
onSearch={(searchValue)=>console.log('SearchTree-> SearchTreeOption',searchValue)}
onChange={(selectedAll, selectd, isChecked)=>console.log('SearchTree-> onChange',selectedAll, selectd, isChecked)}
value={[{ label: '东花市街道', value: '2-3-1' }]}
value={[{ label: '东花市街道', key: '2-3-1' }]}
options={data}
placeholder="请输入选择"
/>
)
ReactDOM.render(<Demo />, _mount_);
```

## Form中使用

<!--rehype:bgWhite=true&codeSandbox=true&codePen=true-->
```jsx
import ReactDOM from 'react-dom';
import { Form, Button, SearchTree, Card, Row, Col } from 'uiw';;

const Demo = () => {

const data = [
{
label: '上海市',
key: '1-0-0',
children:[
{ label: '黄浦区', key: '1-0-1' },
{ label: '卢湾区', key: '1-0-2' },
{
label: '徐汇区',
key: '1-0-3',
children:[
{ label: '半淞园路街道', key: '1-1-0' },
{ label: '南京东路街道', key: '1-2-0' },
{ label: '外滩街道', key: '1-3-0' },
]
},
]
},
{
label: '北京市',
key: '2-0-0',
children:[
{ label: '东城区', key: '2-1-0' },
{ label: '西城区', key: '2-2-0' },
{
label: '崇文区',
key: '2-3-0',
children:[
{ label: '东花市街道', key: '2-3-1' },
{ label: '体育馆路街道', key: '2-3-2' },
{ label: '前门街道', key: '2-3-3' },
]
},
]
},
{ label: '澳门', key: '3' },
];

return (
<div>
<Form
onSubmitError={(error) => {
if (error.filed) {
return { ...error.filed };
}
return null;
}}
onSubmit={({initial, current}) => {
const errorObj = {};
if (!current.selectField) {
errorObj.selectField = '默认需要选择内容,选择入内容';
}
if(Object.keys(errorObj).length > 0) {
const err = new Error();
err.filed = errorObj;
Notify.error({ title: '提交失败!', description: '请确认提交表单是否正确!' });
throw err;
}
Notify.success({
title: '提交成功!',
description: `表单提交成功,选择值为:${current.selectField},将自动填充初始化值!`,
});
}}
fields={{
searchTree: {
initialValue:[{ label: '东花市街道', key: '2-3-1' }],
children: (
<SearchTree
allowClear={true}
onSearch={(searchValue)=>console.log('SearchTree-> SearchTreeOption',searchValue)}
onChange={(selectedAll, selectd, isChecked)=>console.log('SearchTree-> onChange',selectedAll, selectd, isChecked)}
options={data}
placeholder="请输入选择"
/>
)
},
}}
>
{({ fields, state, canSubmit }) => {
return (
<div>
<Row>
<Col fixed>{fields.searchTree}</Col>
</Row>
<Row>
<Col fixed>
<Button disabled={!canSubmit()} type="primary" htmlType="submit">提交</Button>
</Col>
</Row>
<Row>
<Col>
<pre style={{ padding: 10, marginTop: 10 }}>
{console.log('state',state)}
{JSON.stringify(state.current, null, 2)}
</pre>
</Col>
</Row>
</div>
)
}}
</Form>
</div>
);
}
ReactDOM.render(<Demo />, _mount_);
```

## Props

| 参数 | 说明 | 类型 | 默认值 |
|--------- |-------- |--------- |-------- |
| allowClear | 支持清除 | Boolean | `false` |
| disabled | 禁用选择器 | Boolean | `false` |
| value | 指定当前选中的条目 | [{label:string, value:string}] | - |
| options | 下拉数据源 | [{label:string, value:string}] | - |
| value | 指定当前选中的条目 | [{label:string, key:string}] | - |
| options | 下拉数据源,可参考Tree下拉数据源 | [{label:string, key:string, children: [{label:string, key:string}] }] | - |
| placeholder | 选择框默认文字 | String | - |
| size | 选择框尺寸 | Enum{large, default, small } | `default` |
| onChange | 选中 option,或 input 的 value,调用此函数 | function(selectdAll, selectd, isChecked)=>void | - |
Expand Down
2 changes: 1 addition & 1 deletion packages/react-search-tree/src/SearchTagInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export interface DropContent<V> {

export interface SearchTagInputOption {
label: string;
value: string | number;
key: string | number;
}

export interface SearchTagInputProps<V> extends IProps, DropdownProps, DropContent<V> {
Expand Down
25 changes: 17 additions & 8 deletions packages/react-search-tree/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,36 @@ function TreeCheckeds<V extends SearchTagInputOption>(
useEffect(() => {
let selectOption: SelectOtpion = {};
const keys = props.values?.map((opt) => {
selectOption[opt.value] = opt.label;
return opt.value;
selectOption[opt.key] = opt.label;
return opt.key;
});
selectOptionSet(selectOption);
keysSet(keys || []);
}, [props.values]);

const onSelected = (_1: any, _2: any, isChecked: boolean, evn: TreeData) => {
const curSelectOption: SelectOtpion = getOptionsRecursion([evn], selectOption, isChecked);
const option = Object.entries(curSelectOption).map(([value, label]) => ({ value, label } as V));
props.onSelected?.(option, { value: evn.key, label: evn.label as string } as V, isChecked);
const option = Object.entries(curSelectOption).map(([key, label]) => ({ key, label } as V));
props.onSelected?.(option, { key: evn.key, label: evn.label as string } as V, isChecked);
};

const getOptionsRecursion = (childrens: TreeData[], selectOption: SelectOtpion, isAdd: boolean) => {
const addOrDel = (key: string | number, label: string, isAdd: boolean) => {
if (isAdd) {
selectOption[key] = label;
} else {
delete selectOption[key!];
}
};

childrens.forEach((child: TreeData) => {
if (!!child.children?.length) {
selectOption = getOptionsRecursion(child.children, selectOption, isAdd);
} else if (isAdd) {
selectOption[child.key!] = child.label?.toString()!;
} else {
delete selectOption[child.key!];
}
addOrDel(child.key!, child.label?.toString()!, isAdd);
if (child.parent) {
const selectCount = child.parent.children.filter((child: TreeData) => !selectOption[child.key!]).length;
addOrDel(child.parent.key, child.parent.label, selectCount === 0);
}
});
return selectOption;
Expand Down
4 changes: 2 additions & 2 deletions website/src/routes/components/search-tree/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React, { useState } from 'react';
import { TreeChecked, SearchTree, Row, Col, Card, Icon } from 'uiw';
import { Form, Button, TreeChecked, SearchTree, Row, Col, Card, Icon } from 'uiw';
import Markdown from '../../../components/Markdown';

export default () => (
<Markdown
path="https://github.com/uiwjs/uiw/tree/master/packages/react-search-tree/README.md"
dependencies={{ TreeChecked, SearchTree, Row, Col, Card, Icon, useState }}
dependencies={{ Form, Button, TreeChecked, SearchTree, Row, Col, Card, Icon, useState }}
renderPage={async () => {
const md = await import('uiw/node_modules/@uiw/react-search-tree/README.md');
return md.default || md;
Expand Down

0 comments on commit 51d768e

Please sign in to comment.