React Native: flex - move content to far right - reactjs

I'm trying to move the selection text to the far right on this Detail component. I've tried justifyContent on the View with the sideBySide style and alignSelf on the selectionStyle. I've tried various combinations but am not able to move the selection text to the far right, up until where the arrow might be. I feel like there's something simple I'm missing.
Here's what it looks like (Selection is not to the far right):
Thanks for any help!
const Detail = ({ onPress, selection, text, info }) => {
const wrapper = {
flex: 1,
paddingTop: 20,
paddingLeft: 16,
};
const sideBySide = {
flexDirection: 'row',
};
const textStyle = {
flex: 1.3,
fontWeight: '500',
fontSize: 12,
paddingRight: 5,
};
const selectionStyle = {
flex: 1,
color: 'blue',
fontWeight: '500',
fontSize: 12,
};
const infoWrapper = {
paddingTop: 8,
paddingBottom: 20,
};
return (
<ViewWrapper onPress={onPress} noArrow={true}>
<View style={wrapper}>
<View style={sideBySide}>
<Text style={textStyle}>
{text}
</Text>
<Text style={selectionStyle}>
{selection}
</Text>
</View>
<View style={infoWrapper}>
<Text style={subHeader}>
{info}
</Text>
</View>
</View>
</ViewWrapper>
);
};
const iconView = { position: 'absolute', right: 16 };
const icon = { color: 'gray', fontSize: 14 };
const ViewWrapper = ({ onPress, children, noArrow, style }) => {
const view = {
flexDirection: 'row',
alignItems: 'center',
paddingRight: Platform.OS === 'ios' && !noArrow ? 35 : 16,
backgroundColor: 'white',
};
return (
<TouchableHighlight underlayColor="#eee" onPress={onPress}>
<View style={[view, style]}>
{children}
{Platform.OS === 'ios' &&
!noArrow && (
<View style={iconView}>
<Icon name="arrow" style={icon} />
</View>
)}
</View>
</TouchableHighlight>
);
};

Remove flex: 1 from selectionStyle

Related

how to update state according to id?

I have a touchableopacity on each card where I want to setstate of expand to true, but I want to do it according to the id, so that state of only one changes, any idea how to do it using map()?
My code:
import React, {useState, useEffect} from 'react';
import {
SafeAreaView,
Text,
Image,
ScrollView,
TouchableOpacity,
View,
} from 'react-native';
import axios from 'axios';
import {ROOT} from '../../../../ApiUrl';
import Icon from 'react-native-vector-icons/FontAwesome';
export default function VaccinationListScreen(props) {
const [expand, setExpand] = useState(false);
const [data, setData] = useState('');
let id = props.route.params.id;
const getData = () => {
let url = `some url`;
console.log('bbb');
axios
.get(url)
.then(function (res) {
console.log(res.data.content);
setData(res.data.content);
})
.catch(function (err) {
console.log(err);
});
};
useEffect(() => {
getData();
}, []);
return (
<SafeAreaView>
<ScrollView>
<TouchableOpacity style={{padding: 10}} onPress={()=>setExpand(true)}>
{data != undefined &&
data != null &&
data.map((item) => {
return (
<View
style={{
padding: 10,
backgroundColor: '#fff',
elevation: 3,
margin: '2%',
borderRadius: 5,
}}
key={item.id}>
<View style={{alignItems: 'flex-end'}}>
<Text style={{color: 'grey', fontSize: 12}}>
{item.display_date}
</Text>
</View>
<View style={{flexDirection: 'row'}}>
<View>
<Image
source={require('../../assets/atbirth.jpg')}
style={{height: 40, width: 50}}
resizeMode="contain"
/>
</View>
<View style={{flex: 1}}>
<View style={{flexDirection: 'row', flex: 1}}>
<Text
key={item.id}
style={{
fontFamily: 'Roboto',
fontSize: 18,
fontWeight: 'bold',
}}>
{item.name}
</Text>
</View>
<View style={{flexDirection: 'row', width: '30%'}}>
{item.vaccine_list.map((i) => {
return (
<View style={{flexDirection: 'row'}}>
<Text
numberOfLines={1}
ellipsizeMode="tail"
style={{fontFamily: 'Roboto', fontSize: 15}}>
{i.name},
</Text>
</View>
);
})}
</View>
</View>
</View>
<View style={{alignItems: 'flex-end', marginTop: '1%'}}>
<View style={{flexDirection: 'row'}}>
<Text
style={{
color: 'red',
fontSize: 14,
fontWeight: 'bold',
}}>
{item.child_vacc_status.text}
</Text>
<Icon
name="chevron-up"
color="red"
size={12}
style={{marginTop: '1%', marginLeft: '1%'}}
/>
</View>
</View>
</View>
);
})}
</TouchableOpacity>
</ScrollView>
</SafeAreaView>
);
}
Any suggestions would be great, do let mw know if anything else is required for better understanding
As i review your code <TouchableOpacity> wraps all of your cards at once not on each card set. If you implement your code that way if it's not impossible it will be difficult for you to reference each cards id and set the state of expand to true according to cards id.
My suggestion is to include <TouchableOpacity> to map() function nest so that it will be easy to reference each cards function.
I reproduce this specific problem and implement a solution in which I was able to set the state of expand to true according to each cards id.
You may click the sandbox link to see a demonstration.
https://codesandbox.io/s/accordingtoid-4px1w
Code in Sandbox:
import React, { useState, useEffect } from "react";
import {
SafeAreaView,
Text,
Image,
TouchableOpacity,
View
} from "react-native";
// import axios from 'axios';
// import {ROOT} from '../../../../ApiUrl';
// import Icon from "react-native-vector-icons/FontAwesome";
export default function VaccinationListScreen(props) {
const [expand, setExpand] = useState({});
const [data, setData] = useState([]);
// let id = props.route.params.id;
// const getData = () => {
// let url = `some url`;
// console.log('bbb');
// axios
// .get(url)
// .then(function (res) {
// console.log(res.data.content);
// setData(res.data.content);
// })
// .catch(function (err) {
// console.log(err);
// });
// };
// useEffect(() => {
// getData();
// }, []);
useEffect(() => {
// In order to simulate and reproduce the problem
// Assume that these are the data that you fetch from an API
const dataContent = [
{
id: 1,
name: "At Birth",
display_date: "02 May - 08 May 16",
vaccine_list: [
{ name: "BCG" },
{ name: "Hepatitis B" },
{ name: "OPV 0" }
],
child_vacc_status: { text: "Missed" }
},
{
id: 2,
name: "At 6 Weeks",
display_date: "02 May - 08 May 16",
vaccine_list: [
{ name: "IPV" },
{ name: "PCV" },
{ name: "Hepatitis b" },
{ name: "DTP" },
{ name: "HiB" },
{ name: "Rotavirus" }
],
child_vacc_status: { text: "Missed" }
}
];
setData(dataContent);
}, []);
function handleOnPress(id) {
setExpand((prev) => {
let toggleId;
if (prev[id]) {
toggleId = { [id]: false };
} else {
toggleId = { [id]: true };
}
return { ...toggleId };
});
}
useEffect(() => {
console.log(expand); // check console to see the value
}, [expand]);
return (
<SafeAreaView>
{data !== undefined &&
data !== null &&
data.map((item) => {
return (
<TouchableOpacity
key={item.id}
style={{
padding: 10
}}
onPress={() => handleOnPress(item.id)}
>
<View
style={{
padding: 10,
backgroundColor: expand[item.id] ? "lightgrey" : "#fff",
elevation: 3,
margin: "2%",
borderRadius: 5
}}
>
<View style={{ alignItems: "flex-end" }}>
<Text style={{ color: "grey", fontSize: 12 }}>
{item.display_date}
</Text>
</View>
<View style={{ flexDirection: "row" }}>
<View>
<Image
// source={require('../../assets/atbirth.jpg')}
style={{ height: 40, width: 50 }}
resizeMode="contain"
/>
</View>
<View style={{ flex: 1 }}>
<View style={{ flexDirection: "row", flex: 1 }}>
<Text
key={item.id}
style={{
fontFamily: "Roboto",
fontSize: 18,
fontWeight: "bold"
}}
>
{item.name}
</Text>
</View>
<View style={{ flexDirection: "row", width: "30%" }}>
{item.vaccine_list.map((item, i) => {
return (
<View key={i} style={{ flexDirection: "row" }}>
<Text
numberOfLines={1}
ellipsizeMode="tail"
style={{ fontFamily: "Roboto", fontSize: 15 }}
>
{item.name},
</Text>
</View>
);
})}
</View>
</View>
</View>
<View style={{ alignItems: "flex-end", marginTop: "1%" }}>
<View style={{ flexDirection: "row" }}>
<Text
style={{
color: "red",
fontSize: 14,
fontWeight: "bold"
}}
>
{item.child_vacc_status.text}
</Text>
</View>
</View>
</View>
</TouchableOpacity>
);
})}
</SafeAreaView>
);
}
I haven't tested the code to work correctly, but you could try something similar. You could create a separate component for the items and set a status for each of them.
export default function VaccinationListScreen(props) {
const [expand, setExpand] = useState(false);
const [data, setData] = useState("");
const VaccinationListItem = (item) => {
const [expand, setExpand] = useState(false);
return (
<TouchableOpacity style={{ padding: 10 }} onPress={() => setExpand(true)}>
<View
style={{
padding: 10,
backgroundColor: "#fff",
elevation: 3,
margin: "2%",
borderRadius: 5,
}}
key={item.id}
>
<View style={{ alignItems: "flex-end" }}>
<Text style={{ color: "grey", fontSize: 12 }}>
{item.display_date}
</Text>
</View>
<View style={{ flexDirection: "row" }}>
<View>
<Image
source={require("../../assets/atbirth.jpg")}
style={{ height: 40, width: 50 }}
resizeMode="contain"
/>
</View>
<View style={{ flex: 1 }}>
<View style={{ flexDirection: "row", flex: 1 }}>
<Text
key={item.id}
style={{
fontFamily: "Roboto",
fontSize: 18,
fontWeight: "bold",
}}
>
{item.name}
</Text>
</View>
<View style={{ flexDirection: "row", width: "30%" }}>
{item.vaccine_list.map((i) => {
return (
<View style={{ flexDirection: "row" }}>
<Text
numberOfLines={1}
ellipsizeMode="tail"
style={{ fontFamily: "Roboto", fontSize: 15 }}
>
{i.name},
</Text>
</View>
);
})}
</View>
</View>
</View>
<View style={{ alignItems: "flex-end", marginTop: "1%" }}>
<View style={{ flexDirection: "row" }}>
<Text
style={{
color: "red",
fontSize: 14,
fontWeight: "bold",
}}
>
{item.child_vacc_status.text}
</Text>
<Icon
name="chevron-up"
color="red"
size={12}
style={{ marginTop: "1%", marginLeft: "1%" }}
/>
</View>
</View>
</View>
</TouchableOpacity>
);
};
return (
<SafeAreaView>
<ScrollView>
{data != undefined &&
data != null &&
data.map((item) => {
VaccinationListItem(item);
})}
</ScrollView>
</SafeAreaView>
);
}
Generally if you want to toggle any single element you should store its id in expand (instead of a boolean), and simply check when rendering the array if any specific element's id matches, i.e. element.id === expand. When any new element is touched, pop its id in there, if the id is already there, set to null to collapse.
export default function VaccinationListScreen(props) {
const [expandId, setExpandId] = useState(null); // <-- stores null or id, initially null
...
// Create curried handler to set/toggle expand id
const expandHandler = (id) => () =>
setExpandId((oldId) => (oldId === id ? null : id));
return (
<SafeAreaView>
<ScrollView>
{data &&
data.map((item) => {
return (
<View
...
key={item.id}
>
<TouchableOpacity
style={{ padding: 10 }}
onPress={expandHandler(item.id)} // <-- attach callback and pass id
>
...
</TouchableOpacity>
{item.id === expandId && ( // <-- check if id match expand id
<ExpandComponent />
)}
</View>
);
})}
</ScrollView>
</SafeAreaView>
);
}

how to set modal visible according to id?

I have a map() data each of which has touchableopacity that should set the state of modal visible to true, but am unable to do it.
Could anyone let me know a way to set the state according to id?
ParentComponent:
export default function ExpandedVaccineComponent(props) {
const {navigation} = props;
const [note, setNote] = useState({});
const [addNoteText, setAddNoteText] = useState('');
const [modalVisible, setModalVisible] = useState(false);
const [selectedItem,setSelectedItem]=useState(null);
const [demo, setDemo] = useState(false);
let id = props.id;
return (
<View
style={{
backgroundColor: '#fff',
elevation: 3,
margin: '2%',
borderRadius: 5,
}}>
<View style={{marginTop: '2%'}}>
{props.item.vaccine_list.map((i) => {
return (
<View style={{flex: 1}}>
<View style={{flexDirection: 'row'}}>
<TouchableOpacity onPress={() => setModalVisible(true)}>
<Icon name="calendar" size={15} />
</TouchableOpacity>
<View>
<Modal
animationType="fade"
transparent={true}
visible={modalVisible}>
<View
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
borderRadius: 20,
}}>
<CalenderModal
item={props.item}
modalVisible={modalVisible}
item={i}
id={id}
/>
<View
style={{
flexDirection: 'row',
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
width: '72%',
}}>
<TouchableOpacity
style={{
flex: 1,
borderTopColor: '#C0C0C0',
borderTopWidth: 1,
borderRightColor: '#C0C0C0',
borderRightWidth: 1,
justifyContent: 'center',
alignItems: 'center',
padding: 10,
}}
onPress={() => setModalVisible(!modalVisible)}>
<Text
style={{
fontFamily: 'Roboto',
fontSize: 17,
fontWeight: 'bold',
color: '#2D7AFA',
}}>
Cancel
</Text>
</TouchableOpacity>
<TouchableOpacity
style={{
flex: 1,
borderTopColor: '#C0C0C0',
borderTopWidth: 1,
borderLeftColor: '#C0C0C0',
borderLeftWidth: 1,
justifyContent: 'center',
alignItems: 'center',
padding: 10,
}}>
<Text
style={{
fontFamily: 'Roboto',
fontSize: 17,
fontWeight: 'bold',
color: '#2D7AFA',
}}>
Save
</Text>
</TouchableOpacity>
</View>
</View>
</Modal>
</View>
<View style={{marginLeft: '10%', width: '30%'}}>
<View>
<View style={{flexDirection: 'row'}}>
<Text
style={{
fontFamily: 'Roboto',
fontSize: 14,
color: '#000',
}}>
{i.name}
</Text>
<Text
style={{
fontFamily: 'Roboto',
color: '#000',
opacity: 0.5,
}}>
(Dose{i.dose}/3)
</Text>
</View>
<Text
numberOfLines={2}
ellipsizeMode="tail"
style={{
fontFamily: 'Roboto',
fontSize: 14,
lineHeight: 14,
color: '#000',
opacity: 0.5,
}}>
{i.protects_against}
</Text>
</View>
</View>
<View style={{marginLeft: '30%'}}>
<Text>{i.child_vacc_status.text}</Text>
<Text>16 Aug,2020</Text>
</View>
</View>
</View>
);
})}
</View>
</View>
);
}
CalenderModal component:
import React, {useState} from 'react';
import {View, Text, StyleSheet, TouchableOpacity, Image} from 'react-native';
import Icon from 'react-native-vector-icons/FontAwesome';
import DatePicker from 'react-native-datepicker';
import axios from 'axios';
import {ROOT} from '../../../ApiUrl';
export default function CalenderModal(props) {
const [date, setDate] = useState('2016-05-15');
const [vaccinatedOn, setVaccinatedOn] = useState(null);
const [reminder, setReminder] = useState(1);
const [toggle, setToggle] = useState(null);
const [modalVisible, setModalVisible] = useState(null);
const reminderSet = () => {
setReminder(6);
setToggle(6);
};
const vaccinationSet = () => {
setVaccinatedOn(1);
setToggle(1);
};
const data = props.item;
const id = props.id;
const SaveData = () => {
let url = `some url`;
axios({
method: 'POST',
url: url,
data: {
child_id: id,
event_date: date,
status: toggle,
vaccine_id: data.id,
},
headers: {
'content-type': 'application/json',
},
})
.then(function (res) {
console.log('RES', res);
if (res.data.code == 200) {
navigation.navigate('consultationHome', {res: res});
}
})
.catch(function (err) {
console.log('ERR', err);
});
};
return (
<View>
<View style={styles.modalView}>
<Text>{props.item.name}</Text>
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
marginTop: '5%',
}}>
{reminder == 6 && toggle == 6 ? (
<TouchableOpacity style={{flexDirection: 'row'}}>
<Icon
name="circle"
size={17}
color="pink"
style={{marginTop: '2%', paddingRight: '1%'}}
/>
<Text
style={{
fontFamily: 'Roboto',
fontSize: 17,
color: '#000',
}}>
Set reminder
</Text>
</TouchableOpacity>
) : (
<TouchableOpacity
style={{flexDirection: 'row'}}
onPress={() => reminderSet()}>
<Icon
name="circle-o"
size={17}
color="#000"
style={{marginTop: '2%', paddingRight: '1%'}}
/>
<Text
style={{
fontFamily: 'Roboto',
fontSize: 17,
color: '#000',
}}>
Set reminder
</Text>
</TouchableOpacity>
)}
{vaccinatedOn == 1 && toggle == 1 ? (
<TouchableOpacity style={{flexDirection: 'row'}}>
<Icon
name="circle"
size={17}
color="pink"
style={{marginTop: '2%', paddingRight: '1%'}}
/>
<Text
style={{
fontFamily: 'Roboto',
fontSize: 17,
color: '#000',
}}>
Vaccinated on
</Text>
</TouchableOpacity>
) : (
<TouchableOpacity
style={{flexDirection: 'row'}}
onPress={() => vaccinationSet()}>
<Icon
name="circle-o"
size={17}
color="#000"
style={{marginTop: '2%', paddingRight: '1%'}}
/>
<Text
style={{
fontFamily: 'Roboto',
fontSize: 17,
color: '#000',
}}>
Vaccinated on
</Text>
</TouchableOpacity>
)}
</View>
<DatePicker
style={{width: 200, marginTop: '5%'}}
date={date}
mode="date"
placeholder="select date"
format="YYYY-MM-DD"
minDate="2016-05-01"
maxDate="2016-06-01"
confirmBtnText="Confirm"
cancelBtnText="Cancel"
customStyles={{
dateIcon: {
position: 'absolute',
left: 0,
top: 4,
marginLeft: 0,
},
dateInput: {
marginLeft: 36,
},
// ... You can check the source to find the other keys.
}}
onDateChange={(date) => {
setDate(date);
}}
/>
{console.log('DATE', date)}
</View>
</View>
);
}
const styles = StyleSheet.create({
modalView: {
backgroundColor: 'white',
padding: 20,
},
});
Any suggestion would be great, please let me know if anything else is required for better understanding.
you might want to try setting up your onPress similar to the RN documentation for TouchableOpacity (https://reactnative.dev/docs/touchableopacity.html you also may want to consider switching to Pressable for future proofing purposes). You can do
const onPress = () => setModalVisible(true);
<TouchableOpacity onPress={onPress}>

How to append new images to the array using react native image crop picker?

Hi, I am using react-native-image-crop-picker to overcome the above-shown module to select images from the gallery and display it in react native app, but I also want to click on add photo and again select images from the gallery and append them to the previous array of photos, am unable to figure that out.
This is the exact code that I have written to achieve the above-shown behavior, what should I change or add to perform the append feature?
import React, {useEffect, useState} from 'react';
import {
View,
Text,
StyleSheet,
ScrollView,
Image,
TouchableOpacity,
Dimensions,
FlatList,
} from 'react-native';
import Icon from 'react-native-vector-icons/FontAwesome';
import ImagePicker from 'react-native-image-crop-picker';
const deviceWidth = Dimensions.get('window').width;
const deviceHeight = Dimensions.get('window').height;
const App = () => {
const [photos, setAddPhotos] = useState(null);
const [photo, setAddphoto] = useState(null);
const handleChoosePhoto = () => {
ImagePicker.openPicker({
multiple: true,
waitAnimationEnd: false,
includeExif: true,
forceJpg: true,
})
.then((images) => {
setAddphoto(null);
setAddPhotos(
images.map((i) => {
console.log('recieved image', i);
return {
uri: i.path,
// width: i.width,
// height: i.height,
width: 185,
height: 128,
mime: i.mime,
};
}),
);
})
.catch((e) => alert(e));
};
const renderImage = (image) => {
return (
<Image
style={{
width: 185,
height: 128,
resizeMode: 'contain',
marginTop: 1,
}}
source={image}
/>
);
};
const renderAsset = (image) => {
return renderImage(image);
};
return (
<View style={{flex: 1}}>
{console.log('PHOTOS', photos)}
{photos === null ? (
<View style={{flex: 1}}>
<View style={Styles.headerWrapper}>
<View
style={{flexDirection: 'row', justifyContent: 'space-between'}}>
<Icon name="angle-left" size={30} />
<TouchableOpacity style={{right: '10%', top: '2%'}}>
<Text style={{fontSize: 15, fontWeight: 'bold'}}>
SAVE AND EXIT
</Text>
</TouchableOpacity>
</View>
</View>
<ScrollView>
<Text style={Styles.headerText}>Add photos to your listing</Text>
<Text style={Styles.subHeader}>
Photos help guests imagine staying in your place. You can start
with one and add more after you publish.
</Text>
<View style={Styles.container}>
<TouchableOpacity onPress={() => handleChoosePhoto()}>
<View
style={{
backgroundColor: '#20B2AA',
width: 150,
height: 40,
borderRadius: 5,
justifyContent: 'center',
}}>
<Text
style={{
color: '#fff',
textAlign: 'center',
fontSize: 15,
fontWeight: 'bold',
}}>
Add photos
</Text>
</View>
</TouchableOpacity>
</View>
</ScrollView>
<TouchableOpacity
style={{
alignSelf: 'flex-end',
right: '5%',
position: 'absolute',
bottom: 10,
}}>
<View
style={{
borderColor: '#20B2AA',
borderWidth: 1,
alignSelf: 'flex-end',
padding: 10,
}}>
<Text
style={{fontSize: 15, fontWeight: 'bold', color: '#20B2AA'}}>
Skip For Now
</Text>
</View>
</TouchableOpacity>
</View>
) : (
<>
<View style={{flex: 1}}>
<View style={Styles.headerWrapper}>
<View
style={{flexDirection: 'row', justifyContent: 'space-between'}}>
<Icon name="angle-left" size={30} />
<TouchableOpacity style={{right: '10%', top: '2%'}}>
<Text style={{fontSize: 15, fontWeight: 'bold'}}>
SAVE AND EXIT
</Text>
</TouchableOpacity>
</View>
</View>
<ScrollView>
<View style={{flex: 1, flexWrap: 'wrap', flexDirection: 'row'}}>
{photos
? photos.map((i) => (
<View
style={{
// width: 185, height: 128,
// width:'50%',
flexBasis: '33.33%',
}}
key={i.uri}>
{renderAsset(i)}
</View>
))
: null}
</View>
</ScrollView>
<TouchableOpacity
style={{
alignSelf: 'flex-end',
right: '5%',
position: 'absolute',
bottom: 10,
}}>
<View
style={{
backgroundColor: '#20B2AA',
alignSelf: 'flex-end',
padding: 10,
}}>
<Text style={{fontSize: 15, fontWeight: 'bold', color: '#FFF'}}>
NEXT
</Text>
</View>
</TouchableOpacity>
</View>
</>
)}
</View>
);
};
export default App;
const Styles = StyleSheet.create({
headerWrapper: {
width: deviceWidth,
paddingLeft: 24,
paddingTop: 10,
paddingBottom: 10,
},
headerText: {
fontWeight: 'bold',
fontSize: 28,
paddingLeft: 24,
},
container: {
padding: 24,
},
subHeader: {
paddingLeft: 24,
fontSize: 17,
paddingTop: 24,
paddingRight: 24,
},
});
Please let me know if anything else is required for better understanding, thank you.
You only need to take the prevState in setAddPhotos
setAddPhotos((lastPhotos) => {
const imagesMap = images.map((i) => {
return {
uri: i.path,
width: i.width,
height: i.height,
mime: i.mime,
};
});
return [...lastPhotos, ...imagesMap];
});

React Native how to create a delete button that deletes a different element as well as itself

Look at my code below please I am trying to find a way to make a delete button but i am very new to react native, i have been trying to do it for the past few hours.
import React, { useState } from 'react';
import { StyleSheet, FlatList, Text, View, Image, TextInput, Button, Keyboard, TouchableOpacity, CheckBox } from 'react-native';
import Interactable from 'react-native-interactable';
export default function App()
const [enteredGoal, setEnteredGoal] = useState('');
const [courseGoals, setCourseGoals] = useState([]);
const goalInputHandler = (enteredText) => {
setEnteredGoal(enteredText);
};
const addGoalHandler = () => {
if (enteredGoal.length > 0) {
setCourseGoals(currentGoals => [...currentGoals, enteredGoal])
} else {
alert("You have to write something!")
}
}
return (
<View style={styles.container}>
<View style={styles.topPart}></View>
<View style={styles.navBar}>
<Image source={require('./assets/baseline_menu_black_18dp.png/')} />
<Text style={styles.heading}> Grocery List </Text>
</View>
<View style={styles.body}>
<TextInput
style={styles.textInput}
placeholder='Groceries'
maxLength={20}
onBlur={Keyboard.dismiss}
value={enteredGoal}
onChangeText={goalInputHandler}
/>
<View style={styles.inputContainer}>
<TouchableOpacity style={styles.saveButton}>
<Button title="ADD" onPress={addGoalHandler} color="#FFFFFF" style={styles.saveButtonText} />
</TouchableOpacity>
</View>
<View style={styles.container}>
<FlatList
data={courseGoals}
renderItem={itemData => (
<View style={styles.groceryItem} >
<Text style={styles.groceryItemText}>{itemData.item}</Text>
<Text style={styles.groceryItemDelete}>X</Text>
</View>
)}
/>
</View>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
topPart: {
height: '3%',
backgroundColor: '#5498A7',
},
navBar: {
height: '10%',
backgroundColor: '#5498A7',
elevation: 3,
paddingHorizontal: 15,
flexDirection: 'row',
alignItems: 'center',
},
body: {
backgroundColor: '#edebe9',
height: '100%',
flex: 1
},
heading: {
fontWeight: "bold",
justifyContent: 'center',
paddingLeft: '13%',
fontSize: 25,
color: '#d6d4d3'
},
textInput: {
borderColor: '#CCCCCC',
borderTopWidth: 1,
borderBottomWidth: 1,
height: 50,
fontSize: 25,
paddingLeft: 20,
paddingRight: 20
},
saveButton: {
borderWidth: 1,
borderColor: '#5498A7',
backgroundColor: '#5498A7',
padding: 15,
margin: 5,
},
saveButtonText: {
color: '#FFFFFF',
fontSize: 20,
textAlign: 'center'
},
groceryItem: {
borderWidth: 1,
borderColor: 'black',
backgroundColor: '#6A686B',
padding: 15,
margin: 5,
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between'
},
groceryItemText: {
color: '#d6d4d3',
},
groceryItemDelete: {
color: 'red',
fontWeight: 'bold',
fontSize: 20
}
});
I hope you guys can find a solution I will keep u guys updated on my progress, I am constantly looking for answers but i don't really understand how to make the delete (X) work and to make it delete a different element, if you know a way to make work better just let me know i would appreciate it a lot
You have to send index to delete function.
renderItem={(itemData,index) => (
<View style={styles.groceryItem} >
<Text style={styles.groceryItemText}>{itemData.item}</Text>
<Text style={styles.groceryItemDelete.bind(index)}>X</Text>
</View>
and example delete function :
groceryItemDelete(index){
setCourseGoals(currentGoals.splice(index,1))
}
You need to implement the delete method and add an onPress event:
renderItem={(itemData, idx) => (
<View style={styles.groceryItem} >
<Text style={styles.groceryItemText}>{itemData.item}</Text>
<Text style={styles.groceryItemDelete} onPress={() => deleteItem(idx)}>X</Text>
</View>
)}
const deleteItem = idx => {
const clonedGoals = [...courseGoals]
clonedGoals.splice(idx, 1)
setCourseGoals(clonedGoals)
}

take button in center of FlatList footer

I'm facing an issue that button at bottom of FLatList's footer(here ListFooterComponent). I tried all solutions but I failed.
My output https://i.stack.imgur.com/Hn4PW.jpg
My code
_renderItem(rowData) {
return(
<View style={{ flex: 1}}>
<View style={s.cate_detail_box}>
<TouchableOpacity activeOpacity={0.9} style={{height: 190}}>
<Image source={{uri: rowData.item.images[0].src}} style={s.img}/>
</TouchableOpacity>
<View style={{padding: 5}}>
<View activeOpacity={0.9} style={{flexDirection: 'row', justifyContent: 'space-between'}}>
<View>
<CapitalizedText style={s.cate_detail_title}>{rowData.item.title}</CapitalizedText>
<Text style={s.cate_detail_price}>{'₹' + rowData.item.variants[0].price}</Text>
</View>
<TouchableOpacity activeOpacity={0.7} >
<Icon size={icon_size} color="#aaa" name="turned-in-not" />
</TouchableOpacity>
</View>
</View>
</View>
</View>
);
}
_render_Footer = () => {
return (
<View style = { s.footerStyle }>
<TouchableOpacity
activeOpacity = { 0.7 }
style = { s.btn_load_more }
onPress = { this.fetch_more_data_from_server }
>
<Text style = { s.btn_load_more_txt }>Load More</Text>
</TouchableOpacity>
</View>
)
}
render() {
return(
<ScrollView showsVerticsalScrollIndicator={false} style={s.category_detail_scroll} contentContainerStyle={{ flexGrow: 1}}>
<View>
{
this.state.product_detail.length <= 0 ?
<ActivityIndicator color = '#bc2b78' size = "large" style={{alignItems: 'center', justifyContent: 'center'}} />
:
<FlatList
contentContainerStyle={s.list}
keyExtractor = {( item, index ) => index.toString() }
data = { this.state.product_detail }
renderItem = {(rowData) => this._renderItem(rowData)}
ListFooterComponent = { this._render_Footer }
/>
}
</View>
</ScrollView>
);
}
CSS
cate_detail_box: {
margin: 2,
width: 180,
backgroundColor: '#fff',
borderWidth: 1,
borderColor: '#aaa',
},
cate_detail_title: {
color: '#666',
fontSize: font_small,
},
cate_detail_price: {
fontSize: 15,
color: '#666',
justifyContent: 'center',
alignItems: 'center',
},
category_detail_scroll: {
flex: 1,
backgroundColor: 'rgba(243,229,245, 0.6)',
},
footerStyle:{
padding: 7,
width: '100%',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#000',
},
btn_load_more: {
padding: 7,
backgroundColor: '#F44336',
borderRadius: 5,
},
Any help is appreciated.
Thank you.
Please apply this
footerStyle: {
flex: 1
alignItems: 'center'
}
And remove all styles for TouchableOpacity and Text

Resources