2016-10-28 12 views
6

<TextInput/>'u kullanarak React Native, / öğesinin yalnızca <TextInput/> odaklandığı ve başka bir girdi girildiğinde orada kalmaya çalışıyorum. Bu durumda, kullanıcı üçüncü basamağı yazdığında MM/YY biçimindedir. /'dan sonra giderdi ve eğer kullanıcı geri basarsa /'dan önceki rakamı silecektir.React Native: <TextInput/> kullanarak/ile format kartı süresinin dolması nasıl yapılır?

Daha önce bahsedilen uygulama için doğru yaklaşım ne olurdu? Teşekkürler ve cevabı kabul ettiğinizden emin olabilirsiniz.

Denedim aşağıdaki ancak uzunluğunda bir hata alıyorum ve bu sadece / iki sonra basamak girildikten ekliyor:

_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

uzunlukta hatası nedir? – PaulBGD

+0

@PaulBGD "if (text.length === 2 && this.state.cardExpiry.length === 1)' 'undefined 'özelliğinin' özelliği 'okunamıyor' ifadesinde bir hata alıyorum. –

cevap

1

Eğer onChangeText bu fonksiyonları kullanılabilmektedir;

Yapıcının içinde yöntemi bağlamak için unutmayın;

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

Metin girişi gibi olmalıdır;

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

aslında 3 fonksiyonları bir saniye, gerçek değerini biçimlendirme içindir gerçek değerine geri biçimlendirilmiş değeri dönüştürmek içindir ve üçüncü girilen girdi şimdiye kadar geçerli olmak ya da olmamak sınanmadan için gerekli olan ihtiyaç . Örneğin girilen bir tarih girişi için mektup girişleri göz ardı edilmemelidir, ancak aynı zamanda bir ay için geçerli bir giriş olmadığı için 99 göz ardı edilmelidir. Aşağıdaki yapı (girilen giriş ona göre geçerli ve set devlet olup olmadığı bu örnek inputToValue fonksiyonunda hem çekleri) sizin için çalışması gerektiğini özel durum için So:

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

değil komple bir çözüm, ancak benzer sorunu çözer - maskeleme bluetooth adresi
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} 
    /> 
    } 

}