React Native: How to make format card expiration with / using <TextInput/>?

credit-card, javascript, payment, react-native, reactjs

Solution

In formattion you actually need 3 functions one is for formatting the actual value, second is for converting formatted value back to actual value and the third is needed for checking whether the entered input so far can be valid or not. For example for a date input entered letter inputs should be disregarded, but at the same time 99 should be disregarded as it is not a valid input for a month. So for your specific case the following structure should work for you (in this example `inputToValue` function both checks whether the entered input is valid and set state according to it):

formatFunction(cardExpiry = ""){
   //expiryDate will be in the format MMYY, so don't make it smart just format according to these requirements, if the input has less than 2 character return it otherwise append `/` character between 2nd and 3rd letter of the input.
   if(cardExpiry.length < 2){
    return cardExpiry;
   }
   else{
    return cardExpiry.substr(0, 2) + "/" + (cardExpiry.substr(2) || "")
   }
}

inputToValue(inputText){
    //if the input has more than 5 characters don't set the state
    if(inputText.length < 6){
         const tokens = inputText.split("/");
         // don't set the state if there is more than one "/" character in the given input
         if(tokens.length < 3){
            const month = Number(tokens[1]);
            const year = Number(tokens[2]);
            //don't set the state if the first two letter is not a valid month
            if(month >= 1 && month <= 12){
               let cardExpiry = month + "";
               //I used lodash for padding the month and year with  zero               
               if(month > 1 || tokens.length === 2){
                    // user entered 2 for the month so pad it automatically or entered "1/" convert it to 01 automatically
                    cardExpiry = _.padStart(month, 2, "0");   
               }
               //disregard changes for invalid years
               if(year > 1 && year <= 99){
                   cardExpiry += year;
               }
               this.setState({cardExpiry});
            }
         }
    }
}

render(){
    let {cardExpiry} = this.state;
    return <TextInput
       value = {this.formatFunction(cardExpiry)}
       onChangeText={this.inputToValue.bind(this)}/>;
}

Problem

In React Native using `<TextInput/>`, I am trying to make `/` appear only when the `<TextInput/>` is focused, and would stay there if another input is entered in. Currently, the format is `MM/YY`, so when the user types the third digit, it would go after the `/`, and if the user were to press back, it would delete the digit before the `/`. So what would be the right approach to implementing previously mentioned? Thank you and will be sure to accept the answer. I tried the following but getting an error with length, and this is only adding `/` after two digits have been entered: ``` _changeCardExpiry(value) { if (value.indexOf('.') >= 0 || value.length > 5) { return; } if (value.length === 2 && this.state.cardExpiry.length === 1) { value += '/' } //then update state cardExpiry } ... <TextInput onChangeText={this._changeCardExpiry.bind(this)} placeholder='MM/YY' value={cardExpiry} /> ```

Original source