Skip to content

Commit 7339ba1

Browse files
added control in autoComplete comp to filter options by input value
1 parent 1006e08 commit 7339ba1

File tree

2 files changed

+159
-125
lines changed

2 files changed

+159
-125
lines changed

client/packages/lowcoder/src/comps/comps/autoCompleteComp/autoCompleteComp.tsx

Lines changed: 158 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ReactNode, useEffect, useState } from "react";
1+
import { ReactNode, useEffect, useState, useCallback } from "react";
22
import { Input, Section, sectionNames } from "lowcoder-design";
33
import { BoolControl } from "comps/controls/boolControl";
44
import { styleControl } from "comps/controls/styleControl";
@@ -78,6 +78,7 @@ const childrenMap = {
7878
prefixIcon: IconControl,
7979
suffixIcon: IconControl,
8080
items: jsonControl(convertAutoCompleteData, autoCompleteDate),
81+
filterOptionsByInput: BoolControl.DEFAULT_TRUE,
8182
ignoreCase: BoolControl.DEFAULT_TRUE,
8283
searchFirstPY: BoolControl.DEFAULT_TRUE,
8384
searchCompletePY: BoolControl,
@@ -118,10 +119,11 @@ let AutoCompleteCompBase = (function () {
118119
autoCompleteType,
119120
autocompleteIconColor,
120121
componentSize,
122+
filterOptionsByInput,
121123
} = props;
122124

123125

124-
const getTextInputValidate = () => {
126+
const getTextInputValidate = useCallback(() => {
125127
return {
126128
value: { value: props.value.value },
127129
required: props.required,
@@ -131,7 +133,15 @@ let AutoCompleteCompBase = (function () {
131133
regex: props.regex,
132134
customRule: props.customRule,
133135
};
134-
};
136+
}, [
137+
props.value.value,
138+
props.required,
139+
props.minLength,
140+
props.maxLength,
141+
props.validationType,
142+
props.regex,
143+
props.customRule,
144+
]);
135145

136146
const [activationFlag, setActivationFlag] = useState(false);
137147
const [searchtext, setsearchtext] = useState<string>(props.value.value);
@@ -154,6 +164,113 @@ let AutoCompleteCompBase = (function () {
154164
props.customRule,
155165
]);
156166

167+
const handleFilterOptions = useCallback((inputValue: string, option: any) => {
168+
if (ignoreCase) {
169+
if (
170+
option?.label &&
171+
option?.label
172+
.toUpperCase()
173+
.indexOf(inputValue.toUpperCase()) !== -1
174+
)
175+
return true;
176+
} else {
177+
if (option?.label && option?.label.indexOf(inputValue) !== -1)
178+
return true;
179+
}
180+
if (
181+
chineseEnv &&
182+
searchFirstPY &&
183+
option?.label &&
184+
option.label
185+
.spell("first")
186+
.toString()
187+
.toLowerCase()
188+
.indexOf(inputValue.toLowerCase()) >= 0
189+
)
190+
return true;
191+
if (
192+
chineseEnv &&
193+
searchCompletePY &&
194+
option?.label &&
195+
option.label
196+
.spell()
197+
.toString()
198+
.toLowerCase()
199+
.indexOf(inputValue.toLowerCase()) >= 0
200+
)
201+
return true;
202+
if (!searchLabelOnly) {
203+
if (ignoreCase) {
204+
if (
205+
option?.value &&
206+
option?.value
207+
.toUpperCase()
208+
.indexOf(inputValue.toUpperCase()) !== -1
209+
)
210+
return true;
211+
} else {
212+
if (
213+
option?.value &&
214+
option?.value.indexOf(inputValue) !== -1
215+
)
216+
return true;
217+
}
218+
if (
219+
chineseEnv &&
220+
searchFirstPY &&
221+
option?.value &&
222+
option.value
223+
.spell("first")
224+
.toString()
225+
.toLowerCase()
226+
.indexOf(inputValue.toLowerCase()) >= 0
227+
)
228+
return true;
229+
if (
230+
chineseEnv &&
231+
searchCompletePY &&
232+
option?.value &&
233+
option.value
234+
.spell()
235+
.toString()
236+
.toLowerCase()
237+
.indexOf(inputValue.toLowerCase()) >= 0
238+
)
239+
return true;
240+
}
241+
return false;
242+
}, [filterOptionsByInput, ignoreCase, chineseEnv, searchFirstPY, searchCompletePY, searchLabelOnly]);
243+
244+
const handleChange = useCallback((value: string) => {
245+
props.valueInItems.onChange(false);
246+
setvalidateState(textInputValidate(getTextInputValidate()));
247+
setsearchtext(value);
248+
props.value.onChange(value);
249+
props.onEvent("change");
250+
}, [props.valueInItems, getTextInputValidate, props.value, props.onEvent]);
251+
252+
const handleSelect = useCallback((data: string, option: any) => {
253+
setsearchtext(option[valueOrLabel]);
254+
props.valueInItems.onChange(true);
255+
props.value.onChange(option[valueOrLabel]);
256+
props.onEvent("submit");
257+
}, [valueOrLabel, props.valueInItems, props.value, props.onEvent]);
258+
259+
const handleFocus = useCallback(() => {
260+
setActivationFlag(true);
261+
props.onEvent("focus");
262+
}, [props.onEvent]);
263+
264+
const handleBlur = useCallback(() => {
265+
props.onEvent("blur");
266+
}, [props.onEvent]);
267+
268+
const popupRender = useCallback((originNode: ReactNode) => (
269+
<DropdownStyled $style={props.childrenInputFieldStyle as ChildrenMultiSelectStyleType}>
270+
{originNode}
271+
</DropdownStyled>
272+
), [props.childrenInputFieldStyle]);
273+
157274
return props.label({
158275
required: props.required,
159276
children: (
@@ -163,117 +280,24 @@ let AutoCompleteCompBase = (function () {
163280
value={searchtext}
164281
options={items}
165282
style={{ width: "100%" }}
166-
onChange={(value: string, option) => {
167-
props.valueInItems.onChange(false);
168-
setvalidateState(textInputValidate(getTextInputValidate()));
169-
setsearchtext(value);
170-
props.value.onChange(value);
171-
props.onEvent("change")
172-
}}
173-
onFocus={() => {
174-
setActivationFlag(true)
175-
props.onEvent("focus")
176-
}}
177-
onBlur={() => props.onEvent("blur")}
178-
onSelect={(data: string, option) => {
179-
setsearchtext(option[valueOrLabel]);
180-
props.valueInItems.onChange(true);
181-
props.value.onChange(option[valueOrLabel]);
182-
props.onEvent("submit");
183-
}}
184-
filterOption={(inputValue: string, option) => {
185-
if (ignoreCase) {
186-
if (
187-
option?.label &&
188-
option?.label
189-
.toUpperCase()
190-
.indexOf(inputValue.toUpperCase()) !== -1
191-
)
192-
return true;
193-
} else {
194-
if (option?.label && option?.label.indexOf(inputValue) !== -1)
195-
return true;
196-
}
197-
if (
198-
chineseEnv &&
199-
searchFirstPY &&
200-
option?.label &&
201-
option.label
202-
.spell("first")
203-
.toString()
204-
.toLowerCase()
205-
.indexOf(inputValue.toLowerCase()) >= 0
206-
)
207-
return true;
208-
if (
209-
chineseEnv &&
210-
searchCompletePY &&
211-
option?.label &&
212-
option.label
213-
.spell()
214-
.toString()
215-
.toLowerCase()
216-
.indexOf(inputValue.toLowerCase()) >= 0
217-
)
218-
return true;
219-
if (!searchLabelOnly) {
220-
if (ignoreCase) {
221-
if (
222-
option?.value &&
223-
option?.value
224-
.toUpperCase()
225-
.indexOf(inputValue.toUpperCase()) !== -1
226-
)
227-
return true;
228-
} else {
229-
if (
230-
option?.value &&
231-
option?.value.indexOf(inputValue) !== -1
232-
)
233-
return true;
234-
}
235-
if (
236-
chineseEnv &&
237-
searchFirstPY &&
238-
option?.value &&
239-
option.value
240-
.spell("first")
241-
.toString()
242-
.toLowerCase()
243-
.indexOf(inputValue.toLowerCase()) >= 0
244-
)
245-
return true;
246-
if (
247-
chineseEnv &&
248-
searchCompletePY &&
249-
option?.value &&
250-
option.value
251-
.spell()
252-
.toString()
253-
.toLowerCase()
254-
.indexOf(inputValue.toLowerCase()) >= 0
255-
)
256-
return true;
257-
}
258-
return false;
259-
}}
260-
popupRender={(originNode: ReactNode) => (
261-
<DropdownStyled $style={props.childrenInputFieldStyle as ChildrenMultiSelectStyleType}>
262-
{originNode}
263-
</DropdownStyled>
264-
)}
283+
onChange={handleChange}
284+
onFocus={handleFocus}
285+
onBlur={handleBlur}
286+
onSelect={handleSelect}
287+
filterOption={!filterOptionsByInput ? false : handleFilterOptions}
288+
popupRender={popupRender}
265289
>
266-
<InputStyle
267-
ref={props.viewRef}
268-
placeholder={placeholder}
269-
allowClear={props.allowClear}
270-
$style={props.inputFieldStyle}
271-
prefix={hasIcon(props.prefixIcon) && props.prefixIcon}
272-
suffix={hasIcon(props.suffixIcon) && props.suffixIcon}
273-
status={getValidate(validateState)}
274-
onPressEnter={undefined}
275-
tabIndex={typeof props.tabIndex === 'number' ? props.tabIndex : undefined}
276-
/>
290+
<InputStyle
291+
ref={props.viewRef}
292+
placeholder={placeholder}
293+
allowClear={props.allowClear}
294+
$style={props.inputFieldStyle}
295+
prefix={hasIcon(props.prefixIcon) && props.prefixIcon}
296+
suffix={hasIcon(props.suffixIcon) && props.suffixIcon}
297+
status={getValidate(validateState)}
298+
onPressEnter={undefined}
299+
tabIndex={typeof props.tabIndex === 'number' ? props.tabIndex : undefined}
300+
/>
277301
</AutoComplete>
278302
</>
279303
),
@@ -306,24 +330,33 @@ let AutoCompleteCompBase = (function () {
306330
tooltip: itemsDataTooltip,
307331
placeholder: '[]',
308332
})}
309-
{getDayJSLocale() === 'zh-cn' &&
333+
{children.filterOptionsByInput.propertyView({
334+
label: trans('autoComplete.filterOptionsByInput'),
335+
})}
336+
{children.filterOptionsByInput.getView() && getDayJSLocale() === 'zh-cn' && (
310337
children.searchFirstPY.propertyView({
311338
label: trans('autoComplete.searchFirstPY'),
312-
})}
313-
{getDayJSLocale() === 'zh-cn' &&
339+
})
340+
)}
341+
{children.filterOptionsByInput.getView() && getDayJSLocale() === 'zh-cn' && (
314342
children.searchCompletePY.propertyView({
315343
label: trans('autoComplete.searchCompletePY'),
316-
})}
317-
{children.searchLabelOnly.propertyView({
344+
})
345+
)}
346+
{children.filterOptionsByInput.getView() && children.searchLabelOnly.propertyView({
318347
label: trans('autoComplete.searchLabelOnly'),
319348
})}
320-
{children.ignoreCase.propertyView({
321-
label: trans('autoComplete.ignoreCase'),
322-
})}
323-
{children.valueOrLabel.propertyView({
324-
label: trans('autoComplete.checkedValueFrom'),
325-
radioButton: true,
326-
})}
349+
{children.filterOptionsByInput.getView() && (
350+
children.ignoreCase.propertyView({
351+
label: trans('autoComplete.ignoreCase'),
352+
})
353+
)}
354+
{children.filterOptionsByInput.getView() && (
355+
children.valueOrLabel.propertyView({
356+
label: trans('autoComplete.checkedValueFrom'),
357+
radioButton: true,
358+
})
359+
)}
327360
</Section>
328361
<TextInputBasicSection {...children} />
329362

client/packages/lowcoder/src/i18n/locales/en.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4475,6 +4475,7 @@ export const en = {
44754475
"autoComplete": {
44764476
"value": "Auto Complete Value",
44774477
"checkedValueFrom": "Checked Value From",
4478+
"filterOptionsByInput": "Filter Options By Input",
44784479
"ignoreCase": "Search Ignore Case",
44794480
"searchLabelOnly": "Search Label Only",
44804481
"searchFirstPY": "Search First Pinyin",

0 commit comments

Comments
 (0)