How to set search image icon in react-native-google-places-autocomplete? - google-maps

How to set search image icon in react-native-google-places-autocomplete?
I want to know how i can set search image icon on left side in react-native-google-places-autocomplete.
I want output like this in below screen.So please help me.
But my design is like this.
Here is code of DiscoveryLocation.js file.
import React, { Component } from 'react'
import { Text, View, TouchableOpacity, TextInput, StyleSheet, Image } from 'react-native'
import { heightPercentageToDP as hp, widthPercentageToDP as wp } from 'react-native-responsive-screen';
import { RFPercentage, RFValue } from "react-native-responsive-fontsize";
import MapView, { PROVIDER_GOOGLE, Marker } from 'react-native-maps';
import { GooglePlacesAutocomplete } from 'react-native-google-places-autocomplete';
console.disableYellowBox = true;
export default class DiscoveryLocation extends Component {
render() {
return (
<View style={styles.container}>
<View style={styles.vwheader} >
<TouchableOpacity
onPress={() => { this.props.navigation.goBack() }}
>
<Image source={require('../../Images/left-arrow-red.png')} style={{ height: 25, width: 30, marginTop: 22, marginLeft: 15, }}
/>
</TouchableOpacity>
<Text style={styles.txtdisloc}>Discovery Location </Text>
</View>
<View style={styles.mapcontainer}>
<MapView
provider={PROVIDER_GOOGLE}
style={styles.map}
region={{
latitude: 37.78825,
longitude: -122.4324,
latitudeDelta: 0.015,
longitudeDelta: 0.0121,
}}
>
</MapView>
<View style={{ marginTop: hp('12%'), }}>
<GooglePlacesAutocomplete
placeholder='Enter City, State, Country'
minLength={2} // minimum length of text to search
autoFocus={false}
fetchDetails={true}
onPress={(data, details = null) => { // 'details' is provided when fetchDetails = true
console.log(data);
console.log(details);
}}
getDefaultValue={() => {
return 'Mataram';
}}
query={{
// available options: https://developers.google.com/places/web-service/autocomplete
key: 'MY_API_KEY',
language: 'en', // language of the results
types: '(cities)' // default: 'geocode'
}}
styles={{
textInputContainer: {
width: wp('90%%'), height: hp('7%'), borderRadius: 11, borderTopWidth: 0,
borderBottomWidth: 0
},
textInput: {
marginLeft: 0,
marginRight: 0,
backgroundColor: 'D3D3D3'
},
description: {
fontWeight: 'bold',
},
predefinedPlacesDescription: {
color: '#1faadb'
},
powered: {
},
}}
filterReverseGeocodingByTypes={['locality', 'administrative_area_level_3']} // filter the reverse geocoding results by types - ['locality', 'administrative_area_level_3'] if you want to display only cities
predefinedPlacesAlwaysVisible={true}
/>
</View>
</View>
<View style={{ marginTop: 10, marginBottom: 10 }}>
<TouchableOpacity style={styles.btn}>
<Text style={styles.txtbtn}>Confirm Location</Text>
</TouchableOpacity>
</View>
</View>
);
}
}

I know this is late, but for the future ref There are props to add icons in GooglePlacesAutocomplete
renderLeftButton={() => <Image source={require('path/custom/left-icon')} />}
renderRightButton={() => <Text>Custom text after the input</Text>}
Here is the link for tutorial

Related

Cypress check if the sort the grid by order

I am trying to sort images by order, i have the button new and old. the [data-cy="list-file"] is the wrap for all images and [data-cy=fileCard-list] represent each one image.
I want after clicking the button old for example to be able the check with cypress if the sort is working perfectly.
import { sortFilteredComments } from './../../../../lib/vmr';
import loginData from '../../../fixtures/login.json';
/// <reference types='cypress' />
describe('upload multiple photos', () => {
before(() => {
cy.clearLocalStorageSnapshot();
});
beforeEach(() => {
cy.restoreLocalStorage();
});
afterEach(() => {
cy.saveLocalStorage();
});
it('login', () => {
cy.get('[data-cy=projects-card-table]').contains('E2E-TEST').click();
cy.get('[data-cy="header-search-bar"]').click();
cy.wait(3000).get('[data-cy=file-order-old]').click();
cy.get('[data-cy="list-file"]').should('be.visible');
cy.get('[data-cy=each-item-file]').should('be.visible');
});
});
Here is the file with sort method
`import Card from '#material-ui/core/Card';
import CardMedia from '#material-ui/core/CardMedia';
import Grid from '#material-ui/core/Grid';
import { makeStyles } from '#material-ui/core/styles';
import Typography from '#material-ui/core/Typography';
import { IFetchedFiles } from 'api';
import clsx from 'clsx';
import { useRouter } from 'next/router';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { formatFullDate } from '~/lib/date';
import MimeIcon from '../../MimeIcon';
import { COLORS } from '~/lib/theme';
const useStyles = makeStyles(() => ({
card: {
backgroundColor: '#F1F3F3',
height: '400px',
width: '288px',
margin: '8px'
},
cardMedia: {
height: '200px',
margin: '10px',
cursor: 'pointer',
position: 'relative'
},
cardMediaImgContain: {
backgroundSize: 'contain'
},
excelTitle: {
backgroundColor: COLORS.white,
bottom: 0,
color: 'black',
fontSize: 14,
fontWeight: 'bold',
position: 'absolute',
padding: 4,
right: 0
},
group: {
marginRight: 20
},
groupWrap: {
display: 'flex',
padding: '0px 10px'
},
projectLabel: {
fontSize: 14,
fontWeight: 'bold',
marginBottom: '11px',
padding: '0px 10px'
},
title: {
fontSize: 14
},
titleWithMarginTop: {
fontSize: 14,
marginTop: 12
},
fileData: {
fontSize: 14,
fontWeight: 'bold'
},
fileDataMarginTop: {
fontSize: 14,
fontWeight: 'bold',
marginTop: 12
},
iconsContainer: {
display: 'flex',
gap: '4px',
padding: '4px'
}
}));
const iconSize = 24;
interface IProps {
file: IFetchedFiles['files'][number];
organizationName: string;
getImageUrl: () => any;
imageMime: boolean;
excelMime: boolean;
pdfMime: boolean;
tiffMime: boolean;
}
const FileCard: React.VFC<IProps> = ({
file,
organizationName,
getImageUrl,
imageMime,
excelMime
}) => {
const classes = useStyles();
const { t, i18n } = useTranslation();
const router = useRouter();
return (
<Grid **data-cy='each-item-file'** key={file.file.id}>
<Card className={classes.card}>
<CardMedia
className={clsx(classes.cardMedia, {
[classes.cardMediaImgContain]: excelMime
})}
image={getImageUrl()}
onClick={() => {
const photoUrl = `/orgs/${organizationName}/projects/${file.project.id}/photos/${file.file.id}`;
router.push(photoUrl);
}}
>
<div className={classes.iconsContainer}>
{file.file.mime && (
<MimeIcon mime={file.file.mime} iconSizeMime={iconSize} />
)}
</div>
{excelMime && (
<div className={classes.excelTitle}>{file.file.name}</div>
)}
</CardMedia>
<Typography variant='h6' className={classes.projectLabel}>
{file.project.label}
</Typography>
<div className={classes.groupWrap}>
<div className={classes.group}>
{file.material_group.label && (
<Typography variant='h6' className={classes.title}>
{t('searchFile.fileList.materialGroup')}
</Typography>
)}
<Typography variant='h6' className={classes.title}>
{t('searchFile.fileList.material')}
</Typography>
<Typography variant='h6' className={classes.title}>
{t('searchFile.fileList.process')}
</Typography>
<Typography variant='h6' className={classes.titleWithMarginTop}>
{imageMime
? t('searchFile.fileList.date')
: t('file.lastModified')}
</Typography>
<Typography variant='h6' className={classes.title}>
{imageMime
? t('searchFile.fileList.photographer')
: t('searchFile.fileList.registrant')}
</Typography>
</div>
<div>
{file.material_group.label && (
<Typography
variant='h6'
color='primary'
className={classes.fileData}
>
{file.material_group.label}
</Typography>
)}
<Typography
variant='h6'
color='primary'
className={classes.fileData}
>
{file.material.label ?? t('searchFile.fileList.uncategorized')}
</Typography>
<Typography
variant='h6'
color='primary'
className={classes.fileData}
>
{file.process.label ?? t('searchFile.fileList.uncategorized')}
</Typography>
<Typography
variant='h6'
className={classes.fileDataMarginTop}
color='primary'
>
{`${formatFullDate(new Date(file.file.date), i18n.language)}`}
</Typography>
<Typography
variant='h6'
color='primary'
className={classes.fileData}
>
{file.user.display_name ?? ''}
</Typography>
</div>
</div>
</Card>
</Grid>
);
};
export default FileCard;
`
It's a little bit confusing because it's not a table and i am working on react.js and typescript. Here everything is working perfectly but just the last assertion is where i have no clue.
Notes: you can see that [data-cy="list-file"] represent the whole container and [data-cy=fileCard-list] represent each file inside of the container.
I think we need more details about the sorting method you are using. In a table we could check the aria-sort property. Do you have any similar way to check it?
Another way could be iterating over all the [data-cy=fileCard-list] and checking if the parameter you are using to order them is correctly sorted. I don't understand what you mean with that last assertion cy.get('[data-cy="list-file"]').should('be.visible');

Use a function sent from Flatlist to a sub component

I'm trying to use a function from a class into another, when dealing with Flatlist.
Here is my class where my flatlist is :
_displayDetailsForMyItem = (idItem, type) => {
this.props.navigation.navigate('ItemDetails', { idMyItem: idItem, type: type })
}
_displayDataList(){
const type = this.props.route.params?.type ?? 'defaultValue'
if (type === 'Money') {
return this.state.moneyList
} else if (type === 'Stuff') {
return this.state.stuffList
} else {
return this.state.peopleList
}
}
_deleteItem = (idItem, type) => {
alert('Delete button pressed')
}
render(){
const type = this.props.route.params?.type ?? 'defaultValue'
if(this.state.isLoading){
return(
<View style={styles.activity}>
<ActivityIndicator size="large" color="#ED6D6D"/>
</View>
)
}
return(
<FlatList
style={styles.list}
data={this._displayDataList()}
keyExtractor={(item) => item.key.toString()}
renderItem={({item}) => <MyItem
myItem={item}
itemType={type}
displayDetailsForMyItem={this._displayDetailsForMyItem}
deleteItem={(item) => this._deleteItem(item.id, type)}/>}
onEndReachedThreshold={0.5}
onEndReached={() => {
}}
/>
)
}
I don't put all the code since it's not relevant.
In another class I have the item part of my code.
render(){
const { myItem, displayDetailsForMyItem } = this.props
let ptfPrefix
(Platform.OS === 'android') ? ptfPrefix = 'md-' : ptfPrefix = 'ios-'
const calIconName = ptfPrefix + 'calendar'
const titleIconName = ptfPrefix + 'create'
const pplIconName = ptfPrefix + 'contact'
const RightActions = (progress, dragX) => {
const scale = dragX.interpolate({
inputRange: [-100, 0],
outputRange: [0.7, 0]
})
return (
<>
<TouchableOpacity onPress={() => deleteItem(myItem.key, 'toto')}>
<View
style={{ flex: 1, backgroundColor: 'red', justifyContent: 'center' }}>
<Animated.Text
style={{
color: 'white',
paddingHorizontal: 20,
fontWeight: '600',
transform: [{ scale }]
}}>
<Ionicons name='ios-trash' size={70} color='#FFFFFF' />
</Animated.Text>
</View>
</TouchableOpacity>
</>
)
}
return(
<Swipeable renderRightActions={RightActions}>
<TouchableOpacity
style={styles.main_container}
onPress={() => displayDetailsForMyItem(myItem.key)}>
<View style={styles.first_line}>
<View style={styles.left_part_container}>
<View style={styles.date_container}>
<Image style={styles.date_bg} source={require('../assets/icons/list_bg.png')} />
<Ionicons name={calIconName} style={styles.top_left_elmnts} />
<Moment style={styles.top_left_elmnts} element={Text} format="DD/MM/YYYY" date={myItem.date} />
</View>
</View>
<View style={styles.right_part_container}>
<Text style={styles.top_right_elmnts}>{myItem.title}</Text>
<Ionicons name={titleIconName} style={styles.top_right_elmnts} />
</View>
</View>
<View style={styles.main_data}>
<Text style={styles.main_text}>
{(this.props.itemType === 'Money') ? myItem.amount + " €" : myItem.quantity + " Objets"}
</Text>
</View>
<View style={styles.last_row}>
<View style={styles.left_part_container}>
<Ionicons name={pplIconName} style={styles.btm_left_elmnts} />
<Text style={styles.btm_left_elmnts}>{myItem.people}</Text>
</View>
</View>
</TouchableOpacity>
</Swipeable>
)
}
So here, I pass 2 functions from the Flatlist class to the Item Class (two distinct .js files for me).
The displayDetailsForMyItem(myItem.key) function is correctly working (seems that it's because I'm calling it from the HTML part).
The fact is I would like to be able to call the second function deleteItem from outside the render() part (within the onPress() of the TouchableOpacity which is in the const RightActions), but I have an error telling :
can't find variable: deleteItem
I'm stuck
Ok I just didn't test all the possibilities.
Just have to call this.props.myFunction() instead of just myFunction (which is working inside the HTML part)

Need to dynamically add items into a drawer menu in React Native

I need to have some items dynamically in my app's drawer after some categories get fetched from a json file (https://www.rallyssimo.it/wp-json/wp/v2/categories)
json example (I need that information)
[
{
"id": 44,
.
.
"name": "ALTRI RALLY",
.
.
},
Tis is the drawer:
const CustomDrawerComponent = (props) => (
<SafeAreaView style={{flex:1}}>
<View style={{height:80, backgroundColor: 'white', alignItems: 'center', justifyContent: 'center'}}>
<Image
source={{uri: 'https://www.rallyssimo.it/wp-content/uploads/2016/08/rallyssimo-logo.png'}}
style={{ height: 60, width: 180}}
/>
</View>
<ScrollView>
<DrawerItems {...props} />
</ScrollView>
</SafeAreaView>
)
const AppNavigator = createDrawerNavigator(
{
Home: DashboardStackNavigator,
},
{
contentComponent: CustomDrawerComponent
}
);
const AppContainer = createAppContainer(AppNavigator);
//Main class
export default class App extends React.Component {
render() {
return <AppContainer />;
}
}
How can I put the items (I'm going to get from the JSON) in the drawer?
As you have noticed, you need to create your own custom drawer to achieve this, which is done with contentComponent: CustomDrawerComponent.
Now you cannot use DrawerItems within CustomDrawerComponent since you want full control on the items listed. But you can recreate the items yourself using basic and elements.
Finally you need to fetch the API and store the data in your state in order to render the result as a list in the drawer.
Here is a basic example for :
import React, { Component } from 'react';
import { ScrollView, Text, View, Image } from 'react-native';
import { NavigationActions } from 'react-navigation';
class CustomDrawerComponent extends Component {
constructor(props) {
super(props);
this.state = { data: null };
}
async componentDidMount() {
fetch('https://www.rallyssimo.it/wp-json/wp/v2/categories')
.then(res => res.json())
.then(data => this.setState({ data }))
}
navigateToScreen(routeName, params) {
return () => { this.props.navigation.dispatch(NavigationActions.navigate({ routeName, params })) };
}
render() {
if (this.state.data === null) {
return <Text>...</Text>;
}
return (
<View style={{ flex: 1, paddingTop: 30 }}>
<View style={{height:80, backgroundColor: 'white', alignItems: 'center', justifyContent: 'center'}}>
<Image
source={{uri: 'https://www.rallyssimo.it/wp-content/uploads/2016/08/rallyssimo-logo.png'}}
style={{ height: 60, width: 180}}
/>
</View>
<ScrollView>
<View>
{this.state.data.map(x => (
<Text
key={x.id}
style={{ fontSize: 16, lineHeight: 30, textAlign: 'center' }}
onPress={this.navigateToScreen('page2')}
>
{x.name}
</Text>
))}
</View>
</ScrollView>
</View>
);
}
}
export default CustomDrawerComponent;
And here is a working snack.

How to get the address from google maps autocomplete in React Native

I am using react-native-google-places-autocomplete to select a location. I want to extract the location selected and use it in other component.
How can I save the address
This is my code
import React, {Component} from 'react';
import { View, Image, Text, StyleSheet } from 'react-native';
import { GooglePlacesAutocomplete } from 'react-native-google-places-autocomplete';
const homePlace = { description: 'Home', geometry: { location: { lat: 48.8152937, lng: 2.4597668 } }};
const workPlace = { description: 'Work', geometry: { location: { lat: 48.8496818, lng: 2.2940881 } }};
export default class google extends Component {
render(){
return (
<View style={styles.container}>
<View style={styles.top}>
<GooglePlacesAutocomplete
placeholder='Search'
minLength={2} // minimum length of text to search
autoFocus={false}
returnKeyType={'search'} // Can be left out for default return key https://facebook.github.io/react-native/docs/textinput.html#returnkeytype
listViewDisplayed='auto' // true/false/undefined
fetchDetails={true}
renderDescription={row => row.description} // custom description render
onPress={(data, details = null) => { // 'details' is provided when fetchDetails = true
console.log(data, details);
this.setState(
{
address: data.description, // selected address
coordinates: `${details.geometry.location.lat},${details.geometry.location.lng}` // selected coordinates
}
);
}}
getDefaultValue={() => ''}
query={{
// available options: https://developers.google.com/places/web-service/autocomplete
key: 'AIzaS#################',
language: 'es', // language of the results
}}
styles={{
textInputContainer: {
width: '100%'
},
description: {
fontWeight: 'bold'
},
predefinedPlacesDescription: {
color: '#1faadb'
}
}}
currentLocation={true} // Will add a 'Current location' button at the top of the predefined places list
currentLocationLabel="Current location"
nearbyPlacesAPI='GooglePlacesSearch' // Which API to use: GoogleReverseGeocoding or GooglePlacesSearch
GoogleReverseGeocodingQuery={{
// available options for GoogleReverseGeocoding API : https://developers.google.com/maps/documentation/geocoding/intro
}}
GooglePlacesSearchQuery={{
// available options for GooglePlacesSearch API : https://developers.google.com/places/web-service/search
rankby: 'distance',
types: 'food'
}}
filterReverseGeocodingByTypes={['locality', 'administrative_area_level_3']} // filter the reverse geocoding results by types - ['locality', 'administrative_area_level_3'] if you want to display only cities
predefinedPlaces={[homePlace, workPlace]}
debounce={200} // debounce the requests in ms. Set to 0 to remove debounce. By default 0ms.
renderRightButton={() => <Text>Custom text after the input</Text>}
/>
</View>
<View style={styles.container2}>
<Text>
hola {this.setState.address}
</Text>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
width: '100%',
height: '100%',
},
welcome: {
fontSize: 40,
textAlign: 'center',
margin: 10,
color:'black',
},
instructions: {
textAlign: 'center',
color: 'black',
marginBottom: 5,
},
top: {
height: '50%',
justifyContent: 'center',
alignItems: 'center',
},
container2: {
height:'75%',
justifyContent: 'center',
},
buttonContainer: {
alignItems: 'center',
backgroundColor: 'rgba(255, 255,255, 0.5)',
padding: 1,
margin: 50,
borderRadius: 25,
borderWidth: 2,
borderColor: '#0B0B3B'
},
textoboton: {
textAlign: 'center',
color: 'black',
marginBottom: 5,
fontSize: 12
},
})
I've been also using another library with some differences
app.js
import React,{Component} from 'react';
import { Constants } from 'expo';
import Icon from 'react-native-vector-icons/FontAwesome';
import { View, Image, Text, StyleSheet, AsyncStorage, Button,ScrollView, TextInput, ActivityIndicator } from 'react-native';
import {
NavigationActions
} from 'react-navigation';
import { GoogleAutoComplete } from 'react-native-google-autocomplete';
import {Card, Input} from "react-native-elements";
import LocationItem from './locationItem';
export default class App extends React.Component {
state={
datos:[],
}
componentDidMount(){
this._loadedinitialstate().done();
}
_loadedinitialstate =async() => {
AsyncStorage.getItem('datos');
}
render() {
return (
<View style={styles.container}>
<GoogleAutoComplete apiKey={'AIzaSyB2HyNTBm1sQJYJkwOOUA1LXRHAKh4gmjU'} debounce={20} minLength={2} getDefaultValue={() => ''} onPress={(data, details = null) => { // 'details' is provided when fetchDetails = true
console.log(data, details);}} returnKeyType={'default'} fetchDetails={true}
>
{({
locationResults,
isSearching,
clearSearchs,
datos,
handleTextChange
}) => (
<React.Fragment>
<View style={styles.inputWrapper}>
<Input
style={styles.textInput}
placeholder="Ingresa tu direccion"
onChangeText={(datos) => this.setState({datos})}
value={datos}
/>
</View>
{isSearching && <ActivityIndicator size="large" color="red" />}
<ScrollView>
{locationResults.map(el => (
<LocationItem
{...el}
key={el.id}
/>
))}
</ScrollView>
</React.Fragment>
)}
</GoogleAutoComplete>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
textInput: {
height: 40,
width: 300,
borderWidth: 1,
paddingHorizontal: 16,
},
inputWrapper: {
marginTop: 80,
flexDirection: 'row'
},
});
locationitem.js
import React, { PureComponent } from 'react';
import { View, Alert, Text, StyleSheet, TouchableOpacity, AsyncStorage} from 'react-native';
class LocationItem extends PureComponent {
constructor(props) {
super(props);
this.state = {datos:''};
}
_handlePress = () => {
AsyncStorage.setItem('datos',datos)
}
render() {
return (
<TouchableOpacity style={styles.root} onPress={this._handlePress} >
<Text value={this.state.datos}> {this.props.description} </Text>
</TouchableOpacity>
);
}
}
const styles = StyleSheet.create({
root: {
height: 40,
borderBottomWidth: StyleSheet.hairlineWidth,
justifyContent: 'center'
}
})
export default LocationItem;
The source of both codes is here react-native-google-places-autocomplete enter link description here
Which code will be easy to use, and How can I solve my Issue (get the address) ??
Any Answer will be Helpful
first install
npm i react-native-google-places-autocomplete
then
import React from 'react';
import { View, Image } from 'react-native';
import { GooglePlacesAutocomplete } from 'react-native-google-places-autocomplete';
const homePlace = { description: 'Home', geometry: { location: { lat: 48.8152937, lng: 2.4597668 } }};
const workPlace = { description: 'Work', geometry: { location: { lat: 48.8496818, lng: 2.2940881 } }};
const GooglePlacesInput = () => {
return (
<GooglePlacesAutocomplete
placeholder='Search'
minLength={2} // minimum length of text to search
autoFocus={false}
returnKeyType={'search'} // Can be left out for default return key https://facebook.github.io/react-native/docs/textinput.html#returnkeytype
listViewDisplayed='auto' // true/false/undefined
fetchDetails={true}
renderDescription={row => row.description} // custom description render
onPress={(data, details = null) => { // 'details' is provided when fetchDetails = true
console.log(data, details);
}}
getDefaultValue={() => ''}
query={{
// available options: https://developers.google.com/places/web-service/autocomplete
key: 'YOUR API KEY',
language: 'en', // language of the results
types: '(cities)' // default: 'geocode'
}}
styles={{
textInputContainer: {
width: '100%'
},
description: {
fontWeight: 'bold'
},
predefinedPlacesDescription: {
color: '#1faadb'
}
}}
currentLocation={true} // Will add a 'Current location' button at the top of the predefined places list
currentLocationLabel="Current location"
nearbyPlacesAPI='GooglePlacesSearch' // Which API to use: GoogleReverseGeocoding or GooglePlacesSearch
GoogleReverseGeocodingQuery={{
// available options for GoogleReverseGeocoding API : https://developers.google.com/maps/documentation/geocoding/intro
}}
GooglePlacesSearchQuery={{
// available options for GooglePlacesSearch API : https://developers.google.com/places/web-service/search
rankby: 'distance',
types: 'food'
}}
filterReverseGeocodingByTypes={['locality', 'administrative_area_level_3']} // filter the reverse geocoding results by types - ['locality', 'administrative_area_level_3'] if you want to display only cities
predefinedPlaces={[homePlace, workPlace]}
debounce={200} // debounce the requests in ms. Set to 0 to remove debounce. By default 0ms.
renderLeftButton={() => <Image source={require('path/custom/left-icon')} />}
renderRightButton={() => <Text>Custom text after the input</Text>}
/>
);
}
After a long journey, these steps helped me solve the problem.
1) Install npm install react-native-google-places-autocomplete --save.
2) Then use this code below, as an element in your component.
<GooglePlacesAutocomplete
query={{
key: "GOOGLE_PLACES_API_KEY",
language: "en", // language of the results
}}
onPress={(data, details = null) => {
console.log(details);
console.log(data);
console.log("data.description",data.description.split(','));
}}
onFail={(error) => console.error(error)}
listViewDisplayed="false"
requestUrl={{
url:
"https://cors-
anywhere.herokuapp.com/https://maps.googleapis.com/maps/api",
useOnPlatform: "web",
}} // this in only required for use on the web. See https://git.io/JflFv
more for details.
styles={{
textInputContainer: {
backgroundColor: "rgba(0,0,0,0)",
borderTopWidth: 0,
borderBottomWidth: 0,
},
textInput: {
marginLeft: 0,
marginRight: 0,
height: 38,
color: "#5d5d5d",
fontSize: 16,
},
predefinedPlacesDescription: {
color: "#1faadb",
},
}}
/>
3) You may have the same problem that i had, which the list disappears when i try to select result. However, this is the action that solved this problem for me.
Commenting out onBlur on node_modules. path: "..\node_modules\react-native-google-places-autocomplete\GooglePlacesAutocomplete.js".
...
onFocus={onFocus ? () => {this._onFocus(); onFocus()} : this._onFocus}
// onBlur={this._onBlur}
underlineColorAndroid={this.props.underlineColorAndroid}
...
4) For saving the address you can check the console.log in the code, and then use setState or something like this.
5) For more information and options of these element check out this repository:
https://github.com/FaridSafi/react-native-google-places-autocomplete.
hope this will help for you :)
First of all, I used listViewDisplayed={false} because otherwise the list view get stuck with the results, and even on location press the list doesn't closes.
Second, to answer your question: The results are in the onPress function of GooglePlacesAutocomplete, you can update the state with the chosen location and then use it where ever you want in your component:
onPress={(data, details = null) => {
this.setState({
latitude: details.geometry.location.lat,
longitude: details.geometry.location.lng,
moveToUserLocation: true
});
this._gotoLocation();
}
}
As i wrote it, onPress also trigger the function that moves the map to display the new location.
import React, {Component} from 'react';
import { View, Image, Text, StyleSheet } from 'react-native';
import { GooglePlacesAutocomplete } from 'react-native-google-places-autocomplete';
export default class google extends Component {
constructor(props) {
super(props);
this.state = {
address:null,
lat:null,
lng:null,
}
}
getAdd(data){
console.log("add",data);
this.setState(
{
address: data.formatted_address, // selected address
lat: data.geometry.location.lat,// selected coordinates latitude
lng:data.geometry.location.lng, // selected coordinates longitute
}
);
console.log("this.state.address",this.state.address); ///to console address
console.log("this.state.coordinates",this.state.lat,this.state.lng); /// to console coordinates
}
render(){
return (
<View style={styles.container}>
<View style={styles.top}>
<GooglePlacesAutocomplete
placeholder='Search'
minLength={2} // minimum length of text to search
autoFocus={false}
fetchDetails={true}
returnKeyType={'default'}
onPress={(data, details = null) => { // 'details' is provided when fetchDetails = true
var data = details;
this.getAdd(data);
}}
query={{
// available options: https://developers.google.com/places/web-service/autocomplete
key: 'AIzaS#################',
language: 'en',
types: 'geocode', // default: 'geocode'
}}
listViewDisplayed={this.state.showPlacesList}
textInputProps={{
onFocus: () => this.setState({ showPlacesList: true }),
onBlur: () => this.setState({ showPlacesList: false }),
}}
styles={{
textInputContainer: {
width: '100%'
},
description: {
fontWeight: 'bold'
},
predefinedPlacesDescription: {
color: '#1faadb'
}
}}
currentLocation={true} // Will add a 'Current location' button at the top of the predefined places list
currentLocationLabel="Current location"
nearbyPlacesAPI='GooglePlacesSearch' // Which API to use: GoogleReverseGeocoding or GooglePlacesSearch
filterReverseGeocodingByTypes={['locality', 'administrative_area_level_3']} // filter the reverse geocoding results by types - ['locality', 'administrative_area_level_3'] if you want to display only cities
// predefinedPlaces={[]}
predefinedPlacesAlwaysVisible={true}
/>
</View>
{ this.state.address !=null ?(
<View style={styles.container2}>
<Text>
Address: {this.state.address}
</Text>
</View>
):null }
</View>
);
}
}
const styles = StyleSheet.create({
container: {
width: '100%',
height: '100%',
},
welcome: {
fontSize: 40,
textAlign: 'center',
margin: 10,
color:'black',
},
instructions: {
textAlign: 'center',
color: 'black',
marginBottom: 5,
},
top: {
height: '50%',
justifyContent: 'center',
alignItems: 'center',
},
container2: {
height:'75%',
justifyContent: 'center',
},
buttonContainer: {
alignItems: 'center',
backgroundColor: 'rgba(255, 255,255, 0.5)',
padding: 1,
margin: 50,
borderRadius: 25,
borderWidth: 2,
borderColor: '#0B0B3B'
},
textoboton: {
textAlign: 'center',
color: 'black',
marginBottom: 5,
fontSize: 12
},
})

How to set this.props.key into the Firebase database reference in react native

I have retrieved the values from the other component and displayed in the TextInput for users to edit the values which are the (itemTitle: this.props.title, itemIng: this.props.ing, itemSteps: this.props.steps) and now
I'm trying to update the values back to firebase after user pressed the button in modal. But I'm having a problem to get the firebase database reference, I'm able get the {this.props._key} from another component but when I write as a .child(itemKey) it's not working and shows "Can't find variable: itemKey" Does anyone has the similar problem?
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View,
ScrollView,
Button,
TouchableHighlight,
Modal,
TextInput,
ImageBackground
} from 'react-native';
import {Actions}from 'react-native-router-flux';
import firebase from './firebase';
const remote = 'http://l.rgbimg.com/cache1oCOq1/users/b/ba/ba1969/600/mxc1dae.jpg';
export default class RecipeDetails extends React.Component{
constructor(props){
super(props);
this.state={
modalVisible: false,
itemTitle: this.props.title,
itemIng: this.props.ing,
itemSteps: this.props.steps,
itemKey: this.props._key.toString(),
};
this.vegeRef = this.getRef().child('Vegetarian').child(itemKey);
this.fastRef = this.getRef().child('Fast Food');
this.hpRef = this.getRef().child('Healthy');
}
setModalVisible(visible){
this.setState({modalVisible:visible});
}
getRef(){
return firebase.database().ref();
}
updateItem(){
this.setModalVisible(true);
}
render(){
return(
<View style={styles.container}>
<Modal
visible={this.state.modalVisible}
animationType={'slide'}
onRequestClose={() => {}}
>
<Text>Edit the details and Update.</Text>
<TextInput
value={this.state.itemTitle}
onChangeText ={(itemTitle) => this.setState({ itemTitle })}
/>
<TextInput
value={this.state.itemIng}
onChangeText ={(itemIng) => this.setState({itemIng})}
/>
<TextInput
value={this.state.itemSteps}
onChangeText ={(itemSteps) => this.setState({itemSteps})}
/>
<View style={styles.modalContainer}>
<View style={styles.innerContainer}>
<Button onPress={() => {
this.vegeRef.update({title:this.state.itemTitle, ing:this.state.itemIng, steps:this.state.itemSteps});
this.setModalVisible(!this.state.modalVisible)
}}
title="Save Recipe"
>
</Button>
<Button
onPress={() => this.setModalVisible(!this.state.modalVisible)}
title="Cancel"
>
</Button>
</View>
</View>
</Modal>
<ImageBackground
style={{
flex: 1,
justifyContent: 'center',
paddingVertical: 35
}}
source={{ uri: remote }}
>
<ScrollView style={styles.container2} showsVerticalScrollIndicator={false}>
<Text style={styles.heading1}>
Ingredients
</Text>
<Text style={styles.heading2}>
{this.props.ing}
{this.props._key}
</Text>
<Text style={styles.heading1}>
Steps
</Text>
<Text style={styles.heading2}>
{this.props.steps}
</Text>
</ScrollView>
</ImageBackground>
<View style={styles.action}>
<TouchableHighlight
underlayColor='#24ce84'
onPress={this.updateItem.bind(this)}
>
<Text style = {styles.actionText}>Update Recipe</Text>
</TouchableHighlight>
</View>
</View>
);
}
}
This is the Firebase JSON format
"Vegetarian" : {
"-L3RaWBQchF5rKmVtpNk" : {
"ing" : "Aasaaaa",
"steps" : "Aa",
"title" : "Eeww"
},
"-L3WdmePSwkWNN4xB51M" : {
"ing" : "This is good",
"steps" : "Nice",
"title" : "Salad"
},
You need to change the value ot itemKey to this.state.itemKey and that will not be inside constructor as your are initialising the states in constructor. Also whenever you are calling any function like you have called update to update the values. Try to use the update query of firebase inside a function and use that in onPress event of Button react element. Please check modified code.
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View,
ScrollView,
Button,
TouchableHighlight,
Modal,
TextInput,
ImageBackground
} from 'react-native';
import { Actions } from 'react-native-router-flux';
import firebase from './firebase';
const remote = 'http://l.rgbimg.com/cache1oCOq1/users/b/ba/ba1969/600/mxc1dae.jpg';
export default class RecipeDetails extends React.Component {
constructor(props) {
super(props);
this.state = {
modalVisible: false,
itemTitle: this.props.title,
itemIng: this.props.ing,
itemSteps: this.props.steps,
itemKey: this.props._key.toString(),
};
// this.vegeRef = this.getRef();
this.fastRef = this.getRef().child('Fast Food');
this.hpRef = this.getRef().child('Healthy');
}
componentDidMount() {
this.getRef().child('Vegetarian').on('child_added', s => {
if (s.exists()) {
console.log(s.val()) // It will return the new updated object
console.log(s.key) // It will return the timestamp key
this.setState({
itemTitle: s.val().title,
itemIng: s.val().ing,
itemSteps: s.val().steps,
})
}
})
}
setModalVisible(visible) {
this.setState({ modalVisible: visible });
}
getVegRef = () => {
this.getRef().child('Vegetarian').child(this.state.itemKey)
}
getRef = () => {
return firebase.database().ref();
}
updateVeg = () => {
this.getVegRef().update(
{
title: this.state.itemTitle,
ing: this.state.itemIng,
steps: this.state.itemSteps
});
this.setModalVisible(!this.state.modalVisible)
}
updateItem() {
this.setModalVisible(true);
}
render() {
return (
<View style={styles.container}>
<Modal
visible={this.state.modalVisible}
animationType={'slide'}
onRequestClose={() => { }}
>
<Text>Edit the details and Update.</Text>
<TextInput
value={this.state.itemTitle}
onChangeText={(itemTitle) => this.setState({ itemTitle })}
/>
<TextInput
value={this.state.itemIng}
onChangeText={(itemIng) => this.setState({ itemIng })}
/>
<TextInput
value={this.state.itemSteps}
onChangeText={(itemSteps) => this.setState({ itemSteps })}
/>
<View style={styles.modalContainer}>
<View style={styles.innerContainer}>
<Button onPress={
this.updateVeg
}
title="Save Recipe"
>
</Button>
<Button
onPress={() => this.setModalVisible(!this.state.modalVisible)}
title="Cancel"
>
</Button>
</View>
</View>
</Modal>
<ImageBackground
style={{
flex: 1,
justifyContent: 'center',
paddingVertical: 35
}}
source={{ uri: remote }}
>
<ScrollView style={styles.container2} showsVerticalScrollIndicator={false}>
<Text style={styles.heading1}>
Ingredients
</Text>
<Text style={styles.heading2}>
{this.props.ing}
{this.props._key}
</Text>
<Text style={styles.heading1}>
Steps
</Text>
<Text style={styles.heading2}>
{this.props.steps}
</Text>
</ScrollView>
</ImageBackground>
<View style={styles.action}>
<TouchableHighlight
underlayColor='#24ce84'
onPress={this.updateItem.bind(this)}
>
<Text style={styles.actionText}>Update Recipe</Text>
</TouchableHighlight>
</View>
</View>
);
}
}