React Native:如何使用<textinput>制作格式卡到期?

时间:2016-10-28 22:00:46

标签: javascript react-native payment react-jsx credit-card

在使用<TextInput/>的React Native中,我尝试仅在/聚焦时才显示<TextInput/>,并且如果输入了其他输入,则会保留在那里。目前,格式是MM/YY,因此当用户键入第三个数字时,它将在/之后,如果用户要按回,则会删除/之前的数字。

那么前面提到的实施方法是什么?谢谢你,一定会接受答案。

我尝试了以下操作,但收到了长度错误,这只是在输入两位数后添加/

  _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}
  />

4 个答案:

答案 0 :(得分:4)

在格式化中,您实际上需要3个函数,一个用于格式化实际值,第二个用于将格式化值转换回实际值,第三个用于检查到目前为止输入的输入是否有效。例如,对于日期输入,输入的字母输入应该被忽略,但同时99应该被忽略,因为它不是一个月的有效输入。因此,对于您的特定情况,以下结构应该适用于您(在此示例中,inputToValue函数都检查输入的输入是否有效并根据它设置状态):

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)}/>;
}

答案 1 :(得分:2)

不完整的解决方案,但它解决了类似的问题 - 屏蔽蓝牙地址
AB
AB:C
AB:CD:EF:GH:IJ:KL

/*
Usage:
import { TextInput } from '../utils/input'
const MaskedTextInput = withMask(TextInput)
<MaskedTextInput
  placeholder="Printer address"
  value={ printerId }
  onChange={this.handlePrinterAddressChange}
/>
*/

import React, { Component } from 'react'
import { View } from 'react-native'

export const withMask = (WrappedComponent) => class Wrapper extends Component {

  constructor(props) {
    super()
    this.state = { value: props.value }
  }

  onChange(event) {
    let value = event.nativeEvent.text
    const rawValue = event.nativeEvent.text.replace(/:/g, '')

    if (rawValue) {
      value = rawValue.match(/.{1,2}/g).join(':').toUpperCase()
    }

    this.setState({value})

    if (this.props.onChange) {
      event.nativeEvent.text = value
      this.props.onChange(event)
    }
  }

  render() {
    return <WrappedComponent 
      {...this.props} 
      onChange={(event) => this.onChange(event)}
      value={this.state.value}
    />
  }

}

答案 2 :(得分:1)

你可以使用onChangeText的这个函数;

不要忘记在构造函数中绑定方法;

this.fixCardText = this.fixCardText.bind(this)

fixCardText(text){
  if(text.length == 2 && this.state.text == 1){
    text += '/'
  }else if(text.length == 2 && this.state.text.length == 3){
    text = text.substring(0 , text.length-1)
  }
  this.setState({text:text}) 
}

你的文字输入应该是;

<TextInput
  value = {this.state.text}
  onChangeText={(text)=>{this.fixCardText(text)}}
/>

答案 3 :(得分:0)

您可以使用 2 个 TextInputs 代替一个以保持简单。

这是一种方法。

<TextInput
            onChangeText={() => alert('update state with Expiry Month')}
            placeholder="MM/"
            value={expiryMonth}
          />
          {expiryMonth.length > 0 && <Text> / </Text>}
          <TextInput
            onChangeText={() => alert('update state with Expiry Year or do whatever you need with whole Expiry Date')}
            placeholder="YY"
            value={expiryYear}
          />