Skip to content

Commit

Permalink
feat: add props excludeItems, excludeSearchItems
Browse files Browse the repository at this point in the history
  • Loading branch information
hoaphantn7604 committed May 3, 2024
1 parent 4ff1be0 commit 59ac0a2
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 10 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ yarn add react-native-element-dropdown
| accessibilityLabel | String | No | Set an accessibilityLabel on the view, so that people who use VoiceOver know what element they have selected |
| itemAccessibilityLabelField | String | No | Add this field to the input data. Ex: DATA = [{itemAccessibilityLabelField: '', label: '', value:: ''}]|
| closeModalWhenSelectedItem | Boolean | No | By default, closeModalWhenSelectedItem is set to true. When closeModalWhenSelectedItem is set to false, the Modal won't close when an item is selected. |
| excludeItems | Item[] | No | The array containing the items to be excluded. |
| excludeSearchItems | Item[] | No | The array containing the items to be excluded. |



Expand Down Expand Up @@ -143,6 +145,8 @@ yarn add react-native-element-dropdown
| itemTestIDField | String | No | Add this field to the input data. Ex: DATA = [{itemTestIDField: '', label: '', value:: ''}]|
| accessibilityLabel | String | No | Set an accessibilityLabel on the view, so that people who use VoiceOver know what element they have selected |
| itemAccessibilityLabelField | String | No | Add this field to the input data. Ex: DATA = [{itemAccessibilityLabelField: '', label: '', value:: ''}]|
| excludeItems | Item[] | No | The array containing the items to be excluded. |
| excludeSearchItems | Item[] | No | The array containing the items to be excluded. |



Expand Down
6 changes: 6 additions & 0 deletions example/src/dropdown/Dropdown1.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ const data = [
{ label: 'Item 8', value: '8', search: 'Item 8' },
];

const excludeItem = [
{ label: 'Item 7', value: '7', search: 'Item 7' },
{ label: 'Item 8', value: '8', search: 'Item 8' },
];

const DropdownComponent = () => {
const [value, setValue] = useState<string>();
const [isFocus, setIsFocus] = useState(false);
Expand All @@ -40,6 +45,7 @@ const DropdownComponent = () => {
inputSearchStyle={styles.inputSearchStyle}
iconStyle={styles.iconStyle}
data={data}
excludeSearchItems={excludeItem}
autoScroll
search
maxHeight={300}
Expand Down
6 changes: 6 additions & 0 deletions example/src/dropdown/MultiSelectAll.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ const data = [
{ label: 'Item 8', value: '8' },
];

const excludeItem = [
{ label: 'Item 7', value: '7', search: 'Item 7' },
{ label: 'Item 8', value: '8', search: 'Item 8' },
];

const MultiSelectComponent = () => {
const [selected, setSelected] = useState<string[]>([]);
const ref = useRef(null);
Expand Down Expand Up @@ -54,6 +59,7 @@ const MultiSelectComponent = () => {
backgroundColor={'rgba(0,0,0,0.2)'}
search
data={data}
excludeItems={excludeItem}
labelField="label"
valueField="value"
placeholder="Multiselect All"
Expand Down
54 changes: 49 additions & 5 deletions src/components/Dropdown/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-shadow */
import _ from 'lodash';
import React, {
JSXElementConstructor,
Expand Down Expand Up @@ -89,6 +90,8 @@ const DropdownComponent: <T>(
itemAccessibilityLabelField,
mode = 'default',
closeModalWhenSelectedItem = true,
excludeItems = [],
excludeSearchItems = [],
} = props;

const ref = useRef<View>(null);
Expand Down Expand Up @@ -123,8 +126,25 @@ const DropdownComponent: <T>(
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

const excludeData = useCallback(
(data: any[]) => {
if (excludeItems.length > 0) {
const getData = _.differenceWith(
data,
excludeItems,
(obj1, obj2) => _.get(obj1, valueField) === _.get(obj2, valueField)
);
return getData || [];
} else {
return data || [];
}
},
[excludeItems, valueField]
);

useEffect(() => {
setListData([...data]);
const filterData = excludeData(data);
setListData([...filterData]);
if (searchText) {
onSearch(searchText);
}
Expand Down Expand Up @@ -277,7 +297,8 @@ const DropdownComponent: <T>(

_measure();
setVisible(!visible);
setListData(data);
const filterData = excludeData(data);
setListData(filterData);

if (!visible) {
if (onFocus) {
Expand Down Expand Up @@ -333,12 +354,35 @@ const DropdownComponent: <T>(
const dataSearch = data.filter(
searchQuery ? propSearchFunction : defaultFilterFunction
);
setListData(dataSearch);

if (excludeSearchItems.length > 0 || excludeItems.length > 0) {
const excludeSearchData = _.differenceWith(
dataSearch,
excludeSearchItems,
(obj1, obj2) =>
_.get(obj1, valueField) === _.get(obj2, valueField)
);

const filterData = excludeData(excludeSearchData);
setListData(filterData);
} else {
setListData(dataSearch);
}
} else {
setListData(data);
const filterData = excludeData(data);
setListData(filterData);
}
},
[data, searchField, labelField, searchQuery]
[
data,
searchQuery,
excludeSearchItems,
excludeItems,
searchField,
labelField,
valueField,
excludeData,
]
);

const onSelect = useCallback(
Expand Down
2 changes: 2 additions & 0 deletions src/components/Dropdown/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ export interface DropdownProps<T> {
inverted?: boolean;
mode?: 'default' | 'modal' | 'auto';
closeModalWhenSelectedItem?: boolean;
excludeItems?: T[];
excludeSearchItems?: T[];
onChange: (item: T) => void;
renderLeftIcon?: (visible?: boolean) => JSX.Element | null | undefined;
renderRightIcon?: (visible?: boolean) => JSX.Element | null | undefined;
Expand Down
54 changes: 49 additions & 5 deletions src/components/MultiSelect/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ const MultiSelectComponent: <T>(
itemAccessibilityLabelField,
visibleSelectedItem = true,
mode = 'default',
excludeItems = [],
excludeSearchItems = [],
} = props;

const ref = useRef<View>(null);
Expand Down Expand Up @@ -127,8 +129,26 @@ const MultiSelectComponent: <T>(
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

const excludeData = useCallback(
(data: any[]) => {
if (excludeItems.length > 0) {
const getData = _.differenceWith(
data,
excludeItems,
(obj1, obj2) => _.get(obj1, valueField) === _.get(obj2, valueField)
);
return getData || [];
} else {
return data || [];
}
},
[excludeItems, valueField]
);

useEffect(() => {
setListData([...data]);
const filterData = excludeData(data);
setListData([...filterData]);

if (searchText) {
onSearch(searchText);
}
Expand Down Expand Up @@ -244,7 +264,8 @@ const MultiSelectComponent: <T>(

_measure();
setVisible(!visible);
setListData(data);
const filterData = excludeData(data);
setListData(filterData);

if (!visible) {
if (onFocus) {
Expand Down Expand Up @@ -299,12 +320,35 @@ const MultiSelectComponent: <T>(
const dataSearch = data.filter(
searchQuery ? propSearchFunction : defaultFilterFunction
);
setListData(dataSearch);

if (excludeSearchItems.length > 0 || excludeItems.length > 0) {
const excludeSearchData = _.differenceWith(
dataSearch,
excludeSearchItems,
(obj1, obj2) =>
_.get(obj1, valueField) === _.get(obj2, valueField)
);

const filterData = excludeData(excludeSearchData);
setListData(filterData);
} else {
setListData(dataSearch);
}
} else {
setListData(data);
const filterData = excludeData(data);
setListData(filterData);
}
},
[data, searchField, labelField, searchQuery]
[
data,
searchQuery,
excludeSearchItems,
excludeItems,
searchField,
labelField,
valueField,
excludeData,
]
);

const onSelect = useCallback(
Expand Down
2 changes: 2 additions & 0 deletions src/components/MultiSelect/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ export interface MultiSelectProps<T> {
itemAccessibilityLabelField?: string;
inverted?: boolean;
mode?: 'default' | 'modal' | 'auto';
excludeItems?: T[];
excludeSearchItems?: T[];
onChange: (value: string[]) => void;
renderLeftIcon?: (visible?: boolean) => JSX.Element | null | undefined;
renderRightIcon?: (visible?: boolean) => JSX.Element | null | undefined;
Expand Down

0 comments on commit 59ac0a2

Please sign in to comment.