Create a autocomplete search dropdown picker with tree view in React Native
December 16, 2021
Create a autocomplete search dropdown picker with tree view in React Native/React
App.js
import React,{useRef} from 'react'
import { SafeAreaView,Text,View } from 'react-native';
import AutoCompletePicker from './AutoCompletePicker';
const Data=[{"entityId":1,"name":"Test Root",
"entityTypeName":"Test",
"parentValueId":null},
{"entityId":2,"name":"Test Industries",
"entityTypeName":"Test Name",
"parentValueId":null}]
const App = () => {
const fieldRef = useRef(null);
const FocusTextInputFxn = () =>{
fieldRef?.current.focus()
}
const ClearFxn=()=>{
fieldRef?.current.clear();
}
const SetItemFxn=(ItemData)=>{
console.info(ItemData)
}
const ConvertFlatToTree = (items, entityId = null, link = 'parentValueId') =>
items.filter(item => item[link] === entityId)
.map(item => ({ ...item, children: ConvertFlatToTree(items, item.entityI
d) }));
return (
<SafeAreaView>
<AutoCompletePicker
fieldRef={fieldRef}
label="Email"
SetItem={(ItemData)=>SetItemFxn(ItemData)}
focusTextInput={FocusTextInputFxn}
Clear={ClearFxn}
Data={ConvertFlatToTree(Data)}
/>
<View style={{margin:10}}>
<Text>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s,
when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries,
</Text>
</View>
</SafeAreaView>
)
}
export default App
AutoCompletePicker.js
import React,{useState} from 'react'
import { View,ScrollView,TouchableOpacity,
Dimensions,
StyleSheet
} from 'react-native';
import { TextInput } from 'react-native-paper'
import styled from 'styled-components/native';
import AwesomeIcon from 'react-native-vector-icons/FontAwesome';
const { width, height } = Dimensions.get('window');
const size = size => (size / 100) * width;
const hp = hp => (hp / 100) * height;
const wp = wp => (wp / 100) * width;
const styles=StyleSheet.create({
item: {
height: hp(5),
paddingHorizontal: wp(5),
justifyContent: 'center',
},
itemText: {
color: 'black'
},
list: {
width: wp(96),
height: hp(30),
maxHeight: hp(30)
},
listContainer: {
padding: size(1.75),
}
})
const RenderIcons=({clear,DropDownToggle})=>{
return <View style={{flexDirection:'row',alignItems:'center'}}>
<AwesomeIcon
onPress={DropDownToggle}
name="caret-down" size={22} style={{margin:8}}/>
<AwesomeIcon
onPress={clear}
name="close" size={22} style={{margin:8}}/>
</View>
}
const Item = ({item,Selected}) => {
return <View
style={styles.item}>
<ListText
Selected={Selected}
style={styles.itemText}>{item.name}</ListText>
</View>
}
const CustomInput = ({value,fieldRef,right,...props}) => (
<TextInput
{ ...props }
ref={fieldRef}
value={value}
render={ (inputProps) => (
<InputContainer>
<Input { ...inputProps } />
{right && (
<AdornmentContainer>
{right}
</AdornmentContainer>
)}
</InputContainer>
) }
/>
)
const AutoCompletePicker = ({Data,fieldRef,focusTextInput,Clear,label,SetItem}) => {
const [ListData, SetListData] = useState(Data);
const [DropDownState, SetDropDownState] = useState(false);
const [ActiveEntityID, SetActiveEntityID] = useState(null);
const [input, setInput] = useState(null);
const OnChangeTextFxn=(text)=>{
let textValue = text.toLowerCase();
let StoreDataForRest = Data;
if (!text || text === '') {
SetListData(Data)
}
let FilterLabel = StoreDataForRest.filter((item) => {
return item.name.toLowerCase().match(textValue)
})
SetListData(FilterLabel)
setInput(text)
}
const ClearAndClose=()=>{
Clear()
setInput(null)
SetListData(Data)
}
return (
<View style={{margin:6}}>
<CustomInput
fieldRef={fieldRef}
value={input}
onFocus={()=>SetDropDownState(true)}
onBlur={()=>SetDropDownState(false)}
mode="outlined"
onChangeText={(text) => OnChangeTextFxn(text)}
label={label}
right={
<RenderIcons
clear={ClearAndClose}
DropDownToggle={focusTextInput}
/>
}
/>
{DropDownState&&
<>
/*
IF YOU ONLY NEED SEARCHING AND AUTOCOMPLETE THIS IS PREFRECT
IF YOU NEED NESTED TREE VIEW JUST USED THE COMPONET THAT IS
https://www.npmjs.com/package/react-native-nested-listview
You can replace with scrollview with nested-listview
*/
{ListData?.length!==0&&
<ScrollView
keyboardShouldPersistTaps='handled'
style={styles.list}
contentContainerStyle={styles.listContainer}
>
{
ListData.map((item, index) => (
<TouchableOpacity
onPress={()=>{
setInput(item?.name)
fieldRef?.current.blur();
SetItem(item)
SetActiveEntityID(item?.entityId)
}}
key={index}>
<Item item={item}
Selected={ActiveEntityID==item?.entityId}
/>
{ListData.length !== (index + 1) ? <Separator/> : null}
</TouchableOpacity>
))
}
</ScrollView>
}
{ListData?.length===0&&
<NoItemFound>No Item Found..</NoItemFound>
}
</>
}
</View>
)
}
export default AutoCompletePicker;
const InputContainer = styled.View`
flex-direction: row;
`
const Input = styled.TextInput`
flex: 1;
`
const AdornmentContainer = styled.View`
align-items: center;
justify-content: center;
padding: 0 10px;
`
const Separator = styled.View`
border-bottom-width: 1px;
border-bottom-color:#c2c2c2
`
const ListText = styled.Text`
font-weight: ${props=>props.Selected?"bold":'normal'};
`
const NoItemFound = styled.Text`
font-weight:bold;
margin: 10px;
text-align: center;
`