Adding checkbox in between text description in react native - flexbox

I have a view where I display a Heading and details which I get from server as below.
Now, in the question description there is a tag __CB__ which I need to replace with the checkbox, so, instead of that tag there will be a checkbox and rest of the text will continue as usual. I have separated the text based on tag and placed a checkbox in between but I haven't been able to align the view, either it gets arranged columnwise or if I try to arrange in row the text doesn't continue. Here is what I've tried.
Try 1:
<ScrollView
style={styles.scrollStyle}
scrollEnabled={scrollEnabled}
onContentSizeChange={this.onContentSizeChange}
>
<View style={styles.checkBoxTextContainer}>
<Text style={styles.questionText}>{questionText1}</Text>
<CheckBox
style={styles.checkboxStyle}
onClick={this.checkboxClick}
isChecked={this.state.isChecked}
checkedImage={<Image source={Images.checkBoxTick} />}
unCheckedImage={<Image source={Images.checkBoxEmpty} />}
// leftText={questionText1}
// rightText={questionText2}
/>
<Text style={styles.questionText}>{questionText2}</Text>
</View>
</ScrollView>
Styles
checkBoxTextContainer: {
flex: 1,
flexDirection: "row"
},
checkBoxStyle: {
width: 20,
height: 20
}
Result:
Try 2:
<ScrollView
style={styles.scrollStyle}
scrollEnabled={scrollEnabled}
onContentSizeChange={this.onContentSizeChange}
>
<Text style={styles.questionText}>{questionText1}</Text>
<CheckBox
style={styles.checkboxStyle}
onClick={this.checkboxClick}
isChecked={this.state.isChecked}
checkedImage={<Image source={Images.checkBoxTick} />}
unCheckedImage={<Image source={Images.checkBoxEmpty} />}
// leftText={questionText1}
// rightText={questionText2}
/>
<Text style={styles.questionText}>{questionText2}</Text>
</ScrollView>
Result:
I need the checkbox to continue in between text like the tag in my original image. Any help is appreciated.

Below is sample working code for your scenario.
import React, { Component } from 'react'
import { View, Text, StyleSheet } from 'react-native'
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap'
},
cb: {
width: 10,
height: 10,
borderWidth: 2,
borderRadius: 2,
borderColor: 'red',
marginTop: 4,
marginHorizontal: 3,
}
})
const sampleData = [ 'Lorem', 'ipsum', 'dolor', 'sit', 'amet',
'CB',
'consectetur', 'adipiscing', 'elit.', 'Curabitur',
'CB',
' nunc', 'vel', 'scelerisque', 'tempus.', 'CB', 'Morbi', 'luc', 'abcd', 'xyzw'
]
const CheckBox = () => (
<View style={styles.cb} />
)
export default class CheckText extends Component {
renderData = (data) => {
const views = data.map((item) => {
if (item === 'CB') { return <CheckBox />}
return (<Text>{item}</Text>)
})
return views
}
render() {
return (
<View style={styles.container}>
{this.renderData(sampleData)}
</View>
)
}
}
And this is snapshot of output
Note:
I have parsed the text into array of strings. This is the key logic here. The way you decide to tokenize your input text will affect the rendering of your component. When I tried long strings as token, flexWrap: 'wrap' didn't work properly. See this issue for more details. Tokenizing into single words may do the job.

try to wrap the Text and Checkbox into <Text> tag.
Please try below solution. It may help you.
<ScrollView
style={styles.scrollStyle}
scrollEnabled={scrollEnabled}
onContentSizeChange={this.onContentSizeChange}
>
<View style={{
width:'100%',
flexDirection: "row"
}}>
// wrap into text tag
<Text>
// add space after first text
<Text style={styles.questionText}>{questionText1+" "}</Text>
<CheckBox
style={styles.checkboxStyle}
onClick={this.checkboxClick}
isChecked={this.state.isChecked}
checkedImage={<Image source={Images.checkBoxTick} />}
unCheckedImage={<Image source={Images.checkBoxEmpty} />}
/>
// add space before second text
<Text style={styles.questionText}>{" "+questionText2}</Text>
</Text>
</View>
</ScrollView>

Related

in react native how i can change background color for every view element independent

for every view element independent when i press them without effect other views and save pressed state so next time i can find what ipressed still pressed and i can change color of other view when ipress them without lose stat of preview view
the problem is when i press one from two task the other task also change her background color
import React, { useState } from 'react';
import {
SafeAreaView,
View,
FlatList,
StyleSheet,
Text,
TouchableOpacity,
} from 'react-native';
function App() {
const [changBack,backgroundColor]=useState('green')
function changIt() {
backgroundColor('red');
}
const DATA1 = 'Task one';
const DATA2 = 'Task two';
return (
<View>
<TouchableOpacity
style={{
flex: 1,
backgroundColor:changBack,
padding: 20,
}}
onPress={changIt}>
<View>
<Text>{DATA1}</Text>
</View>
</TouchableOpacity>
<TouchableOpacity
style={{
flex: 1,
backgroundColor:changBack,
padding: 20,
}}
onPress={changIt}>
<View>
<Text>{DATA2}</Text>
</View>
</TouchableOpacity>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection:'column',
textAlign:'right',
justifyContent:'space-evenly',
},
});
export default App;
Brother I notice you passed backgroundColor on Style for <TouchableOpacity> so definitely it won't work. backgroundColor is applicable for <View> only but not for TouchableOpcacity.
Do something like this ~
<View>
<View style={{backgroundColor:changBack}}>
<TouchableOpacity onPress={changeIt}>
<View>
<Text>Heyya</Text>
</View>
</ToucableOpacity>
</View>
</View>
or this,
<View>
<TouchableOpacity onPress={changeIt}>
<View style={{backgroundColor:changBack}}>
<Text>Heyya</Text>
</View>
</ToucableOpacity>
</View>

Slash "/" symbol added in data list after each order

im just a begineer with react native and i have this problem :
im working on a food app where you can check food items with checkbox , for each food checked it will be automatically stored in array like this :
const data = [
{
"Viande": Viande,
"Sauce": Sauce,
"Extra": Extra,
"Boisson": Boisson,
"Supplements": Supplements,
}
]
AsyncStorage.getItem("STORAGE_Data").then((datacart) => {
console.log("datacart = ", datacart)
if (datacart !== null) {
const cart = JSON.parse(datacart)
cart.push(datacart)
AsyncStorage.setItem("STORAGE_Data", JSON.stringify(cart))
console.log("cart 2:",JSON.stringify(cart))
}else{
AsyncStorage.setItem("STORAGE_Data", JSON.stringify(data))
console.log("else : " , data)
}
console.log("DATA:", JSON.stringify(data))
alert("done")
}).catch((error) => {
alert(error)
})
};
Everything works properly so far , im using asyncstorage to save all the data and get them in my Cart class where i have all the data , im using map() function to create a view for each time i add new food :
constructor(props) {
super(props);
this.state = {
dataCart: [],
};
}
componentDidMount()
{
try {
AsyncStorage.getItem('STORAGE_Data').then((cart) => {
if (cart !== null) {
const cartfood = JSON.parse(cart)
console.log(cart)
this.setState({ dataCart: cartfood })
console.log(JSON.stringify(this.state.dataCart))
}
})
}
catch (error) {
console.log(error)
}
}
and here is my map() function
{
this.state.dataCart.map((item , i) => {
return (
<View style={styles.rectangle}>
<Image style={{ width: normalize(200), height: normalize(64), alignSelf: 'center', marginLeft: normalize(-40) }} source={require("../assets/Tacos-M.png")}></Image>
<View>
<Text style={{ alignSelf: 'center', fontSize: normalize(17), marginTop: normalize(10) }} key={i}>{item.Viande}</Text>
<View style={{ flexDirection: 'row', alignSelf: 'center', marginTop: normalize(40) }}>
<TouchableOpacity onPress={() => alert('ok')}><Feather name="minus" color={'#D05A0B'} size={normalize(20)} style={styles.btnMoin} /></TouchableOpacity>
<Text style={{ fontSize: normalize(15), marginLeft: normalize(15) }}>2</Text>
<TouchableOpacity><Feather name="plus" color={'#D05A0B'} size={normalize(20)} style={styles.btnPlus} /></TouchableOpacity>
</View>
</View>
<View>
<TouchableOpacity><Feather name="x" color={'#D05A0B'} size={25} style={{ alignSelf: 'flex-start', marginTop: normalize(20), marginLeft: normalize(40), }} /></TouchableOpacity>
<Text style={{ fontSize: normalize(15), alignSelf: 'center', marginTop: normalize(27), marginLeft: normalize(35) }}>14 DT</Text>
</View>
</View>
)
})
}
So the problem is i can make a food list as a first order , but in the second order after i change the food choice my map() function doest not give food name like this :
it returns an empty text instead in the second order view
so tired console.log() to see if im getting real data or no and suddenly i figured out whenever i add another order the food list becomes like this :
the slash "/" symbol added for each order , i have no clue how but is there any solution to avoid these kind of symbols and get a clean and proper list for my data ?
If you look in your AsyncStorage.getItem callback, you'll see that you're doing:
cart.push(datacart)
meaning you're pushing your stringified cart onto your cart and then setting it back into AsyncStorage, when you probably want to be doing:
cart.push(data)
Edit:
Actually, you probably want to set data equal to the object rather than an array containing the object, and then change your code to either push the object to the cart array in the if statement or set the AsyncStorage with a new array containing the object like so:
const data = {
"Viande": Viande,
"Sauce": Sauce,
"Extra": Extra,
"Boisson": Boisson,
"Supplements": Supplements,
}
...
if (...) {
const cart = JSON.parse(datacart)
cart.push(datacart)
AsyncStorage.setItem("STORAGE_Data", JSON.stringify(cart))
} else {
AsyncStorage.setItem("STORAGE_Data", JSON.stringify([data]))
}

React-Native display image or video on mime/file type condition

i am making a gallery app using React-Native with node.js , I got a data from Node.js api, i want to display files either image or video depends on file type in a FlatList , I don't know how to write the condition for that,
{items.file_Name == 'mp4' ? Video : image }
I am trying to use the above code but i don't know how to get the file name. So please check my code
export default class HomeScreen extends React.Component {
constructor(Props) {
super(Props);
this.state = {
error: null,
Posts:[
{"id":166,"user_id":1,"description":"7th test","file_Name":[VID-WA0005.mp4"]},
{"id":10,"user_id":3,"description":" 6th test","file_Name":["10.jpg", "12.jpg"]},
{"id":9,"user_id":2,"description":" 5th test","file_Name":["9.jpg", "14.jpg"]} ],
}
}
render() {
const { Posts } = this.state
return (
<View style={styles.container}>
<View style={styles.tabContent}>
<FlatList style={styles.list}
data={this.state.Posts}
keyExtractor={(data_posts, index) => {
return data_posts.id.toString();
}}
ItemSeparatorComponent={() => {
return (
<View style={styles.separator} />
)
}}
renderItem={(post, id) => {
const items = post.item;
return (
<View style={styles.card}>
<View style={styles.cardHeader}>
<Text style={styles.title}>{items.description}</Text>
</View>
<View style={styles.cardContent}>
{items.file_Name.split('.').reverse()[0] == 'mp4' ?
<Video
source={{ uri: "http://192.168.1.2:3200/" + items.file_Name }}
style={{ width: '100%', height: 600 }}
resizeMode="cover"
paused={this.state.paused}
controls={true}
volume={this.state.volume}
muted={this.state.muted}
paused={this.state.paused}
onLoad={this.onLoad}
onBuffer={this.onBuffer}
onProgress={this.onProgress}
/>
:
<Image style={styles.cardImage} source={{ uri: "http://192.168.1.2:3200/" + item.file_Name }} />
}
</View>
</View>
)
}}
/>
{/* Flatlist Ends*/}
</View>
</View>
);
}
}
````
I tried with condition like
````{items.file_Name.split('.').reverse()[0] == 'mp4' ? <Video /> : <image />}````
But its not working because i am unable to get the file type.
If anyone know how to get the file name and how to display either video or image please tell me .
You can use endsWith() function is used to check whether the given string ends with the characters of the specified string or not
{items.file_Name.toString().endsWith("mp4") ? Video : image }
Try this
{items.file_Name.split('.').pop() == 'mp4'?<Video /> : <image />}

Implemeting drawer in React native application

I just created my first interface in my React native app. I created a navbar in which there is a menu button to click, so the drawer opens and i can navigate from one screen to another. I intend to use this https://github.com/root-two/react-native-drawer.
I know i need to call open drawer in the menu button when click and here is the code i used, that displays an alert for now
openDrawer(){
this.drawer.open()
}
render() {
return (
<Container>
<Navbar
bgColor={'#C0C0C0'}
title={"Det globale flyktningbildet"}
titleColor="white"
left={{
icon: "ios-menu",
iconColor: "#FFFFFF",
// onPress: () => {alert('Toggle menu ')}
onPress: () => {this.props.openDrawer}
}}
/>
<Drawer
type="static"
// content={<ControlPanel />}
openDrawerOffset={100}
styles={{main: {shadowColor: "#000000", shadowOpacity: 0.4, shadowRadius: 3}}}
tweenHandler={Drawer.tweenPresets.parallax}>
</Drawer>
<View>
<Image
source = { require('./../images/image1_2.png')}
style={[styles.image1, {resizeMode: 'contain'}]}
/>
</View>
</Container>
);
}
So can you please help me implemet the drawer and navigate between different screens
Go through example code in github you will get the idea or you can refer https://stackoverflow.com/a/42748086/6423570
EDIT
You should wrap root container of the screen with Drawer component. The <ControlPanel /> component is the content that should be displayed in the drawer. You could use Touchable Components in the <ControlPanel /> and navigator to navigate between screens. And the openDrawer function is not a prop, call it as this.openDrawer
render() {
return (
<Drawer
type="static"
// content={<ControlPanel />}
openDrawerOffset={100}
styles={{
main: {
shadowColor: "#000000",
shadowOpacity: 0.4,
shadowRadius: 3
}
}}
tweenHandler={Drawer.tweenPresets.parallax}
>
<Container>
<Navbar
bgColor={'#C0C0C0'}
title={"Det globale flyktningbildet"}
titleColor="white"
left={{
icon: "ios-menu",
iconColor: "#FFFFFF",
// onPress: () => {alert('Toggle menu ')}
onPress: () => {this.openDrawer}
}}
/>
<View>
<Image
source = { require('./../images/image1_2.png')}
style={[styles.image1, {resizeMode: 'contain'}]}
/>
</View>
</Container>
</Drawer>
);
}

React native, children of ScrollView wont fill full height

So I have a horizontal scrollview at the top of the view. The ScrollView contains nodes that have a specified width. I then have a border on the bottom of the ScrollView, like you can see in this screen cap: http://i.imgur.com/pOV1JFP.png
As you can see the child nodes of the ScrollView at the top don't reach the border. However, if I change the ScrollView to a View with flexDirection: 'row', then the child nodes fill the height fine. I've tried changing a few properties on the scrollview, such as:
Setting padding:0 on contentContainerStyle
automaticallyAdjustContentInsets={false}
Changing the values of contentInsets directly
None of those seem to fix the issue.
The scrollview code & style:
var styles = StyleSheet.create({
nav: {
padding: 0,
marginTop: 30,
flex: 1,
borderBottomWidth: 1,
borderColor: '#000000'
}
});
<ScrollView
style={[{width: screen.width}, styles.nav]}
horizontal={true}
showsHorizontalScrollIndicator={true}
automaticallyAdjustContentInsets={false}>
{dayNavItems}
</ScrollView>
The child components (makes up dayNavItems)
const styles = StyleSheet.create({
container: {
paddingLeft: 15,
paddingRight: 15,
width: 50,
justifyContent: 'center'
},
odd: {
backgroundColor: '#ccc'
},
selected: {
backgroundColor: '#39b54a'
},
text: {
fontFamily: 'Optima'
}
});
class DayNavItem extends React.Component {
static propTypes = {
day: React.PropTypes.object.isRequired,
odd: React.PropTypes.bool,
selectDay: React.PropTypes.func.isRequired,
selected: React.PropTypes.bool
};
render() {
const d = new Date(this.props.day.created_at);
const viewStyles = [styles.container];
if (this.props.selected) {
viewStyles.push(styles.selected);
} else if (this.props.odd) {
viewStyles.push(styles.odd);
}
return (
<TouchableOpacity style={viewStyles} onPress={() => this.props.selectDay(this.props.day.uuid)}>
<View>
<Text style={styles.text}>{getMonth(d)}</Text>
<Text style={styles.text}>{d.getDate()}</Text>
</View>
</TouchableOpacity>
);
}
}
Adding contentContainerStyle={{flexGrow: 1}} will do the trick.
<ScrollView contentContainerStyle={{flexGrow: 1}}>
</ScrollView>
There is a property called contentContainerStyle for ScrollView. I just solved a similar issue where I set flex: 1 to the ScrollView's styles, ScrollView's contentContainerStyle, and the child View component.
The other answers are correct, but just to provide a clarifying example:
<ScrollView contentContainerStyle={{ flex: 1 }}>
{children}
</ScrollView>
Setting flex: 1 for ScrollView's contentContainerStyle property did the trick for me.
I always end up creating this component in all my projects:
import * as React from 'react'
import { ScrollView, ScrollViewProps, StyleSheet } from 'react-native'
export function FullHeightScrollView(
props: {
children: React.ReactNode
} & Omit<ScrollViewProps, 'contentContainerStyle'>
) {
return (
<ScrollView contentContainerStyle={styles.grow} {...props}>
{props.children}
</ScrollView>
)
}
const styles = StyleSheet.create({
grow: { flexGrow: 1 },
})
Use it in place of React Native's ScrollView.
If ScrollView is wrapped inside of a SafeAreaView, put flex: 1 on SafeAreaView, this did the trick for me after hours of debugging...
Parent:
Child (styles ScrollView I implemented has nothing to do with the current issue you reported):
I have made a simple package for those who just want, like me, a working out of the box ScrollView, without having to apply all the time the styles to make it work properly.
https://github.com/SrBrahma/pagescrollview
Usage:
import { PageScrollView } from 'pagescrollview';
<PageScrollView>
{/** Your contents */}
</PageScrollView>

Resources