Skip to content
This repository has been archived by the owner on May 20, 2022. It is now read-only.

Commit

Permalink
feat(select-web): vitual scroll by debound
Browse files Browse the repository at this point in the history
  • Loading branch information
engalar committed Sep 11, 2021
1 parent 89e2c8e commit a8d96d5
Show file tree
Hide file tree
Showing 22 changed files with 1,890 additions and 43 deletions.
97 changes: 70 additions & 27 deletions packages/pluggableWidgets/select-web/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions packages/pluggableWidgets/select-web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@
"@types/react-dom": "~17.0.1"
},
"dependencies": {
"antd": "^4.16.12",
"ahooks": "^2.10.9",
"antd": "^4.16.13",
"@mendix-cn/piw-utils-internal": "^1.0.0",
"@mendix-cn/pluggable-widget-utils": "^1.0.0",
"classnames": "^2.2.6"
}
}
}
43 changes: 40 additions & 3 deletions packages/pluggableWidgets/select-web/src/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,14 @@ import { SelectContainerProps } from "../typings/SelectProps";
import SelectComponent, { SelectOption } from "./components/SelectComponent";

import "./ui/Select.css";
import { useDebounceFn, useMount, usePrevious } from "ahooks";

export default function Select(props: SelectContainerProps) {
const [dropdownVisible, setDropdownVisible] = useState(false);
useMount(() => {
props.options.setLimit(10);
props.options.requestTotalCount(true);
});
const onChange = useCallback(
(value: string) => {
if (props.value.status === ValueStatus.Available) {
Expand All @@ -29,13 +35,28 @@ export default function Select(props: SelectContainerProps) {

const options = useMemo(() => {
if (props.options.status === ValueStatus.Available) {
return props.options.items?.map<SelectOption>(item => ({
const loadingOption: SelectOption = { value: "-", label: "加载中。。。" };

const page = props.options.items?.map<SelectOption>(item => ({
label: props.optionLabel.get(item).value!,
value: props.optionValue.get(item).value!
value: props.optionValue.get(item).value!.toString()
}));

const leftOptions = Array(props.options.offset).fill(loadingOption);

const rightOptions = Array(
props.options.totalCount! - props.options.items!.length - props.options.offset
).fill(loadingOption);

return leftOptions
.concat(page)
.concat(rightOptions)
.map((v, i) => ({ label: v.label, value: i.toString() }));
}
}, [props.options]);

const preOptions = usePrevious(options);

const [value, setValue] = useState<string>();

useEffect(() => {
Expand All @@ -44,5 +65,21 @@ export default function Select(props: SelectContainerProps) {
}
}, [props.value]);

return <SelectComponent isMulti={isMulti} value={value} options={options} onChange={onChange}></SelectComponent>;
const { run } = useDebounceFn(
(offset, _) => {
props.options.setOffset(Math.max(0, offset - 1));
},
{ wait: 300 }
);

return (
<SelectComponent
isMulti={isMulti}
value={value}
options={dropdownVisible ? (options ? options : preOptions) : options}
onPopupScroll={run}
onDropdownVisibleChange={setDropdownVisible}
onChange={onChange}
></SelectComponent>
);
}
1 change: 1 addition & 0 deletions packages/pluggableWidgets/select-web/src/Select.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
<description></description>
<attributeTypes>
<attributeType name="String" />
<attributeType name="Integer" />
</attributeTypes>
</property>
<property key="optionLabel" type="attribute" required="true" dataSource="options">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { createElement } from "react";

import "../ui/antd.css";
import { Select } from "antd";
import { useWhyDidYouUpdate } from "ahooks";

export interface SelectOption {
label: string;
Expand All @@ -13,24 +14,30 @@ export interface SelectComponentProps {
value?: string;
isMulti?: boolean;
onChange?: (value: string) => void;
onPopupScroll?: (offset: number, pageSize: number) => void;
loading?: boolean;
onDropdownVisibleChange?: (open: boolean) => void;
}

export default function SelectComponent(props: SelectComponentProps) {
return props.options ? (
useWhyDidYouUpdate("SelectComponent", { ...props });

return (
<Select
allowClear
loading={props.loading}
value={props.value}
listItemHeight={32}
onChange={props.onChange}
onDropdownVisibleChange={props.onDropdownVisibleChange}
onPopupScroll={e => {
if (props.onPopupScroll) {
props.onPopupScroll(Math.floor(e.currentTarget.scrollTop / 32), e.currentTarget.clientHeight / 32);
}
}}
mode={props.isMulti ? "multiple" : undefined}
style={{ width: "100%" }}
>
{props.options.map(item => (
<Select.Option key={item.value} value={item.value}>
{item.label}
</Select.Option>
))}
</Select>
) : (
<Select loading></Select>
options={props.options}
></Select>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/
import { CSSProperties } from "react";
import { ActionValue, EditableValue, ListValue, ListAttributeValue } from "mendix";
import { Big } from "big.js";

export interface SelectContainerProps {
name: string;
Expand All @@ -13,7 +14,7 @@ export interface SelectContainerProps {
tabIndex?: number;
options: ListValue;
value: EditableValue<string>;
optionValue: ListAttributeValue<string>;
optionValue: ListAttributeValue<string | Big>;
optionLabel: ListAttributeValue<string>;
onChange?: ActionValue;
isMultiConst: boolean;
Expand Down
Loading

0 comments on commit a8d96d5

Please sign in to comment.