Disable the input from react-native-autocomplete-input - javascript

I'm using react-native-autocomplete-input and I'd like disable the <Autocomplete /> input. I tried adding disabled={this.state.loading} (disabling it while the data loads...right now the user can start typing before the autocomplete is available).
I'm confident there's a way to do so but I haven't been able to figure it out. Code below:
<Autocomplete
data={data}
defaultValue={query}
listStyle={styles.autoCompleteItems}
onChangeText={(text) => this.setState({query: text})}
renderItem={(data) => (
<TouchableOpacity onPress={() =>
this.setState({query: data.name, schoolId: data.id, social: data.social})
}
>
<Text>{data.name}</Text>
</TouchableOpacity>
)}
/>

react-native-autocomplete-input itself does not provide functionality to disable the input field. So passing disabled={this.state.loading} will have no effect.
You can edit the the package by going into your node_modules/react-native-autocomplete-input folder and editing index.js file.
change the render function in index.js to following. Now its accepting isEditable prop and passing it to TextInput
render() {
const { showResults } = this.state;
const { containerStyle, inputContainerStyle, onEndEditing, isEditable, style, ...props } = this.props;
return (
<View style={[styles.container, containerStyle]}>
<View style={[styles.inputContainer, inputContainerStyle]}>
<TextInput
editable={isEditable}
style={[styles.input, style]}
ref="textInput"
onEndEditing={e =>
this._showResults(false) || (onEndEditing && onEndEditing(e))
}
{...props}
/>
</View>
{showResults && this._renderItems()}
</View>
);
}
Now you can pass isEditable={this.loading} as a prop to <Autocomplete />

Related

How do I change the state present in a specific item within a flatlist?

I am generating a flatlist that contains comments. Inside the comment component, I'm using a state isCollpsed to determine if the individual comment is collapsed or not. Pressing on each individual comment does make it collapse. However, I want to manipulate this state from the parent component without affecting every other comment. How could I achieve this?
I tried using the reference hook to access each individual item in the flatlist but it keeps returning 'undefined'. I'm using the react-native-collapsible library to collapse the comments.
My Flatlist:
<FlatList
data={SAMPLE_COMMENTS}
keyExtractor={keyExtractor}
renderItem={({item})=>
<Comment
ref={(el) => {rowRefs.current[item.id] = el} }
onPress={()=>{rowRefs.current[item.id].collapseFunction()}}
body={item.body}
author={item.author}
level={item.level}
createdAt={item.createdAt}
commentId={item.id}
commentChildren={item.replies} />}
/>
Comment Component :
const [isCollapsed, setIsCollapsed] = useState(false);
const collapseFunction = () => {setIsCollapsed(!isCollapsed)};
return (
<Collapsible collapsed={isCollapsed}>
<TouchableWithoutFeedback onPress={onPress}>
<View style={styles.container}>
</View>
</TouchableWithoutFeedback>
</Collapsible>
you can use recursive function
// add this to parent
<MapComments
comments={SAMPLE_COMMENTS}
childClickHandler={onItemClickHandler}
/>
// MapComments component
const MapComments= ({
Comments= [],
childClickHandler,
}) => {
return (
<ScrollView>
<Tree
CommentTree={CommentTree}
childClickHandler={childClickHandler}
/>
</ScrollView>
);
};
const Tree = ({CommentTree= [], childClickHandler}) => {
return (
<View>
{CommentTree.map(tree => (
<TreeNode
key={tree.commentId}
node={tree}
childClickHandler={childClickHandler}
/>
))}
</View>
);
};
const TreeNode = ({node, childClickHandler}) => {
const [childVisible, setChildVisiblity] = useState(false);
const hasChild = node.commentChildren.length > 0 ? true : false;
return (
<View
style={{marginRight: node.Level > 1 ? 40 : null}}>
<TouchableOpacity
onPress={() =>
hasChild ? setChildVisiblity(prev => !prev) : childClickHandler(node)
}>
<Text numberOfLines={1} style={styles.label}>
{node.body}
</Text>
{hasChild ? (
<AntDesign name={childVisible ? 'minus' : 'plus'}
/>
) : (
<FontAwesome name="circle" />
)}
</TouchableOpacity>
{hasChild && childVisible && (
<Tree
childClickHandler={childClickHandler}
knowledgeTree={node.commentChildren}
/>
)}
</View>
);
};

How do I grab state information from custom header button component in react-native?

I'm new to React. I'm having a tough time trying to change how a screen looks depending on what value I select inside a dialog/modal that pops up when I press the header button using a Stack Navigator.
This is a gif of what it looks like: https://i.imgur.com/Yw2jbHu.gifv
This is what my Stack Navigation looks like:
const HistoryStack = () =>{
return (
<Stack.Navigator screenOptions={{headerShown:true,headerStyle:{backgroundColor:'#21252B',shadowColor: '#333842'},headerTintColor:"#528bff",headerTitleAlign: 'center' }}>
<Stack.Screen name="History" component={History} />
<Stack.Screen name="Logging" options={({ navigation, route })=> ({headerTitle: props => <SwitchWorkoutButton/>})}component={Logging} />
</Stack.Navigator>
);
}
As you can see I made the header title my own custom button component. I added a currentWorkout state variable to the component that gets set whenever a value selected in the dialog.
This is what the header button looks like:
const SwitchWorkoutButton = () =>{
const [showDialog,setShowDialog] = useState(false)
const [currentWorkout,setCurrentWorkout] = useState('A')
const renderDialog = (showDialog) =>{
return (<Dialog migrate visible={showDialog} useSafeArea bottom onDismiss={setShowDialog(false)}>test</Dialog>)
}
const closeDialog = () =>{
setShowDialog(false)
}
const openDialog = () =>{
setShowDialog(true)
}
return (
<View>
<Chip label ="Workout A"
iconStyle={{margin: 4,tintColor:'#528bff',width:11,height:6}}
rightIconSource={require('../assets/chevronDown.png')}
labelStyle={{color: Colors.white,fontSize:13}}
containerStyle={{borderColor: "#2D2E33", backgroundColor: "#2D2E33", marginLeft: Spacings.s3,padding:2.5,width:115}}
onPress={() =>{ console.log('pressed',showDialog)
setShowDialog(true)
console.log('pressed',showDialog)
}}/>
<Dialog migrate height={150} containerStyle={styles.roundedDialog} panDirection={PanningProvider.Directions.UP} visible={showDialog} onDismiss={closeDialog} useSafeArea top>
<View style ={{backgroundColor:'#2d2e33',borderBottomColor:'#929497',borderBottomWidth:.2,alignItems:'center',}}>
<Text style={{fontSize:20,marginVertical:10,color:'#929497'}}>Switch Workout</Text>
</View>
<TouchableOpacity onPress={()=>{setCurrentWorkout('B')}}>
<View style ={{paddingLeft:20,marginVertical:5,marginTop:10}}>
<Text style={{fontSize:20,color:'#929497',}}>Workout B</Text>
</View>
</TouchableOpacity>
<TouchableOpacity onPress={()=>{setCurrentWorkout('C')}}>
<View style ={{paddingLeft:20,marginVertical:5}}>
<Text style={{fontSize:20,color:'#929497'}}>Workout C</Text>
</View>
</TouchableOpacity>
</Dialog>
</View>
);
}
And this is the page where the content is displayed through my WorkoutSet component that gets passed a prop that I will use to display the correct data.
const Logging = ({navigation}) =>{
const [selectedIndex,setSelectedIndex] = useState(0)
return (
<SafeAreaView style={{ flex: 1,backgroundColor:'#21252B'}}>
<View style={{ flex:3}} >
<WorkoutSet id={'A'}/>
</View>
</SafeAreaView>
);
}
My question is how do I grab the value I selected in the dialog to do that. I've read through https://reactnavigation.org/docs/header-buttons/ but their use case is different than mine.

React Native editable FlatList How to edit item data

React Native editable FlatList – How to edit item data in a List?
Hi code community, I am new in reactive native and I need some help. I am trying to handle a data update in FlatList. where the user can change the text name for whatever they want. Exemplo if the user creates a folder named "Bar" but later on decides to change the name for "Bar1". How can I do it??? Here is my code so far...
My Modal State
const [modalVisible, setModalVisible] = useState(false);
My FlatList Component... discard data={folderToDisplay}
<FlatList numColumns={4} data={folderToDisplay} renderItem={renderItem} />
My renderItem={renderItem} is set like this: where {itemData.item.value} is here I am fetching my text name. We can replace {itemData.item.value} to Bar if you wish.
const renderItem = (itemData) => {
return (
<View style={styles.folderNameContainer}>
<TouchableOpacity
onPress={() => {
setModalVisible(true);
}}
>
<Text style={styles.itemText}>{itemData.item.value}</Text>
</TouchableOpacity>
</View>
);
};
When I press the text name a Modal opens.
<Modal animationType="fade" transparent={true} visible={modalVisible}>
<SimpleModal
closeModal={onCloseModal}
/>
</Modal>
...And when I press cancel it close.
const onCloseModal = () => {
setModalVisible(false);
};
My SimpleModal component is set like this: I could make my code all in one place but it looks ugly.
const SimpleModal = (props) => {
return (
<View style={styles.centeredView}>
<View style={styles.modalView}>
<Text style={styles.modalText}>Change Name!</Text>
<TextInput
style={styles.textInput}
placeholder="Type Here..."
maxLength={15}
/>
<View style={styles.saveAndCancelContainer}>
<View style={styles.button}>
<Button title="Save" color="#87CEEB" onPress={props.renameFolder} />
</View>
<View style={styles.button}>
<Button title="Cancel" color="red" onPress={props.closeModal} />
</View>
</View>
</View>
</View>
);
};
Now the goal here is in my TextInput the user type a new name and then press Save. When onPress it will update the name for the new name. and close the modal. So far this is what I have:
<Modal animationType="fade" transparent={true} visible={modalVisible}>
<SimpleModal
renameFolder={handleRenameFolder}
/>
</Modal>
const handleRenameFolder = () => {
///....????
setModalVisible(false);
};

Updating data on an index of a array javascript and react native

In my Todo App i have sucessfully implemented the add and delete functions but the update function is having trouble. What i need it to do is when i click the touchable opacity of a Todo, it should appear in my inputbox and if any change is made then that todo should be updated e.g clicking on abcd must make it appear in input box and changes made to it should be updated. Picture is also added below
export default function Todo() {
const [getText, setText] = useState('');
const [getList, setList] = useState([]);
const addItem = () => {
setList([...getList, {key: Math.random().toString(), data: getText}]);
setText('');
}
const removeItem = (itemKey) => {
setList(() => getList.filter(item => item.key != itemKey));
}
const updateFieldChanged = (index) => e => {
let newArr = [...getList]; // copying the old datas array
newArr[index] = e.target.value; // replace e.target.value with whatever you want to change it to
setList(newArr);
}
return (
<View style={styles.container}>
<Text style={styles.title}>todo</Text>
<View style={styles.inputContainer}>
<TextInput
style={styles.textInput}
placeholder="Enter Item"
onChangeText={text => setText(text)}
value={getText}
/>
<CustomButton
text = 'add'
color='red'
title= 'add'
textSize={20}
textColor="white"
onPressEvent={addItem}
/>
</View>
<ScrollView style={styles.scrollview}>
{getList.map((item, id) =>
<TouchableOpacity
key={item.key}
activeOpacity={0.7}
onPress= {() => updateFieldChanged(id)}
>
<View style={styles.scrollviewItem}>
<Text style={styles.scrollviewText}>{id}) {item.data}</Text>
<TouchableOpacity
onPress={() => removeItem(item.key)}
>
<View style={styles.crosstextcontainer}>
<Text style={styles.crosstext}>X</Text>
</View>
</TouchableOpacity>
</View>
</TouchableOpacity>
)}
</ScrollView>
</View>
);
}
Change
<TouchableOpacity
key={item.key}
activeOpacity={0.7}
onPress= {() => updateFieldChanged(id)}
>
to
<TouchableOpacity
key={item.key}
activeOpacity={0.7}
onPress= {() => updateFieldChanged(id,getText)}
>
Here iam passing the text that you need to enter to update a particular field
change your updateFieldChanged like this:
const updateFieldChanged = (index, text) => {
let newArr = [...getList]; // copying the old datas array
newArr[index].data = text; // replace e.target.value with whatever you want to change it to
setList(newArr);
setText('');
}
Here iam assigning the text you entered in the TextInput to the data object, which will update the array.
Hope this helps!

save selected value to form field

I have a form where there is an input field for adding the user. It is a different kind of field. When user click on that field, the user is routed to another page where there is already a list of users and there a user can search as well. From that page, if user selects the particular user, he/she is redirected back to that form page and fill that field with the selected user name.
For now I have tried it as following
<Row>
<InputFieldWrapper label="Assigned to">
<Field
name="assigned_to"
input=""
placeholder="Search for contacts to assign"
readonly={false}
component={InputTextWithSearchField}
onPress={() => Actions[routeConstants.SEARCH_ASSIGNEE]({
keys : 'user',
data : taskValues ? taskValues.assigned_to : [],
faFetched: faFetched.users,
fieldName: 'assigned_to',
label : 'Assignee',
})}
/>
</InputFieldWrapper>
</Row>
const InputTextWithSearchField = props => {
let value = props.input.value || {};
makeUpdate = text => {
props.update(text);
};
return (
<View style={styles.inputFieldWrapper}>
<View style={styles.field}>
<TextInput
style={styles.inputField}
onChangeText={makeUpdate}
value={value.label}
placeholder={props.placeholder} />
</View>
<View style={styles.rightSideContent}>
<Icon
name="search"
size={26}
onPress={() => props.onPress()}
style={styles.searchField} />
</View>
</View>
);
};
class Search extends React.Component { // eslint-disable-line
state = {
items: [],
}
componentDidMount() {
this.update(' ');
}
// handleChange = data => {
// console.log('change', data);
// };
update = text => {
this.props.faFetched.sync(
{ search: text, priority_fields: 'personal.first_name,personal.last_name' }
).
then(res => this.setState({ items: res })).
catch(err => console.log(err)); // eslint-disable-line
};
itemSection = item => {
if(item)return alphabetic.map(alpha => {
return ({
title: alpha,
data : (item || []).filter(contact => contact.personal.first_name[0] === alpha)
});
});
};
renderHeader = ({ section }) => {
return <View style={styles.sectionHeader}>
<Text style={styles.sectionText}>
{section.title}
</Text>
</View>;
};
render() {
const { faFetched, data } = this.props;
const { items } = this.state;
return (
<View style={styles.container}>
<ActionButtons
label={this.props.label}
/>
<KeyboardAvoidingView keyboardVerticalOffset={0} behavior='padding'>
<ScrollView
keyboardShouldPersistTaps="always"
>
<View style={styles.formContainer}>
<Row zIndex={5}>
<InputFieldWrapper>
<Field
input=""
name={this.props.fieldName}
placeholder="Search contact"
update={this.update}
readonly={false}
component={InputTextWithSearchField}
/>
</InputFieldWrapper>
</Row>
</View>
<SectionList
sections={this.itemSection(items && items)}
renderItem={({ item, section }) => {
if(item)return <ListItem
item={item}
section={section} />;
}}
renderSectionHeader={items && this.renderHeader}
keyExtractor={item => item._id}
/>
</ScrollView>
</KeyboardAvoidingView>
</View>
);
}
}
class ListItem extends React.Component {
render() {
return (
<View style={styles.sectionItemWrapper}>
<TouchableOpacity onPress={() => null;}>
<Text style={styles.sectionItem}>
{this.props.item.personal.full_name}
</Text>
</TouchableOpacity>
</View>
);
}
}
It should be following
when user clicks on this input field, he/she will move to next step
next step is this and when user selects the name of user from the list he/she will be redirected back to the form page where that username should be filled in that field
Can anyone give me an idea, please? Right now I could only redirect the user to the contact list but I have no idea how can i route back to the same form page after user touches the contact list and fill the field with that value
If you are using react-navigation you can navigate back to the form page and send parameters along with.
this.props.navigation.navigate("form", {
userID:id,
userName: Name,
})
and then in componentdidmount method set value of text field to the one passed in parameters.
If you are using react-native-router-flux use
Actions.YOURSCENE({userID:id, userName: Name});
or use
Actions.pop({refresh: {userID:id, userName: Name}});
you may find the passed data in this.props

Categories