2016-10-28 5 views
6

<TextInput/>を使ってリアクションネイティブでは<TextInput/>がフォーカスされている場合にのみ/を表示しようとしています。別の入力を入力した場合はそこにとどまります。現在はMM/YYです。 /の後に移動し、ユーザーが押し戻す場合は、/の前に数字を削除します。React Native:フォーマットカードの有効期限を/ withと使用する方法<TextInput/>?

これまでの実装にはどのようなアプローチが適していますか?ありがとう、答えを受け入れることを確認します。

私は次のことを試してみましたが、長さのエラーを取得し、2つの数字が入力された後にこれが唯一の/を追加します

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

長さの誤差は何ですか? – PaulBGD

+0

@PaulBGD 'if(text.length === 2 && this.state.cardExpiry.length === 1)'で '不定のプロパティ 'length'を読み取れません。 –

答えて

1

あなたはonChangeTextからこのFUNCを使用することができます。

コンストラクタ内でメソッドをバインドすることを忘れないでください。テキスト入力は次のようにする必要があります

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

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

あなたは実際に3つの関数は1つが第二、実際の値をフォーマットするためで、実際の値に戻ってフォーマットされた値を変換するためであり、第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

ない完全なソリューションが、それは同様の問題を解決 - マスキングBluetoothアドレス
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} 
    /> 
    } 

} 
関連する問題