React Native - Using State to Show/Hide Error Messages - javascript

Have been building a small Todo App on React Native based on a tutorial, I want to add an error message to the app if the user tries to save a list without any characters.
I have created the message, the state and a conditional for the state that is linked into a View containing the message. Although now, the user cannot save a list at all and the error message is constantly visible.
export default class AddTodoModal extends React.Component {
backgroundColors = ['#171219', '#225560', 'grey', '#EDF060', '#F0803C', '#310D20']
state = {
name: '',
color: this.backgroundColors[0],
errorState: false
};
createTodo = () => {
const {name, color} = this.state
if ({name}.length > 0) {
tempData.push({
name,
color,
todos: []
})
}
return
this.setState({name: ""})
this.props.closeModal();
}
renderColors() {
return this.backgroundColors.map(color => {
return (
<TouchableOpacity
key={color}
style={[styles.colorSelect, {backgroundColor: color}]}
onPress={() => this.setState({color})}
/>
);
});
}
render() {
return(
<KeyboardAvoidingView style={styles.container} behavior="padding">
<TouchableOpacity style={{position: 'absolute', top: 64, right: 32}} onPress={() => this.props.closeModal()}>
<AntDesign name="close" size={24} color={colours.blue} />
</TouchableOpacity>
<View visible={this.state.errorState}>
<Text style={styles.errorMessage}>Please Enter a Value!</Text>
</View>
<View style={{alignSelf: 'stretch', marginHorizontal: 32}}>
<Text style={styles.title}>Create Todo List</Text>
<TextInput style={styles.input} placeholder="List Name?" onChangeText={text => this.setState({ name: text })}/>
<View style={{flexDirection: 'row', justifyContent: 'space-between', marginTop: 12 }}>{this.renderColors()}</View>
<TouchableOpacity style={[styles.createList, { backgroundColor: this.state.color}]}
onPress={this.createTodo}>
<Text style={styles.buttonText}>Create List</Text>
</TouchableOpacity>
</View>
</KeyboardAvoidingView>
);
}
}
Update:
With the answer below, now error message appears but saving a list is blocked, even with a valid input.
export default class AddTodoModal extends React.Component {
backgroundColors = ['#171219', '#225560', 'grey', '#EDF060', '#F0803C', '#310D20']
state = {
name: '',
color: this.backgroundColors[0],
errorState: false
};
createTodo = () => {
const {name, color} = this.state
if ({name}.length > 0) {
tempData.push({
name,
color,
todos: []
})
this.setState({name: ""})
this.setState({errorState: false})
this.props.closeModal();
} else {
({name}.length = 0)
this.setState({errorState: true})
return
}
}
renderColors() {
return this.backgroundColors.map(color => {
return (
<TouchableOpacity
key={color}
style={[styles.colorSelect, {backgroundColor: color}]}
onPress={() => this.setState({color})}
/>
);
});
}
render() {
return(
<KeyboardAvoidingView style={styles.container} behavior="padding">
<TouchableOpacity style={{position: 'absolute', top: 64, right: 32}} onPress={() => this.props.closeModal()}>
<AntDesign name="close" size={24} color={colours.blue} />
</TouchableOpacity>
{this.state.errorState && <View>
<Text style={styles.errorMessage}>Please Enter a Value!</Text>
</View>}
<View style={{alignSelf: 'stretch', marginHorizontal: 32}}>
<Text style={styles.title}>Create Todo List</Text>
<TextInput style={styles.input} placeholder="List Name?" onChangeText={text => this.setState({ name: text })}/>
<View style={{flexDirection: 'row', justifyContent: 'space-between', marginTop: 12 }}>{this.renderColors()}</View>
<TouchableOpacity style={[styles.createList, { backgroundColor: this.state.color}]}
onPress={this.createTodo}>
<Text style={styles.buttonText}>Create List</Text>
</TouchableOpacity>
</View>
</KeyboardAvoidingView>
);
}
}
Update:
Fixing if statement for correct display of error message
createTodo = () => {
const {name, color} = this.state
let nameLength = this.state.name.length;
if (nameLength > 0) {
this.setState({errorState: false})
tempData.push({
name,
color,
todos: []
})
this.setState({name: ""})
this.props.closeModal();
} else {
(nameLength === 0)
this.setState({errorState: true})
}
}

You can use condtional rendering instead of visible property.
export default class AddTodoModal extends React.Component {
backgroundColors = ['#171219', '#225560', 'grey', '#EDF060', '#F0803C', '#310D20']
state = {
name: '',
color: this.backgroundColors[0],
errorState: false
};
createTodo = () => {
const {name, color} = this.state
if ({name}.length > 0) {
tempData.push({
name,
color,
todos: []
})
}
return
this.setState({name: ""})
this.props.closeModal();
}
renderColors() {
return this.backgroundColors.map(color => {
return (
<TouchableOpacity
key={color}
style={[styles.colorSelect, {backgroundColor: color}]}
onPress={() => this.setState({color})}
/>
);
});
}
render() {
return(
<KeyboardAvoidingView style={styles.container} behavior="padding">
<TouchableOpacity style={{position: 'absolute', top: 64, right: 32}} onPress={() => this.props.closeModal()}>
<AntDesign name="close" size={24} color={colours.blue} />
</TouchableOpacity>
{this.state.errorState && <View>
<Text style={styles.errorMessage}>Please Enter a Value!</Text>
</View>}
<View style={{alignSelf: 'stretch', marginHorizontal: 32}}>
<Text style={styles.title}>Create Todo List</Text>
<TextInput style={styles.input} placeholder="List Name?" onChangeText={text => this.setState({ name: text })}/>
<View style={{flexDirection: 'row', justifyContent: 'space-between', marginTop: 12 }}>{this.renderColors()}</View>
<TouchableOpacity style={[styles.createList, { backgroundColor: this.state.color}]}
onPress={this.createTodo}>
<Text style={styles.buttonText}>Create List</Text>
</TouchableOpacity>
</View>
</KeyboardAvoidingView>
);
}
}

you can implement like this
render() {
return(
<KeyboardAvoidingView style={styles.container} behavior="padding">
<TouchableOpacity style={{position: 'absolute', top: 64, right: 32}} onPress={() => this.props.closeModal()}>
<AntDesign name="close" size={24} color={colours.blue} />
</TouchableOpacity>
{this.state.errorState ? <View> <Text style={styles.errorMessage}>Please Enter a Value!</Text> </View> :null}
<View style={{alignSelf: 'stretch', marginHorizontal: 32}}>
<Text style={styles.title}>Create Todo List</Text>
<TextInput style={styles.input} placeholder="List Name?" onChangeText={text => this.setState({ name: text })}/>
<View style={{flexDirection: 'row', justifyContent: 'space-between', marginTop: 12 }}>{this.renderColors()}</View>
<TouchableOpacity style={[styles.createList, { backgroundColor: this.state.color}]}
onPress={this.createTodo}>
<Text style={styles.buttonText}>Create List</Text>
</TouchableOpacity>
</View>
</KeyboardAvoidingView>
);
}

Related

Flatlist scroll and scrollview scroll is not working inside modal

I am making filter modal for e-commerce application where I divided it into two component view one for left and one for right view. Where I am using flatlist for left view and scrollview for right.
I am trying achieve scroll on both side. I don't know why isn't working.Same code is working for different project without any problem.
I am unable to scroll on either side.
Attaching code snippet for same.
<Modal
animationType="slide"
transparent={true}
visible={this.state.modalVisible}
onRequestClose={() => {
this.setState({ modalVisible: !this.state.modalVisible });
}}
>
<View style={Style.general.centeredView}>
<View style={Style.general.modalView}>
<View style={Style.general.filterModal}>
<Text style={Style.general.filterModalHeading}>FILTERS</Text>
{this.state.filtersApplied.length > 0 ? (
<TouchableOpacity
style={{
alignSelf: "flex-end",
marginRight: 10,
paddingHorizontal: 10,
paddingVertical: 5,
borderWidth: 1,
borderColor: "#000",
borderRadius: 5,
}}
onPress={() => this.clearFiltersHandler()}
>
<Text>Clear Filters</Text>
</TouchableOpacity>
) : null}
</View>
<View style={Style.general.filterModalData}>
<View style={Style.general.filterModalDataLeftScroll}>
{/* {isFetching && modalVisible ? <Loader /> : null} */}
{this.state.filters && (
<FlatList
// contentContainerStyle={styles.listContainer}
data={this.state.filters}
// numColumns={2}
// onEndReached={() => fetchProducts(false, sortApplied)}
// onEndReachedThreshold={0.1}
keyExtractor={() =>
"_" + Math.random().toString(36).substr(2, 9)
}
renderItem={this.renderFilters}
// removeClippedSubviews
/>
)}
</View>
<ScrollView
style={{
flexGrow: 1,
width: "70%",
flexDirection: "column",
paddingHorizontal: 10,
}}
>
{this.state.activeFilterLabel !== "pf_p_price" &&
this.state.fliterLabel.map((values, i) => {
// console.log("values", values);
return (
<TouchableOpacity
key={i}
onPress={() => this.addFilterHandler(values)}
>
<View
style={Style.general.filterModalDataRightFilter}
>
<View
style={[
Style.general.filterBoxWrap,
{
backgroundColor:
this.state.filtersApplied.some(
(filter) => filter == values.key
)
? "#000"
: "#fff",
},
]}
>
<Icon name="check" size={11} color="#fff" />
</View>
<Text
style={{
fontFamily: "Futura",
fontSize: 12,
}}
>
{values.key}
</Text>
</View>
</TouchableOpacity>
);
})}
{this.state.activeFilterLabel === "pf_p_price" ? (
<View>
<Text>Hello</Text>
</View>
) : null}
</ScrollView>
</View>
{this.state.filterModalLoader ? (
<TouchableOpacity style={{ flex: 1 }} />
) : null}
<View style={Style.general.filterBtnFix}>
<TouchableWithoutFeedback
onPress={() => {
this.setState({ modalVisible: false });
}}
>
<View style={Style.general.filterBtnFixWrap}>
<Text style={Style.general.filterBtnFixWrapText}>
Close
</Text>
</View>
</TouchableWithoutFeedback>
<TouchableWithoutFeedback
onPress={() => {
this.setState({ modalVisible: false });
}}
>
<View style={Style.general.filterBtnFixWrap}>
<Text style={Style.general.filterBtnFixWrapText}>
Apply
</Text>
</View>
</TouchableWithoutFeedback>
</View>
</View>
</View>
</Modal>

How to filter data of a List using Checkboxes in Expo?

I am trying to implement a function in Expo to filter my data using checkboxes. I have already completed my checkboxes and designed them accordingly. The data to be filtered is pulled from the Firebase database and displayed in the form of a list on my page. I have also created a button for the filtering, which is used so that when a user clicks this button, the filtering takes place according to the selection of the respective boxes. Attached is a picture that shows what has already been implemented and below the code for it. I would be very grateful if someone could help me with this, as I am relatively new to React Native and have not found anything in this regard.
Thanks in advance
Anbieterliste-Screen
function MyCheckbox() {
const [checked, onChange] = useState(false);
function onCheckmarkPress() {
onChange(!checked);
}
return (
<Pressable
style={[styles.checkboxBase, checked && styles.checkboxChecked]}
onPress={onCheckmarkPress}>
{checked && <Ionicons name="checkmark" size={18} color="white" />}
</Pressable>
);
}
export default function Anbieter({ route, navigation }) {
//CONSTS WHICH WE GOT FROM THE HOMEPAGE AND DECLARATION
const { latitude, longitude, address } = route.params;
var getLat = latitude;
var getLong = longitude;
var getAddress = JSON.stringify(address);
const [restaurentList, setRestaurentList] = useState()
const [currentUsers, setCurrentUsers] = useState()
const [ranges, setRanges] = useState(1)
const [showRange, setShowRange] = useState(false)
// THIS IS A LIST WHICH DISPLAY ALL RESTAURANTS BY GETTING DATA IN PARAMS IN NAME OF DATA
const ListButton = ({ title, data }) => {
return (
<TouchableOpacity onPress={() => { navigation.navigate('Produktubersicht', { data }) }} style={[styles.itemContainer]}>
<Image source={{ uri: data.anbieterImg }} style={{ width: '90%', marginLeft: '5%', height: 160 }} />
<Text style={{ fontSize: 16, fontWeight: "bold", marginLeft: 20 }}>{data.firmenname}</Text>
<Text style={{ fontSize: 16, fontWeight: "bold", marginLeft: 20, width: '90%' }}>Adresse:
<Text style={{ fontSize: 16, fontWeight: 'normal' }}>{data.adresse}</Text>
</Text>
<Text style={{ fontSize: 16, fontWeight: "bold", marginLeft: 20, width: '90%' }}>Kategorie:
<Text style={{ fontSize: 16, fontWeight: 'normal' }}>{data.kategorie}</Text>
</Text>
</TouchableOpacity>
);
}
// THIS FUNCTION IS USE TO CALL ALL RESTAURANT FROM FIREBASE DATABASE
const getRestaurents = async () => {
let arr = []
// THIS IS FIREBASE API ALL DATA IS COMING FROM FIREBASE
var ar = await firebase.database().ref("/anbieter/").once("child_added", snapshot => {
var obj = snapshot.val();
obj.id = snapshot.key;
arr.push(obj);
});
// ALL DATA OF RESTAURANT IS STORING IN STATE HERE THEN FROM HERE ALL DATA WILL DISPLAY
setRestaurentList(arr)
}
var users = firebase.auth().currentUser;
useEffect(() => {
// WE CALL GET RESTAURANTS API HERE BECAUSE THIS USEEFFECT JUST CALL ONCE WHEN COMPONENT RENDER
console.log(users, 'users');
getRestaurents()
}, []);
// THIS IS SIGN OUT BUTTON , WHEN USER CLICK FOR SIGNOUT THEN IT ASKS WHETHER HE/SHE IS SURE TO DO SO
const signOutFunc = async () => {
Alert.alert(
"Ausloggen?",
"Sind Sie sicher, dass Sie sich ausloggen möchten?",
[
{
text: "Bestätigen", onPress: async () => {
await AsyncStorage.removeItem('userName')
await AsyncStorage.removeItem('order')
firebase.auth().signOut();
navigation.navigate('Homepage');
}
},
{
text: "Abbrechen",
style: "cancel"
}
]
);
}
return (
<ScrollView>
{/* THIS IS THE PART OF ICON WHERE LOGIN , SIGNOUT , Bestellverlauf AND Warenkorb ICON ARE HERE */}
<View style={styles.container}>
<View style={{ flexDirection: 'row', justifyContent: 'space-between', marginRight: 5, marginVertical: 10 }}>
{users ?
<TouchableOpacity onPress={() => { signOutFunc() }}>
<Entypo name="log-out" size={30} color="black" />
</TouchableOpacity>
: null}
{users ?
<View style={{ flexDirection: 'row', }}>
<TouchableOpacity onPress={() => { navigation.navigate('Bestellverlauf') }} style={{ marginRight: 20 }}>
<Fontisto name="prescription" size={30} color="black" />
</TouchableOpacity>
<TouchableOpacity onPress={() => { navigation.navigate('Warenkorb') }}>
<Feather name="shopping-bag" size={30} color="black" />
</TouchableOpacity>
</View>
:
<TouchableOpacity style={{ flexDirection: 'row' }} onPress={() => { navigation.navigate('Anmelden') }}>
<FontAwesome5 name="user" size={30} color="black" />
<Text style={{ margin: 10 }}>Registration/Login</Text>
</TouchableOpacity>
}
</View>
<Text style={styles.textFirst}>Ermittelte Adresse:</Text>
<View style={{ alignContent: 'center', flexDirection: 'row', width: '90%' }}>
<Text style={{ marginBottom: 15, marginTop: 10, marginHorizontal: 10 }}>{getAddress} </Text>
<TouchableOpacity onPress={() => { setShowRange(!showRange) }}>
<MaterialCommunityIcons name="filter-plus" size={30} color="grey" />
</TouchableOpacity>
</View>
{/* THIS IS RANGE SLIDER FOR SORTING ALL RESTAURANTS */}
{showRange ?
<View>
<View style={{ flexDirection: 'row', justifyContent: "space-between" }}>
<Text style={{ marginLeft: '3%', fontSize: 14, fontWeight: 'bold' }}> Entfernung festlegen!</Text>
<Text style={{ marginLeft: '3%' }}> {Math.round(ranges)} km</Text>
</View>
<Slider maximumValue={100} style={{ width: '90%', marginLeft: '5%', marginTop: 10, }} value={ranges} onValueChange={(e) => setRanges(e)} />
<View style={{ marginTop: 10 }}>
<Text style={{ marginLeft: '3%', fontSize: 14, fontWeight: 'bold', marginBottom: 10, }}>Filterung nach Kategorie</Text>
<View style={styles.checkboxContainer}>
<MyCheckbox />
<Text style={styles.checkboxLabel}>Backware</Text>
</View>
<View style={styles.checkboxContainer}>
<MyCheckbox />
<Text style={styles.checkboxLabel}>Bioprodukte</Text>
</View>
<View style={styles.checkboxContainer}>
<MyCheckbox />
<Text style={styles.checkboxLabel}>Feinkost</Text>
</View>
<View style={styles.checkboxContainer}>
<MyCheckbox />
<Text style={styles.checkboxLabel}>Griechische Spezialitäten</Text>
</View>
<View style={styles.checkboxContainer}>
<MyCheckbox />
<Text style={styles.checkboxLabel}>Molkerei</Text>
</View>
<View style={styles.checkboxContainer}>
<MyCheckbox />
<Text style={styles.checkboxLabel}>Türkische Spezialitäten</Text>
</View>
<Button title="Filter anwenden..." color='#5271FF'/>
</View>
</View>
: null
}
<Text style={styles.textSecond}>Sie können gerne die Filterfunktion verwenden, indem Sie oben auf den Symbol klicken...</Text>
{restaurentList && restaurentList.map((val, i) => {
return <ListButton key={i} title={val.firmenname} data={val} />
})}
</View>
</ScrollView>
);
}
A better approach to avoid duplication of code is to create a filterList array and create dynamic filters component.
I modified your code, check the comments for the explanation.
function MyCheckbox({addFilter, removeFilter, filterIndex}) { // ADD THIS PROPS TO ADD AND REMOVE FILTERS
const [checked, onChange] = useState(false);
function onCheckmarkPress() {
onChange(!checked);
checked ? addFilter(filterIndex) : removeFilter(filterIndex)
}
return (
<Pressable
style={[styles.checkboxBase, checked && styles.checkboxChecked]}
onPress={onCheckmarkPress}>
{checked && <Ionicons name="checkmark" size={18} color="white" />}
</Pressable>
);
}
export default function Anbieter({ route, navigation }) {
//CONSTS WHICH WE GOT FROM THE HOMEPAGE AND DECLARATION
const { latitude, longitude, address } = route.params;
var getLat = latitude;
var getLong = longitude;
var getAddress = JSON.stringify(address);
const [restaurentList, setRestaurentList] = useState()
const [filteredRestaurantList, setFilteredRestaurentList] = useState() // <-- ADD THIS STATE TO KEEP TRACK OF THE FILTERED LIST TO DISPLAY
const [currentUsers, setCurrentUsers] = useState()
const [ranges, setRanges] = useState(1)
const [showRange, setShowRange] = useState(false)
const [filters, setFilters] = useState([]) // <-- ADD THIS STATE TO KEEP TRACK OF THE FILTERS SELECTED
const filterList = ["Backware", "Bioprodukte", "Feinkost", "Griechische Spezialitäten"] // <--- CREATE A FILTER ARRAY
const addFilter = (filterIndex) => { // <-- FUNCTION ADD FILTER
setFilters([...filters, filterList[filterIndex]])
}
const removeFilter = (filterIndex) => { // <-- FUNCTION REMOVE FILTER
const index = filters.indexOf(filterList[filterIndex]);
const newFilters = [...filters];
newFilters.splice(index, 1)
setFilters(newFilters)
}
// THIS IS A LIST WHICH DISPLAY ALL RESTAURANTS BY GETTING DATA IN PARAMS IN NAME OF DATA
const ListButton = ({ title, data }) => {
return (
<TouchableOpacity onPress={() => { navigation.navigate('Produktubersicht', { data }) }} style={[styles.itemContainer]}>
<Image source={{ uri: data.anbieterImg }} style={{ width: '90%', marginLeft: '5%', height: 160 }} />
<Text style={{ fontSize: 16, fontWeight: "bold", marginLeft: 20 }}>{data.firmenname}</Text>
<Text style={{ fontSize: 16, fontWeight: "bold", marginLeft: 20, width: '90%' }}>Adresse:
<Text style={{ fontSize: 16, fontWeight: 'normal' }}>{data.adresse}</Text>
</Text>
<Text style={{ fontSize: 16, fontWeight: "bold", marginLeft: 20, width: '90%' }}>Kategorie:
<Text style={{ fontSize: 16, fontWeight: 'normal' }}>{data.kategorie}</Text>
</Text>
</TouchableOpacity>
);
}
// THIS FUNCTION IS USE TO CALL ALL RESTAURANT FROM FIREBASE DATABASE
const getRestaurents = async () => {
let arr = []
// THIS IS FIREBASE API ALL DATA IS COMING FROM FIREBASE
var ar = await firebase.database().ref("/anbieter/").once("child_added", snapshot => {
var obj = snapshot.val();
obj.id = snapshot.key;
arr.push(obj);
});
// ALL DATA OF RESTAURANT IS STORING IN STATE HERE THEN FROM HERE ALL DATA WILL DISPLAY
setRestaurentList(arr)
setFilteredRestaurentList(arr)
}
var users = firebase.auth().currentUser;
useEffect(() => {
// WE CALL GET RESTAURANTS API HERE BECAUSE THIS USEEFFECT JUST CALL ONCE WHEN COMPONENT RENDER
console.log(users, 'users');
getRestaurents()
}, []);
useEffect(() => { // <--- ADD THIS TO UPDATE THE FILTER RESTAURANT LIST EVERY TIME THAT THE FILTER ARRAY CHANGE
const rList = [...restaurentList];
if (filters.length) {
const filteredList = rList.filter(r => {
const toAdd = filters.indexOf(r.category)
if (toAdd !== -1) {
return r
}
})
setFilteredRestaurentList(filteredList)
}else { // <-- IF THERE ARE NO FILTER; RESET TO ORIGINAL LIST
setFilteredRestaurentList(rList)
}
}, [filters]);
return (
<ScrollView>
{/* THIS IS THE PART OF ICON WHERE LOGIN , SIGNOUT , Bestellverlauf AND Warenkorb ICON ARE HERE */}
<View style={styles.container}>
<View style={{ flexDirection: 'row', justifyContent: 'space-between', marginRight: 5, marginVertical: 10 }}>
{users ?
<TouchableOpacity onPress={() => { signOutFunc() }}>
<Entypo name="log-out" size={30} color="black" />
</TouchableOpacity>
: null}
{users ?
<View style={{ flexDirection: 'row', }}>
<TouchableOpacity onPress={() => { navigation.navigate('Bestellverlauf') }} style={{ marginRight: 20 }}>
<Fontisto name="prescription" size={30} color="black" />
</TouchableOpacity>
<TouchableOpacity onPress={() => { navigation.navigate('Warenkorb') }}>
<Feather name="shopping-bag" size={30} color="black" />
</TouchableOpacity>
</View>
:
<TouchableOpacity style={{ flexDirection: 'row' }} onPress={() => { navigation.navigate('Anmelden') }}>
<FontAwesome5 name="user" size={30} color="black" />
<Text style={{ margin: 10 }}>Registration/Login</Text>
</TouchableOpacity>
}
</View>
<Text style={styles.textFirst}>Ermittelte Adresse:</Text>
<View style={{ alignContent: 'center', flexDirection: 'row', width: '90%' }}>
<Text style={{ marginBottom: 15, marginTop: 10, marginHorizontal: 10 }}>{getAddress} </Text>
<TouchableOpacity onPress={() => { setShowRange(!showRange) }}>
<MaterialCommunityIcons name="filter-plus" size={30} color="grey" />
</TouchableOpacity>
</View>
{/* THIS IS RANGE SLIDER FOR SORTING ALL RESTAURANTS */}
{showRange ?
<View>
<View style={{ flexDirection: 'row', justifyContent: "space-between" }}>
<Text style={{ marginLeft: '3%', fontSize: 14, fontWeight: 'bold' }}> Entfernung festlegen!</Text>
<Text style={{ marginLeft: '3%' }}> {Math.round(ranges)} km</Text>
</View>
<Slider maximumValue={100} style={{ width: '90%', marginLeft: '5%', marginTop: 10, }} value={ranges} onValueChange={(e) => setRanges(e)} />
<View style={{ marginTop: 10 }}>
<Text style={{ marginLeft: '3%', fontSize: 14, fontWeight: 'bold', marginBottom: 10, }}>Filterung nach Kategorie</Text>
{filterList.map((filterItem, index) => (
<View
key={index}
style={styles.checkboxContainer}>
<MyCheckbox
addFilter={addFilter} // <-- ADD THIS PROP
removeFilter={removeFilter} // <-- ADD THIS PROP
filterIndex={index} // <-- ADD THIS PROP
/>
<Text style={styles.checkboxLabel}>filterItem</Text>
</View>
))}
<Button title="Filter anwenden..." color='#5271FF'/>
</View>
</View>
: null
}
<Text style={styles.textSecond}>Sie können gerne die Filterfunktion verwenden, indem Sie oben auf den Symbol klicken...</Text>
{filteredRestaurantList && filteredRestaurantList.map((val, i) => {
return <ListButton key={i} title={val.firmenname} data={val} />
})}
</View>
</ScrollView>
);
}

react native : there is way to pass a function into "onpress"?

there is way to pass a function into "onpress" ?
i need to pass the "postData" function into the "onpress" button ,
how can i do it?
in my code the has 2 "onpress" that i want to pass inside the "postData" .
if there some mistake so please let me know and i will fix it .
this is my code for example :
export default class OrderInformationScreen extends Component {
constructor(props) {
super(props);
const { state } = props.navigation;
this.state = {
title: state.params.data
}
//alert(JSON.stringify((state.params.data.SHORT_TEXT)))
}
postData = () => {
const postData = {
ACTOR_ID:"APAZ",
REPORT_KEY:"001",
WORK_ITEM_ID:"000018639250",
NOTE:"fun all time"
}
const axios = require('axios')
axios.post('https://harigotphat1.mekorot.co.il/ConfirmPackaotWS/OrderApprove/OrderApprove_OrderApp_Save_Approvement/'+ postData)
.then(function (response) {
console.log("roei response======>>>>",response);
})
}
render() {
return (
<>
<View
style={{
alignItems: 'flex-start',
justifyContent: 'center',
borderColor: 'blue',
flexDirection: "row",
justifyContent: 'space-evenly'
}}>
<TouchableOpacity onPress={() => console.log("cancel!")}>
<Avatar
size='large'
containerStyle={{ marginTop: 30 }}
activeOpacity={0.2}
rounded
source={require('../assets/down.png')} style={{ height: 80, width: 80 }}
onPress={() => console.log("cancel!")} />
<View >
<Text style={{ fontSize: 25, fontWeight: 'bold', color: 'red' }}>לדחות</Text>
</View>
</TouchableOpacity>
<TouchableOpacity onPress={() => console.log("works!")}> ///HERE I NEED PASS postData
<Avatar
size='large'
activeOpacity={0.1}
rounded
source={require('../assets/up.png')} style={{ height: 80, width: 80 }}
onPress={() => console.log("Works!")} />
<View>
<Text style={{ fontSize: 25, fontWeight: 'bold', color: 'green', marginHorizontal: 6 }}>לאשר</Text>
</View>
</TouchableOpacity>
</View>
<InfoTable headerInfo={this.state.title}></InfoTable>
</>
);
};
}
Check this updated code
export default class OrderInformationScreen extends Component {
constructor(props) {
super(props);
const { state } = props.navigation;
this.state = {
title: state.params.data
};
//alert(JSON.stringify((state.params.data.SHORT_TEXT)))
}
postData = () => {
const postData = {
ACTOR_ID: "APAZ",
REPORT_KEY: "001",
WORK_ITEM_ID: "000018639250",
NOTE: "fun all time"
};
const axios = require("axios");
axios
.post(
"https://harigotphat1.mekorot.co.il/ConfirmPackaotWS/OrderApprove/OrderApprove_OrderApp_Save_Approvement/" +
postData
)
.then(function(response) {
console.log("roei response======>>>>", response);
});
};
render() {
return (
<>
<View
style={{
alignItems: "flex-start",
justifyContent: "center",
borderColor: "blue",
flexDirection: "row",
justifyContent: "space-evenly"
}}
>
<TouchableOpacity onPress={() => console.log("cancel!")}>
<Avatar
size="large"
containerStyle={{ marginTop: 30 }}
activeOpacity={0.2}
rounded
source={require("../assets/down.png")}
style={{ height: 80, width: 80 }}
onPress={() => console.log("cancel!")}
/>
<View>
<Text style={{ fontSize: 25, fontWeight: "bold", color: "red" }}>
לדחות
</Text>
</View>
</TouchableOpacity>
<TouchableOpacity onPress={() => this.postData()}>
<Avatar
size="large"
activeOpacity={0.1}
rounded
source={require("../assets/up.png")}
style={{ height: 80, width: 80 }}
onPress={() => console.log("Works!")}
/>
<View>
<Text
style={{
fontSize: 25,
fontWeight: "bold",
color: "green",
marginHorizontal: 6
}}
>
לאשר
</Text>
</View>
</TouchableOpacity>
</View>
<InfoTable headerInfo={this.state.title}></InfoTable>
</>
);
}
}
Simply you can put function like this way
<TouchableOpacity onPress={() => this.postData()}> .... </TouchableOpacity>

How I can handle multiple checkbox and basis of that show and hide input fields and update to server in react native

In my code there are 2 dropdowns, 4 checkboxes, 4 input fields and one button.
Basically I have to update these fields on button click.
Problem with ckeck box .
I have to make checkbox "checked={true/false}" on condition basis, and I have to take these value and update the server:
1 [] Emal [] sms [] fax (all are unchecked )
Suppose I click on email the email should be checked and one Email input field should appear. And if again I uncheck the checkbox, the input field should be hidden.
If the value is checked Y value should go to server else N value if unchecked when I press the button below .
Basically there are multiple checkboxes and I have to update their value to server . Below Is UX link please see once .
https://xd.adobe.com/view/2b0336f6-6ff6-40ae-6653-f71e080dd0da-5d32/?fullscreen
import React, { Component } from 'react';
import { ImageBackground, ScrollView, TouchableOpacity, View, Platform, Image } from 'react-native';
import { Button, Text, Item, Input, Icon, Form, ListItem, CheckBox, Body, List } from 'native-base';
import Header from '../../ui/header';
import TextFieldTypeClear from '../../ui/textFieldTypeClear';
import SelectField from '../../ui/selectField';
import { PrimaryBtn } from '../../ui/buttons';
import BG from '../../../images/bg.jpg';
import styles from '../../simSwap/SimSwap.style';
import { RegularText, SmallText } from '../../ui/text';
import { ACCOUNT_OWNER,ADDRESS,CYCLE,EMAIL,PHONE,PERIODICITY,CURRENCY,LANGUAGE,EDIT,MAIL,FAX,POST,SMS,WHATSAPP } from '../../../images';
import _ from 'lodash';
const styless = {
icon:{
marginRight:5, marginTop:3
},
label:{
fontSize:14, color:'grey'
}
}
const Label = ({img, textLabel}) =>{
return (
<View style={{flexDirection:'row'}}>
<Image style={styless.icon} source={img}/>
<Text style={styless.label}>{textLabel}</Text>
</View>
);
}
class UpdateBillPreferences extends Component {
constructor(props) {
super(props);
const {navigation,clmmasterData} =this.props;
this.state = {
title: 'Update Bill Preferences',
mobile: navigation.state.params.customer.service.serviceNumber,
icon: 'sim',
email: '',
smsNum: '',
faxNum: '',
isBillByEmail : navigation.state.params.customerInfo[0].billingPreferenceDetails.isBillByEmail,
isBillBySms : navigation.state.params.customerInfo[0].billingPreferenceDetails.isBillByFax,
isBillByFax : navigation.state.params.customerInfo[0].billingPreferenceDetails.isBillBySms,
languageAndCurrecny:{
preferredLanguage: navigation.state.params.customerInfo[0].billingPreferenceDetails.presentationLanguageCode,
},
currencyChangedValue:{
preferredCurrency: navigation.state.params.customerInfo[0].billingPreferenceDetails.preferedCurrencyCode,
}
};
}
componentDidMount() {
}
OnButtonClick = async (preferredLanguage, preferredCurrency,email,smsNum,faxNum) => {
const { OnButtonClick } = this.props;
await OnButtonClick(preferredLanguage, preferredCurrency,email,smsNum,faxNum);
this.setState({
preferredCurrency:'',
preferredLanguage:'',
email :'',
smsNum :'',
faxNum :''
})
}
languageChanged = (key, val) => {
this.handleChange({ field: "preferredLanguage" }, val);
};
handleChange = (props, e) => {
let tempObj = this.state.languageAndCurrecny;
tempObj[props.field] = e;
this.setState({ preferredLanguage: tempObj });
};
currencyChanged = (key, val) => {
this.handleChange2({ field: "preferredCurrency" }, val);
};
handleChange2 = (props, e) => {
let tempObj = this.state.currencyChangedValue;
tempObj[props.field] = e;
this.setState({ preferredCurrency: tempObj });
};
handleChange1 = () => {
let isBillByEmail=this.state.isBillByEmail;
console.log("-----------------------clicked-------");
this.setState(previousState => {
return { isBillByEmail: !previousState.checked };
})
console.log("----------isBillByEmail--------------------",isBillByEmail);
}
render() {
let { title, mobile, icon,languageAndCurrecny,currencyChangedValue,isBillByEmail } = this.state;
const { navigation,clmmasterData} = this.props;
const {billingAddressDetails,billingPreferenceDetails} = navigation.state.params.customerInfo[0];
const {masterData , language} = clmmasterData;
let submitBtn = { label: 'Submit', OnSubmit: this.onSubmit };
let currencyData=[];
masterData.preferredCurrency.map(({ code: value, name: label }) => {
currencyData.push({ value, label });
});
let languageData=[];
masterData.language.map(({ code: value, name: label }) => {
languageData.push({ value, label });
});
return (
<ImageBackground source={BG} style={styles.imgBG}>
<ScrollView>
<View style={styles.container}>
<View>
<Header title={title} subtitle={mobile} icon={icon} navigation={navigation}/>
</View>
<View style={styles.contentContainer}>
<View style={{ padding: 20 }}>
<Form style={{ width: '100%' }}>
<SelectField
label="Presentation Language"
node="presentationLanguage"
options={languageData}
value={languageAndCurrecny.preferredLanguage}
onChange={this.languageChanged}
that={this}
setIcon={true}
img="LANGUAGE"
/>
<SelectField
label="Preferred Currency"
options={currencyData}
value={currencyChangedValue.preferredCurrency}
node="preferredCurrency"
onChange={this.currencyChanged}
that={this}
setIcon={true}
img="CURRENCY"
/>
<View style={{flexDirection:'column', marginBottom:15}}>
<View>
<Text style={{ color: 'grey', marginBottom: 15, marginTop:10, fontSize:14 }}>Preference</Text>
</View>
<View style={{flexDirection:'row', marginLeft:-10}}>
<View style={{flex:1}}>
<CheckBox color="#00678f" checked={billingPreferenceDetails.isBillByPost === "Y" ? true : false}/>
</View>
<View style={{flex:1}}>
<Text style={{fontSize:14}}>Post</Text>
</View>
<View style={{flex:1}}>
<CheckBox color="#00678f" checked={isBillByEmail==='Y'?true : false} onPress={() =>this.handleChange1()}/>
</View>
<View style={{flex:1}}>
<Text style={{fontSize:14}}>Email</Text>
</View>
<View style={{flex:1}}>
<CheckBox color="#00678f" checked={true} onPress={() =>this.handleChange()}/>
</View>
<View style={{flex:1}}>
<Text style={{fontSize:14}}>SMS</Text>
</View>
<View style={{flex:1}}>
<CheckBox color="#00678f" checked={true} onPress={() =>this.handleChange()}/>
</View>
<View style={{flex:1}}>
<Text style={{fontSize:14}}>FAX</Text>
</View>
</View>
</View>
<View style={{flexDirection:'column', marginBottom:15}}>
<View style={{marginTop:10, marginBottom:10, marginLeft:-3}}>
<Label img={ADDRESS} textLabel="Address"/>
</View>
<View>
<RegularText style={{ fontWeight: 'normal' }} text={`${billingAddressDetails.address1}, ${billingAddressDetails.address2}, ${billingAddressDetails.cityName}, ${billingAddressDetails.state}, ${billingAddressDetails.country}`} textColor="black" />
</View>
</View>
<View style={{marginBottom:15}}>
{billingPreferenceDetails.isBillByEmail === 'Y' &&
<View>
<Label img={EMAIL} textLabel="Email"/>
<Item style={{borderColor: '#00fff', borderBottomWidth:1, marginLeft:0}}>
<Input
value={this.state.email}
onChangeText={(text) => this.setState({email:text})}
/>
</Item>
</View>}
{billingPreferenceDetails.isBillBySms === 'Y' &&
<View>
<Label img={EMAIL} textLabel="SMS"/>
<Item style={{borderColor: '#00fff', borderBottomWidth:1, marginLeft:0}}>
<Input
value={this.state.smsNum}
onChangeText={(text) => this.setState({smsNum:text})}
/>
</Item>
</View>}
{billingPreferenceDetails.isBillByFax === 'Y' &&
<View>
<Label img={EMAIL} textLabel="FAX"/>
<Item style={{borderColor: '#00fff', borderBottomWidth:1, marginLeft:0}}>
<Input
value={this.state.faxNum}
onChangeText={(text) => this.setState({faxNum:text})}
/>
</Item>
</View>}
</View>
<View style={{ marginTop: 50 }}>
<PrimaryBtn label={'submit'} disabled={false} onPress={()=> this.OnButtonClick(this.state.preferredLanguage,this.state.preferredCurrency,
this.state.email,this.state.smsNum,this.state.faxNum)}/>
</View>
</Form>
</View>
</View>
</View>
</ScrollView>
</ImageBackground>
);
}
}
export default UpdateBillPreferences;
// Checkbox part where I am facing problem .
Props Value
isBillByEmail: "N"
isBillByFax: "Y"
isBillByPost: "Y"
isBillBySms: "N"
<View style={{flexDirection:'column', marginBottom:15}}>
<View>
<Text style={{ color: 'grey', marginBottom: 15, marginTop:10, fontSize:14 }}>Preference</Text>
</View>
<View style={{flexDirection:'row', marginLeft:-10}}>
<View style={{flex:1}}>
<CheckBox color="#00678f" checked={billingPreferenceDetails.isBillByPost === "Y" ? true : false}/>
</View>
<View style={{flex:1}}>
<Text style={{fontSize:14}}>Post</Text>
</View>
<View style={{flex:1}}>
<CheckBox color="#00678f" checked={isBillByEmail==='Y'?true : false} onPress={() =>this.handleChange1()}/>
</View>
<View style={{flex:1}}>
<Text style={{fontSize:14}}>Email</Text>
</View>
<View style={{flex:1}}>
<CheckBox color="#00678f" checked={true} onPress={() =>this.handleChange()}/>
</View>
<View style={{flex:1}}>
<Text style={{fontSize:14}}>SMS</Text>
</View>
<View style={{flex:1}}>
<CheckBox color="#00678f" checked={true} onPress={() =>this.handleChange()}/>
</View>
<View style={{flex:1}}>
<Text style={{fontSize:14}}>FAX</Text>
</View>
</View>
</View>
<View style={{flexDirection:'column', marginBottom:15}}>
<View style={{marginTop:10, marginBottom:10, marginLeft:-3}}>
<Label img={ADDRESS} textLabel="Address"/>
</View>
<View>
<RegularText style={{ fontWeight: 'normal' }} text={`${billingAddressDetails.address1}, ${billingAddressDetails.address2}, ${billingAddressDetails.cityName}, ${billingAddressDetails.state}, ${billingAddressDetails.country}`} textColor="black" />
</View>
</View>
<View style={{marginBottom:15}}>
{billingPreferenceDetails.isBillByEmail === 'Y' &&
<View>
<Label img={EMAIL} textLabel="Email"/>
<Item style={{borderColor: '#00fff', borderBottomWidth:1, marginLeft:0}}>
<Input
value={this.state.email}
onChangeText={(text) => this.setState({email:text})}
/>
</Item>
</View>}
{billingPreferenceDetails.isBillBySms === 'Y' &&
<View>
<Label img={EMAIL} textLabel="SMS"/>
<Item style={{borderColor: '#00fff', borderBottomWidth:1, marginLeft:0}}>
<Input
value={this.state.smsNum}
onChangeText={(text) => this.setState({smsNum:text})}
/>
</Item>
</View>}
{billingPreferenceDetails.isBillByFax === 'Y' &&
<View>
<Label img={EMAIL} textLabel="FAX"/>
<Item style={{borderColor: '#00fff', borderBottomWidth:1, marginLeft:0}}>
<Input
value={this.state.faxNum}
onChangeText={(text) => this.setState({faxNum:text})}
/>
</Item>
</View>}
</View>
<View style={{ marginTop: 50 }}>
<PrimaryBtn label={'submit'} disabled={false} onPress={()=> this.OnButtonClick(this.state.preferredLanguage,this.state.preferredCurrency,
this.state.email,this.state.smsNum,this.state.faxNum)}/>
</View>
</Form>
</View>
</View>
Please help..Thanks

How to send and display the value of a text input on another screen with native react?

I want to send the data of a text input that is stored in a variable to another screen and show the data that was saved in said variable
Try to pass the state of the variable by react-navigation but the problem is that I have 3 screens and I want to pass the data stored in the variable text from screen 1 to screen 3
class Screen1 extends Component {
constructor(props) {
super(props);
this.state = {
text: '',
percentage: ''
};
}
static navigationOptions = ({ navigation }) => {
const { params = {} } = navigation.state
var data = {
textData: params.text
}
return {
headerLeft: (
<View style={{ flexDirection: 'row', justifyContent: 'center', alignItems: 'center' }}>
<AntDesign
name="left"
color="rgba(0,0,0,0.5)"
size={30}
style={{ marginLeft: 5 }}
/>
<Text style={{ marginLeft: 20, color: '#000', fontSize: 17, fontWeight: 'bold' }}>Crear regalo</Text>
</View>
),
headerRight: (
<View>
<TouchableOpacity
disabled={navigation.getParam('isDisable')} // get value from params and pass it to disabled props
onPress={() => navigation.navigate('2', { data })}
style={styles.Btn}>
<Text style={styles.TxtBtn}>Siguiente</Text>
</TouchableOpacity>
</View>
),
}
};
// set by a default value in componentDidMount to make the next button disable initially
componentDidMount() {
Alert.alert('Advertencia', 'Ingrese el porcentaje de su descuento');
this.props.navigation.setParams({ isDisable: true });
}
render() {
return (
<View style={styles.container}>
<View style={styles.Box}>
<ImageBackground source={require('../Icons/Regalo.png')} style={styles.Image}>
<View style={styles.ContainerInput}>
<TextInput
style={{ textAlign: 'center', color: '#fff', fontSize: 40, }}
type="numeric"
placeholder="%"
value={this.state.text} //set value from state
onChangeText={(text) => {
//when text length is greater than 0 than next button active otherwise it will be disable
let isDisable = text.length > 0 ? false : true
//set value in the state
this.setState({ text: text })
// set value to params
this.props.navigation.setParams({ isDisable: isDisable });
}} />
<Text style={{ fontSize: 40, color: '#fff', textAlign: 'center' }}>
{this.state.text.split(' ').map((word) => word && '%').join(' ')}
</Text>
</View>
</ImageBackground>
</View>
</View>
);
}
}
export default Screen1;
My Screen Two:
class Screen2 extends Component {
constructor(props) {
super(props);
this.state = {
textData: this.props.navigation.state.params.data.textData,
text: ''
};
}
static navigationOptions = ({ navigation }) => {
const { params = {} } = navigation.state
var data = {
textData: params.textData
}
return {
headerLeft: (
<View style={{ flexDirection: 'row', justifyContent: 'center', alignItems: 'center' }}>
<AntDesign
name="left"
color="rgba(0,0,0,0.5)"
size={30}
style={{ marginLeft: 5 }}
onPress={() => navigation.navigate('1')}
/>
<Text style={{ marginLeft: 20, color: '#000', fontSize: 17, fontWeight: 'bold' }}>Crear regalo</Text>
</View>
),
headerRight: (
<View>
<TouchableOpacity
disabled={navigation.getParam('isDisable')} // get value from params and pass it to disabled props
onPress={() => navigation.navigate('3', { data })}
style={styles.Btn}>
<Text style={styles.TxtBtn}>Crear</Text>
</TouchableOpacity>
</View>
),
}
};
componentDidMount() {
this.props.navigation.setParams({ isDisable: true });
}
render() {
return (
<View style={styles.container}>
<View style={styles.InputContainer}>
<TextInput
multiline
style={styles.Input}
type="numeric"
placeholder="Describa los términos y condificones de tu regalos"
placeholderTextColor="rgb(196,196,196)"
value={this.state.text} //set value from state
onChangeText={(text) => {
//when text length is greater than 0 than next button active otherwise it will be disable
let isDisable = text.length > 1 ? false : true
//set value in the state
this.setState({ text: text })
// set value to params
this.props.navigation.setParams({ isDisable: isDisable });
}} />
</View>
</View>
);
}
}
export default Screen2;
My Screen Three:
class Screen3 extends Component {
constructor(props) {
super(props);
this.state = {
textData: this.props.navigation.state.params.data.textData,
text: '',
percentage: '',
};
}
static navigationOptions = ({ navigation }) => ({
headerLeft: (
<View style={{ flexDirection: 'row', justifyContent: 'center', alignItems: 'center' }}>
<AntDesign
name="left"
color="rgba(0,0,0,0.5)"
size={30}
style={{ marginLeft: 5 }}
onPress={() => navigation.navigate('2')}
/>
<Text style={{ marginLeft: 20, color: '#000', fontSize: 17, fontWeight: 'bold' }}>Crear regalo</Text>
</View>
),
headerRight: (
<View>
<TouchableOpacity
disabled={navigation.getParam('isDisable')} // get value from params and pass it to disabled props
onPress={() => navigation.navigate('4')}
style={styles.Btn}>
<Text style={styles.TxtBtn}>Crear</Text>
</TouchableOpacity>
</View>
),
});
// set by a default value in componentDidMount to make the next button disable initially
componentDidMount() {
this.props.navigation.setParams({ isDisable: true });
}
render() {
let datos = [{
value: 'Banana',
}, {
value: 'Mango',
}, {
value: 'Pear',
}];
var data = {
textData: this.state.textData
}
return (
<View style={styles.container}>
<View style={styles.BoxandInput}>
<View style={styles.ContainerInput}>
<TextInput
style={styles.Input}
multiline
placeholder='Escriba una Descripcion'
placeholderTextColor="rgb(196,196,196)"
maxLength={203}
/>
</View>
<View style={styles.Box}>
<ImageBackground
source={require('../Icons/Regalo.png')}
style={styles.Image}>
<View style={styles.ContainerText}>
<Text style={styles.TextBox}>{data}</Text>
</View>
</ImageBackground>
</View>
</View>
<View style={styles.Regalos}>
<View style={{ justifyContent: 'center', alignItems: 'center', flexDirection: 'row' }}>
<Text style={styles.line}>--------------------------</Text>
<Text style={styles.RegalosText}>Cantidad de Regalos</Text>
<Text style={styles.line}>--------------------------</Text>
</View>
<View style={{ justifyContent: 'center', alignItems: 'center', marginTop: 30 }}>
<TextInput
style={styles.RegalosInput}
placeholder='0'
placeholderTextColor='#000'
maxLength={6}
type='numeric'
/>
<View style={styles.LineInput} />
<Text style={{ fontSize: 10, color: '#ccc', textAlign: 'center', marginTop: 5 }}>60 regalos Disponibles</Text>
<TouchableOpacity style={{ marginTop: 15 }}>
<Text style={{ fontSize: 10, color: 'cyan', textAlign: 'center' }}>Comprar Regalos</Text>
</TouchableOpacity>
</View>
</View>
<View style={styles.ContainerServices}>
<View style={{ justifyContent: 'center', alignItems: 'center', flexDirection: 'row' }}>
<Text style={styles.line}>-----------------------------------</Text>
<Text style={styles.RegalosText}>Servicios</Text>
<Text style={styles.line}>-----------------------------------</Text>
</View>
<Dropdown
dropdownMargins={{ min: 5, max: 10 }}
label='Favorite Fruit'
data={datos}
/>
</View>
</View>
);
}
}
export default
This Problem
You can create a data object and you can send it with navigation to next UI. You can pass the data object from UI 1 to UI 2 and then you can send it UI 3 from UI 2.
In the first UI you can create data variable like,
var data = {
textData: text
}
Include the above code inside navigationOptions of your code.
Then in the navigation call include the data object as well.
onPress={() => navigation.navigate('2', {data})}
In the second UI assign the passed value to a variable inside the constructor.
constructor(props) {
super(props);
this.state = {
textData: this.props.navigation.state.params.data. textData,
}
}
Then when you are going to navigate to the third UI create a data variable and send it as previously done.
var data = {
textData: this.state.textData
}
Pass this variable with navigate.navigation and access it from third UI similar as in the second UI.

Categories

Resources