How to provide Picker a default "Please select..." option?

30,378

Solution 1

You can add a conditional to your handleChangeOption so that it would only set state when the value is not 0 (the Please select an option... Picker). Something like:

handleChangeOption(val) {
  if (val !== 0) {
    this.setState({selectedValue: val});
  }
}

...
  
 <View style={Styles.row}>
    <Picker
       selectedValue={this.state.selectedValue}
       onValueChange={this.handleChangeOption}
       prompt='Options'}
       >
       <Picker.Item label='Please select an option...' value='0' />
       <Picker.Item label='option 1' value='1' />
       <Picker.Item label='option 2' value='2' />
    </Picker>
</View>

Solution 2

Here is how I just achieved it in React Native:

InputPicker Presentational Component:

import React from 'react'
import { StyleSheet, View, Text, Picker } from 'react-native'

const InputPicker = ({
    style,
    hasError,
    title,
    enabled,
    selectedValue,
    onValueChange,
    items,
    firstItem
}) => {
    if (!items || !Array.isArray(items)) return null

    const { container, errorContainer, errorText, pickerTitle, pickerItem } = styles

    return (
        <View style={[container, (hasError) ? errorContainer : null, style]}>
            <Text style={[pickerTitle, (hasError) ? errorText : null]}>
                {title}
            </Text>

            <Picker
                style={[pickerItem, (hasError) ? errorText : null]}
                selectedValue={selectedValue}
                onValueChange={onValueChange}
                enabled={enabled}>

                <Picker.Item key={'unselectable'} label={firstItem} value={0} />

                {items.map((c) => <Picker.Item key={c.id} label={c.label} value={c.label} />)}
            </Picker>
        </View>
    )
}

const styles = StyleSheet.create({
    container: {
        flex: 0,
        flexDirection: 'row',
        alignItems: 'center'
    },
    pickerTitle: {
        flex: 1,
        textAlign: 'right'
    },
    pickerItem: {
        flex: 2
    },
    errorContainer: {
        backgroundColor: '#F8DEE0',
        borderColor: '#DD0426',
        borderWidth: 1
    },
    errorText: {
        color: '#DD0426'
    }
})

export { InputPicker }

Parent Container View (using Formik form handler)

<CardSection style={{ flex: 0, alignItems: 'center' }}>
    <InputPicker
        title="City"
        enabled
        hasError={touched.person_city && errors.person_city}
        selectedValue={this.props.person_city}
        onValueChange={(value) => {
            this.props.setFieldValue('person_city', value)
            this.props.updateField({ prop: 'person_city', value })
        }}
        items={this.getCities()}
        firstItem="Select your city"
    />
</CardSection>

Parent Container this.getCities()

getCities() {
    const cities = [
        { id: 0, label: 'Nanaimo' },
        { id: 1, label: 'Victoria' },
        { id: 2, label: 'Ladysmith' }
    ]
    return cities
}

It works because it sets value to 0 if "Select your city" is picked, which makes it a falsy value which triggers touched.person_city && errors.person_city and puts it into an error state.

Share:
30,378
Luiz
Author by

Luiz

I am a passionate Computer Scientist. My main interests are web development, with emphasis on search engines and machine learning, and Internet of Things, with emphasis on agricultural automation. I also love to work with Operating Systems architectures and their subareas.

Updated on September 09, 2021

Comments

  • Luiz
    Luiz almost 3 years

    I'd like to make my Picker to show a "default option" on startup. That means: something like "Please select an option".

    I've tried to add a option manually with this phrase, but, this way the "default option" can be re-selected after selecting other options, like it was one of the real options. There is some way to do this?

    <View style={Styles.row}>
                <Picker
                    selectedValue={this.state.initialOption}
                    onValueChange={this.handleChangeOption}
                    prompt='Options'}
                  >
                  <Picker.Item label='Please select an option...' value='0' />
                  <Picker.Item label='option 1' value='1' />
                  <Picker.Item label='option 2' value='2' />
                </Picker>
    </View>
    
  • Luiz
    Luiz over 7 years
    This way, at the first press on the Picker, "Please select an option" would appear like it was a choosable option. I'd like to make it appear just before the user press it. Like a title, not an option itself.
  • Yo Wakita
    Yo Wakita over 7 years
    @Luiz I updated my answer. I think you are looking to not change state when the 'Please select an option' selection is chosen.
  • Luiz
    Luiz over 7 years
    Thanks. Seems like react-native doesn't provide the exact functionality, which would not even show "Please select and option" when the user pops up the Picker. But your solution help's me to workaround this.