2016-10-28 2 views
6

В React Native с использованием <TextInput/>, я пытаюсь сделать /, если только <TextInput/> сфокусирован и останется там, если в него будет введен другой вход. В настоящее время формат MM/YY, поэтому, когда пользователь вводит третью цифру, будет идти после /, и если пользователь должен был отжать, он удалит цифру до /.React Native: Как сделать окончание срока действия карты с помощью/<TextInput/>?

Итак, какой был бы правильный подход к реализации ранее упомянутых? Благодарю вас и обязательно отвечу.

Я попытался следующие, но получаю сообщение об ошибке с длиной, и это только добавление / после две цифры были введены:

_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)' say 'Невозможно прочитать свойство 'length' undefined.' –

ответ

1

вы можете использовать эту FUNC из 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)}} 
/> 
4

В formattion вы на самом деле нужны 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} 
    /> 
    } 

} 
Смежные вопросы