vbernal
vbernal

Reputation: 723

Why is my Text Input field locked for editing?

I'm still new to react native and I have a problem working with picker and text input together.

I get a list of cars and when I select a particular car, in the field below is set the value of km of that selected car.

The problem is that this field needs to be allowed to edit, that is, the user wants to change the kilometers of that car he can.

But at the moment my input field is blocked for editing, I made a gif that shows when I select a car and I try to edit the km and it does not work.

Current behavior

Below my code, I don't know why it is not working on the snack.io so that's why I put it all here:

import * as React from 'react';
import {
    Text,
    View,
    ImageBackground,
    Image,
    TextInput,
    Dimensions,
    TouchableOpacity,
    Alert,
    Button,
    Picker,
    Animated,
    Platform,
    TouchableWithoutFeedback,
    StyleSheet
} from 'react-native';
import axios from 'axios';

const { width: WIDTH } = Dimensions.get('window')

export default class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            descViatura: '',
            descViaturaIOS: 'Select the car',
            modalIsVisible: false,
            modalAnimatedValue: new Animated.Value(0),
        };
    }

    componentDidMount() {
        axios
            .get(
                `${'http://www.mocky.io/v2/5d304a3c3200005600204352'}`,
                {
                    headers: {
                        'Content-Type': 'application/json',
                    },
                }
            )
            .then(jsonResponse => {
                this.setState({
                    viaturas: true,
                    dataSource: jsonResponse.data['data'],
                });
            })
            .catch(error => console.log(error));
    }

    onValueChange(value: string, index: string) {
        let kms = this.state.dataSource[index].km_actuais
        let marcaSelecionada = this.state.dataSource[index].marca
        let modeloSelecionado = this.state.dataSource[index].modelo
        let matriculaSelecionada = this.state.dataSource[index].matricula

        let viaturaSelecionada = marcaSelecionada + ' ' + modeloSelecionado + ' ' + matriculaSelecionada

        this.setState({
            descViatura: value,
            km_actuais: kms,
            descViaturaIOS: viaturaSelecionada
        });

    }

    _handlePressOpen = () => {
        if (this.state.modalIsVisible) {
            return;
        }

        this.setState({ modalIsVisible: true }, () => {
            Animated.timing(this.state.modalAnimatedValue, {
                toValue: 1,
                duration: 200,
                useNativeDriver: true,
            }).start();
        });
    };

    _handlePressDone = () => {
        Animated.timing(this.state.modalAnimatedValue, {
            toValue: 0,
            duration: 150,
            useNativeDriver: true,
        }).start(() => {
            this.setState({ modalIsVisible: false });
        });
    };


    render() {
        let list_viaturas = this.state.dataSource;
        if (typeof (list_viaturas) !== undefined) {
            list_viaturas = [list_viaturas][0];
        }

        let km_selected = typeof (this.state.km_actuais) !== 'undefined' ? this.state.km_actuais : 0

        let modalPicker = null
        if (Platform.OS === 'ios') {
            modalPicker = (
                <View style={{
                    flexDirection: 'row',
                    justifyContent: 'center',
                    alignItems: 'center',
                    height: 45,
                    marginTop: 30,
                    width: '90%',
                    backgroundColor: '#ecf0f1',
                    borderWidth: 1,
                }}>
                    <TouchableWithoutFeedback onPress={this._handlePressOpen}>
                        <View
                            style={{
                                alignItems: 'center',
                                width: '100%',
                            }}>
                            <Text style={{ paddingLeft: 15, fontSize: 14 }}>{this.state.descViaturaIOS}</Text>
                        </View>
                    </TouchableWithoutFeedback>
                </View>
            )
        } else {
            modalPicker = (
                null
            )
        }

        _maybeRenderModal = () => {
            if (!this.state.modalIsVisible) {
                return null;
            }

            const { modalAnimatedValue } = this.state;
            const opacity = modalAnimatedValue;
            const translateY = modalAnimatedValue.interpolate({
                inputRange: [0, 1],
                outputRange: [300, 0],
            });

            return (
                <View
                    style={StyleSheet.absoluteFill}
                    pointerEvents={this.state.modalIsVisible ? 'auto' : 'none'}>
                    <TouchableWithoutFeedback onPress={this.props.onCancel}>
                        <Animated.View style={[styles.overlay, { opacity }]} />
                    </TouchableWithoutFeedback>
                    <Animated.View
                        style={{
                            width: '100%',
                            position: 'absolute',
                            bottom: 0,
                            left: 0,
                            transform: [{ translateY }],

                        }}>
                        <View style={styles.toolbar}>
                            <View style={styles.toolbarRight}>
                                <Button title="OK" onPress={this._handlePressDone} />
                            </View>
                        </View>
                        <Picker
                            style={{ width: WIDTH, backgroundColor: '#e1e1e1', top: 0 }}
                            selectedValue={this.state.descViatura}
                            itemStyle={{
                                fontSize: 18,
                                color: '#000',
                            }}
                            onValueChange={this.onValueChange.bind(this)}>
                            {list_viaturas.map((item, key) => {
                                return (
                                    <Picker.Item
                                        label={item.marca + ' ' + ' ' + item.modelo + ' ' + item.matricula}
                                        value={item.id}
                                        key={key}
                                    />
                                );
                            })}
                        </Picker>
                    </Animated.View>
                </View>
            )
        }

        return (
            <View style={styles.container}>
                {modalPicker}
                <View style={styles.inputText2}>
                    <TextInput
                        style={styles.input}
                        value={km_selected}
                        keyboardType={'numeric'}
                        placeholder={"0"}
                        placeholderTextColor={'#000'}
                        underlineColorAndroid='transparent'
                    />
                </View>
                {_maybeRenderModal()}
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#fff',
        padding: 8,
    },
    overlay: {
        ...StyleSheet.absoluteFillObject,
        backgroundColor: 'rgba(0,0,0,0.65)',
    },
    toolbar: {
        width: '100%',
        backgroundColor: '#f1f1f1',
        paddingVertical: 5,
        paddingHorizontal: 15,
    },
    toolbarRight: {
        alignSelf: 'flex-end',
    },
    inputText2: {
        flexDirection: 'row',
        justifyContent: 'center',
        alignItems: 'center',
        height: 45,
        marginTop: 30,
        width: '90%',
        backgroundColor: '#ecf0f1',
        borderWidth: 1,
    },
});

This gif is with accelerated recording, but you can see that I click the button to delete the number and nothing happens.

Accelerated gif

Upvotes: 1

Views: 1677

Answers (2)

Anurag Chutani
Anurag Chutani

Reputation: 595

Change your TextInput with

    <TextInput
        style={styles.input}
        value={km_selected}
        keyboardType={'numeric'}
        placeholder={"0"}
        onChangeText={(text) => { this.setState({ km_selected: text }) }}
        placeholderTextColor={'#000'}
        underlineColorAndroid='transparent'
    />

Upvotes: 0

Henfs
Henfs

Reputation: 5411

I believe the issue is that you are providing a value on TextInput.

As you can read here: https://facebook.github.io/react-native/docs/textinput#value

The value to show for the text input. TextInput is a controlled component, which means the native value will be forced to match this value prop if provided. For most uses, this works great, but in some cases this may cause flickering - one common cause is preventing edits by keeping value the same. In addition to simply setting the same value, either set editable={false}, or set/update maxLength to prevent unwanted edits without flicker.

I can't test for you, I'm sorry, but try to set editable={true}. If it doesn't work, remove value and use another way through JavaScript to get the value from Picker to show it there.

Upvotes: 1

Related Questions