2016-10-28 6 views
6

In React Native mit <TextInput/>, versuche ich / erscheinen nur, wenn die <TextInput/> ist fokussiert, und würde dort bleiben, wenn eine andere Eingabe eingegeben wird. Derzeit ist das Format MM/YY, so wenn der Benutzer die dritte Ziffer eingibt würde nach der / gehen, und wenn der Benutzer zurückdrücken würde, würde es die Ziffer vor der / löschen.React Native: Wie Formatkarte Ablauf mit/mit <TextInput/>?

Also, was wäre der richtige Ansatz zur Umsetzung zuvor erwähnt? Danke und werde sicher die Antwort akzeptieren.

Ich habe versucht, die folgenden aber einen Fehler mit einer Länge bekommen, und dies auch nur fügt / nach zwei Ziffern eingegeben wurden:

_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

Was ist der Fehler mit einer Länge? – PaulBGD

+0

@PaulBGD Ich erhalte einen Fehler bei 'if (text.length === 2 && this.state.cardExpiry.length === 1)' sagt 'Kann Eigenschaft 'Länge' von undefined nicht lesen.' –

Antwort

1

Sie diese func von onChangeText verwenden können;

Vergessen Sie nicht, Methode innerhalb Konstruktor zu binden;

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

Ihre Texteingabe sein sollte;

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

In formattion Sie brauchen eigentlich 3 Funktionen ist der tatsächliche Wert für die Formatierung, ist an zweiter Stelle für formatierten Wert zurück Istwert Umwandlung und die dritte für die Überprüfung, ob die eingegebene Eingang kann so weit gültig ist oder nicht benötigt wird, . Zum Beispiel für eine Datumseingabe sollten eingegebene Buchstabeneingaben ignoriert werden, aber gleichzeitig sollte 99 ignoriert werden, da es für einen Monat keine gültige Eingabe ist. Also für Ihren speziellen Fall sollte die folgende Struktur für Sie arbeiten (in diesem Funktionsbeispiel inputToValue beide überprüft, ob der eingegebene Eingangszustand gültig und stellen Sie nach, es ist):

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

Nicht vollständige Lösung, aber es löst ähnliches Problem - Maskierung bluetooth-Adresse
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} 
    /> 
    } 

}