React native - add currency prefix to TextInput
Asked Answered
F

1

5

How can add a currency prefix to a TextInput in React Native? Here is an example of what I'm trying to achieve: enter image description here

To give a bit more details - the TextInput should have a default value, for instance £10. I would like the currency sign to always be there. At some point this value will be sent to a database so it should be converted to an integer.

My code so far (_renderSecondTile section):

import React, {Component} from 'react'
import {
    Text,
    View,
    ListView,
    ScrollView,
    StyleSheet,
    Image,
    TouchableHighlight,
    TextInput,
} from 'react-native'


class AppView extends Component {
    state = {
        isPlayerOneButtonActive: false,
        isPlayerTwoButtonActive: false,
        isThirdTileActive: false,
        textInputValue: '£10',
    }

     activateButton = buttonToActivate => {
        const newState = Object.assign(
            {},
            {
                isPlayerOneButtonActive: false,
                isPlayerTwoButtonActive: false,
            },
            {[buttonToActivate]: true},
        )
        this.setState(newState);
    }

    showThirdTile = tileToShow => {
        this.setState({isThirdTileActive: tileToShow});
    }

    _renderSecondTile = () => {
         if(this.state.isPlayerOneButtonActive || this.state.isPlayerTwoButtonActive) {
             return(
                 <TouchableHighlight>
                     <View style={[styles.step, styles.stepTwo]}>
                        <View style={{flex: 1}}>
                             <Text style={styles.heading}>Enter amount</Text>
                             <View style={styles.amountInputContainer}>
                                 <TextInput
                                     onKeyPress={() => {this.showThirdTile(true)}}
                                     style={styles.amountInput}
                                     maxLength = {3}
                                     value={this.state.textInputValue}
                                 />
                             </View>
                         </View>
                     </View>
                 </TouchableHighlight>
             )
         }
         else{
             return null;
         }
    }

    _renderThirdTile = () => {
        if(this.state.isSecondTitleActive){
            return(
                <View style={[styles.step, styles.stepThree]}>
                    <View style={{flex:1}}>
                        <Text style={styles.heading}>Third tile</Text>
                    </View>
                </View>
            )
        }
        else{
            return null;
        }
    }

    render(){
        const {isPlayerOneButtonActive} = this.state

        return (
            <ScrollView style={styles.container}>
                <View style={[styles.step, styles.stepOne]}>
                    <View style={{flex:1}}>
                        <Text style={styles.heading}>Pick player</Text>
                        <View style={styles.pickContainer}>
                            <TouchableHighlight onPress={() => {this.activateButton('isPlayerOneButtonActive')}}>
                                <Text>Player One</Text>
                            </TouchableHighlight>

                            <TouchableHighlight onPress={() => {this.activateButton('isPlayerTwoButtonActive')}}>
                                <Text>Player One</Text>
                            </TouchableHighlight>
                        </View>
                    </View>
                </View>

                {this._renderSecondTile()}

                {this._renderThirdTile()}
            </ScrollView>
        )
    }
}
Foote answered 27/1, 2017 at 17:31 Comment(0)
M
8

Try using this:

class AppView extends Component {
   state = {
        isPlayerOneButtonActive: false,
        isPlayerTwoButtonActive: false,
        isThirdTileActive: false,
        inputValue: 10,
    }

    inputChange = (e) => {
        this.setState({inputValue: parseInt(e.target.value)});
        if(!this.state.isThirdTileActive){
            this.showThirdTile(true);
        }
    }
    _renderSecondTile = () => {
         if(this.state.isPlayerOneButtonActive || this.state.isPlayerTwoButtonActive) {
             return(
                 <TouchableHighlight>
                     <View style={[styles.step, styles.stepTwo]}>
                        <View style={{flex: 1}}>
                             <Text style={styles.heading}>Enter amount</Text>
                             <View style={styles.amountInputContainer}>
                                 <TextInput
                                     style={styles.amountInput}
                                     maxLength = {3}
                                     onChange={this.inputChange}
                                     value={"£" + this.state.inputValue}
                             />
                             </View>
                         </View>
                     </View>
                 </TouchableHighlight>
             )
         }
         else{
             return null;
         }
     }
 }

Note: I left out anything that I didn't change so my answer would be easier to read.

Here, I changed the textInputValue to inputValue. Now that value is stored as an integer so it is ready to be sent to the database. Whenever that value is changed in the text input field, the state will be updated by inputChange. inputChange will also call showThirdTile if the third tile isn't already active. Finally, the value of the text input will be inputValue concatenated with "£". In my last answer, I added , in the string version of the integer at every thousandth place. Since you have a max length of 3 in the text input field, that isn't necessary any more. If you ever need to increase the max length, I'd use this to convert:

var cashify = function(amountIn){

    var amount = parseFloat(amountIn).toFixed(2);
    var splitAmount = amount.split(".")[0];
    var i = splitAmount.length-4;

    while(i>=0){
        splitAmount = splitAmount.slice(0,i+1) + "," + splitAmount.slice(i+1);
        i=i-3;
    }
    return "\u00A3" + splitAmount + "." + amount.split(".")[1];

}

I hope that helps!

Microbe answered 27/1, 2017 at 18:6 Comment(4)
Thanks for your answer - I've updated my question with a bit more details of what exactly I'm trying to achieveFoote
Hey, thanks for your updated answer. On first load I get inputValue from state just fine but onChange I get undefined. Seems that e.target.value won't work here.Foote
Won't the user able to place the cursor before the currency symbol?Villainous
thank you, this help me to start with my component!Petard

© 2022 - 2024 — McMap. All rights reserved.