Browse Source

fix: [TreeSelect] Fix single selection, filterTreeNode and virtualized TreeSelect, the user needs to click twice to select the option, close #1487

YyumeiZhang 2 years ago
parent
commit
53e5599319

+ 10 - 1
cypress/integration/treeSelect.spec.js

@@ -84,4 +84,13 @@ describe('treeSelect', () => {
         cy.get('.semi-tree-select').eq(2).click();
         cy.get('@consoleLog').should('be.calledWith', 'blur');
     });
-});
+
+    it('filterTreeNode & virtualize', () => {
+        // 该例子为测试当 filterTreeNode 和 virtualize 功能同时使用时, 点击选中是否符合预期
+        cy.visit('http://127.0.0.1:6006/iframe.html?id=treeselect--search-position-in-trigger-and-virtualize');
+        cy.get('.semi-tree-select').eq(0).click();
+        cy.get('.semi-tree-option').eq(0).click();
+        cy.get('.semi-tree-select-selection-TriggerSearchItem').eq(0).should('contain.text', '亚洲');
+    });
+});
+

+ 3 - 2
packages/semi-ui/select/virtualRow.tsx

@@ -4,10 +4,11 @@ export interface VirtualRowProps{
     data: Record<string, any>;
     style?: React.CSSProperties
 }
+
 const VirtualRow = ({ index, data, style }: VirtualRowProps) => {
-    const { visibleOptions } = data;
+    const { visibleOptions, renderOption } = data;
     const option = visibleOptions[index];
-    return data.renderOption(option, index, style);
+    return renderOption(option, index, style);
 };
 
 export default VirtualRow;

+ 24 - 3
packages/semi-ui/treeSelect/_story/treeSelect.stories.jsx

@@ -1,5 +1,5 @@
-import React, { useState, useMemo } from 'react';
-import { Icon, Button, Form, Popover, Tag, Typography, CheckboxGroup } from '../../index';
+import React, { useState, useMemo, useRef } from 'react';
+import { Icon, Input, Button, Form, Popover, Tag, Typography, CheckboxGroup } from '../../index';
 import TreeSelect from '../index';
 import { flattenDeep } from 'lodash';
 import CustomTrigger from './CustomTrigger';
@@ -2085,4 +2085,25 @@ class ValueTypeIsNumber extends React.Component {
   }
 }
 
-export const valueIsNumber = () => <ValueTypeIsNumber />
+export const valueIsNumber = () => <ValueTypeIsNumber />
+
+export const searchPositionInTriggerAndVirtualize = () => {
+  return (
+      <>
+          <TreeSelect  
+              searchPosition="trigger"
+              style={{ width: 300 }}
+              dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
+              treeData={treeData2}
+              filterTreeNode
+              placeholder="单选"
+              virtualize={{
+                  itemSize: 28,
+                  // dropDown height 300 minus search box height minus padding 8 * 2
+                  // or if you set dropdown height, it will fill 100% of rest space
+                  height: 236                
+              }}
+          />
+      </>
+  );
+};

+ 11 - 6
packages/semi-ui/treeSelect/index.tsx

@@ -50,6 +50,7 @@ import { OptionProps, TreeProps, TreeState, FlattenNode, TreeNodeData, TreeNodeP
 import { IconChevronDown, IconClear, IconSearch } from '@douyinfe/semi-icons';
 import CheckboxGroup from '../checkbox/checkboxGroup';
 import Popover, { PopoverProps } from '../popover/index';
+import VirtualRow from '../select/virtualRow';
 
 export type ExpandAction = false | 'click' | 'doubleClick';
 
@@ -1308,9 +1309,10 @@ class TreeSelect extends BaseComponent<TreeSelectProps, TreeSelectState> {
         return <TreeNode {...treeNodeProps} {...data} key={key} data={data} style={style} />;
     };
 
-    itemKey = (index: number, data: TreeNodeData) => {
+    itemKey = (index: number, data: Record<string, any>) => {
+        const { visibleOptions } = data;
         // Find the item at the specified index.
-        const item = data[index];
+        const item = visibleOptions[index];
         // Return a value that uniquely identifies this item.
         return item.key;
     };
@@ -1340,7 +1342,10 @@ class TreeSelect extends BaseComponent<TreeSelectProps, TreeSelectState> {
             );
         }
 
-        const option = ({ index, style, data }: OptionProps) => this.renderTreeNode(data[index], index, style);
+        const data = {
+            visibleOptions: flattenNodes,
+            renderOption: this.renderTreeNode
+        };
 
         return (
             <AutoSizer defaultHeight={virtualize.height} defaultWidth={virtualize.width}>
@@ -1351,12 +1356,12 @@ class TreeSelect extends BaseComponent<TreeSelectProps, TreeSelectState> {
                         height={height}
                         width={width}
                         // @ts-ignore avoid strict check of itemKey
-                        itemKey={this.itemKey as ListItemKeySelector<TreeNodeData>}
-                        itemData={flattenNodes as any}
+                        itemKey={this.itemKey}
+                        itemData={data}
                         className={`${prefixTree}-virtual-list`}
                         style={{ direction }}
                     >
-                        {option}
+                        {VirtualRow}
                     </VirtualList>
                 )}
             </AutoSizer>