React Native TextInput只接受数字字符


101

我需要有一个TextInput只允许输入数字字符(0-9)的React Native组件。我可以设置keyboardTypenumeric几乎让我在那里除了周期输入()。但是,这并不能阻止将非数字字符粘贴到该字段中。

到目前为止,我想出的是使用OnChangeText事件来查看输入的文本。我从文本中删除了所有非数字字符。然后将文本放在状态字段中。然后TextInput通过它的Value属性更新。下面的代码段。

<TextInput 
  style={styles.textInput}
  keyboardType = 'numeric'
  onChangeText = {(text)=> this.onChanged(text)}
  value = {this.state.myNumber}
/> 

onTextChanged(text) {
  // code to remove non-numeric characters from text
  this.setState({myNumber: text})
}

这似乎可行,但似乎很简单。还有另一种方法吗?


从来没有这个例子可以工作。您设法以其他方式解决吗?
AMB


请注意,从React Native 0.54开始,这里建议的大多数答案都被破坏了:github.com/facebook/react-native/issues/18874(至少为0.56,这是撰写本文时的最新版本)。
Tomty,

1
@sumitkumarpradhan该博客文章建议将键盘类型设置为“数字”,这实际上并不能阻止文本输入。您可以将任何内容复制粘贴到那里。
jmathew

keyboardType='numeric'在TextInput中使用prop来仅显示数字键盘(duh),并text.replace(/[^0-9]/g, '')按照以下建议用正则表达式替换文本,以防止任何人在TextInput中粘贴字符串。到目前为止,在React Native v0.62上运行良好
keshavDulal

Answers:


28

在专门开发此类组件(或TextInput上的属性)之前,这是正确的方法。

Web的输入元素具有“数字”类型,但这是基于Web的,react-native不使用Web视图。

您可以考虑将输入单独创建为React组件(可能称为NumberInput):这将使您能够重用它甚至是开源,因为您可以创建许多具有不同值过滤器/检查器的TextInput。

立即纠正的弊端是确保向用户提供正确的反馈,以防止对其价值所发生的事情感到困惑


我如何与国家代码设置(即)可我能在文本输入组件的任何道具,设置国家代码。
sejn

100

像其他答案一样,使用RegExp替换任何非数字的速度比使用带白名单的for循环的速度更快。

将此用于您的onTextChange处理程序:

onChanged (text) {
    this.setState({
        mobile: text.replace(/[^0-9]/g, ''),
    });
}

此处的性能测试:https : //jsperf.com/removing-non-digit-characters-from-a-string


如何使用此方法只允许英文字母中的字母?
CraZyDroiD

2
@CraZyDroiD只需调整正则表达式即可。如果您只想匹配AZ,则需要类似text.replace(/[^A-Za-z]/g, '')
Jake Taylor

1
keyboardType='numeric'还将prop传递给TextInput字段。
keshavDulal

91

你可以这样 它只接受数字值,并根据需要限制为10个数字。

<TextInput 
   style={styles.textInput}
   keyboardType='numeric'
   onChangeText={(text)=> this.onChanged(text)}
   value={this.state.myNumber}
   maxLength={10}  //setting limit of input
/>

您可以通过在页面中编写以下代码来查看输入的值:

{this.state.myNumber}

在onChanged()函数中,代码如下所示:

onChanged(text){
    let newText = '';
    let numbers = '0123456789';

    for (var i=0; i < text.length; i++) {
        if(numbers.indexOf(text[i]) > -1 ) {
            newText = newText + text[i];
        }
        else {
            // your call back function
            alert("please enter numbers only");
        }
    }
    this.setState({ myNumber: newText });
}

我希望这对其他人有帮助。


小修正:onChanged(text){var newText =''; var number ='0123456789'; if(text.length <1){this.setState({myNumber:``}}); } for(var i = 0; i <text.length; i ++){if(numbers.indexOf(text [i])> -1)} {newText = newText + text [i]; } this.setState({myNumber:newText}); }
Bheru Lal Lohar

1
好的答案,但是为什么您讨厌数字'
Stanley Luo

19
因为7讨厌9?
boatcoder

4
是否有防止闪烁的方法?
Waltari

你是最好的小伙子
卡丹·伊克瓦努斯

17

React Native TextInput为keyboardType道具提供以下可能的值:默认数字键盘,十进制键盘,数字电子邮件地址,电话键盘

因此对于您的情况,您可以使用keyboardType ='数字键盘'仅接受数字。不包括“。”

所以,

<TextInput 
  style={styles.textInput}
  keyboardType = 'number-pad'
  onChangeText = {(text)=> this.onChanged(text)}
  value = {this.state.myNumber}
/>

是您必须使用的情况。

有关更多详细信息,请参考TextInput的官方文档链接:https : //facebook.github.io/react-native/docs/textinput#keyboardtype


10

验证输入的功能:

validateInputs(text, type) {
let numreg = /^[0-9]+$/;
  if (type == 'username') {
    if (numreg.test(text)) {
      //test ok
    } else {
      //test not ok
    } 
  }
}



<TextInput
   onChangeText={text => this.validateInputs(text, 'username')}
/>

我希望这是有帮助的。


那是一种更有效的方法,应该使用它而不是循环方法
Asif Ali,

10

仅允许使用正则表达式的数字

<TextInput 
  keyboardType = 'numeric'
  onChangeText = {(e)=> this.onTextChanged(e)}
  value = {this.state.myNumber}
/> 

onTextChanged(e) {
  if (/^\d+$/.test(e.toString())) { 
    this.setState({ myNumber: e });
  }
}

您可能要进行多个验证


<TextInput 
  keyboardType = 'numeric'
  onChangeText = {(e)=> this.validations(e)}
  value = {this.state.myNumber}
/> 

numbersOnly(e) {
    return /^\d+$/.test(e.toString()) ? true : false
}

notZero(e) {
    return /0/.test(parseInt(e)) ? false : true
}

validations(e) {
    return this.notZero(e) && this.numbersOnly(e)
        ? this.setState({ numColumns: parseInt(e) })
        : false
}


无需创建这两个函数,您可以使用:validations(value: string) { return /0/.test(value) && /^\d+$/.test(value) ? this.setState({ numColumns: value }) : false; }
Frederiko Cesar

2
@FrederikoCesar窥视单一责任原则
jasonleonhard

9

第一个解决方案

您可以使用keyboardType = 'numeric'数字键盘。

  <View style={styles.container}>
        <Text style={styles.textStyle}>Enter Number</Text>
        <TextInput
          placeholder={'Enter number here'}
          style={styles.paragraph}
          keyboardType="numeric"
          onChangeText={value => this.onTextChanged(value)}
          value={this.state.number}
        />
      </View>

在第一种情况下,包括标点符号,例如:- -

第二解决方案

使用正则表达式删除标点符号。

 onTextChanged(value) {
    // code to remove non-numeric characters from text
    this.setState({ number: value.replace(/[- #*;,.<>\{\}\[\]\\\/]/gi, '') });
  }

请检查小吃链接

https://snack.expo.io/@vishal7008/numeric-keyboard


8

谨此提醒那些遇到以下问题的人:“ onChangeText”无法按预期在iOS上更改TextInput值:这实际上是ReactNative中的错误,并已在版本0.57.1​​中修复。参考:https : //github.com/facebook/react-native/issues/18874


这应该是评论,而不是答案
Haris Nadeem

1
抱歉,我没有足够的声誉来评论这个问题,所以我最终给出了答案,希望引起人们对寻求可行解决方案的关注。

有道理。我看到一个人需要50个声誉才能发表评论。遗憾的是,我无法删除该限制,但是我可以给您10点声望,并希望删除一些限制。
哈里斯·纳德姆

再花10来获得评论意见...干杯@Wing
Venkatesh Somu

谢谢:) @VenkateshSomu

4
<TextInput autoCapitalize={'none'} maxLength={10} placeholder='Mobile Number'  value={this.state.mobile} onChangeText={(mobile) => this.onChanged(mobile)}/>

和onChanged方法:

onChanged(text){
   var newText = '';
   var numbers = '0123456789';
   if(text.length < 1){
     this.setState({ mobile: '' });
   }
   for (var i=0; i < text.length; i++) {
        if(numbers.indexOf(text[i]) > -1 ) {
             newText = newText + text[i];
        }
        this.setState({ mobile: newText });
    }
}

您的解决方案虽然解决了我的问题,但仍会发出警告:"This synthetic event is reused for performance reasons. If you're seeing this, you're accessing the property 'type' on a released/nullified synthetic event. This is set to null. If you must keep the original synthetic event around, use event.persist(). See fb>react-event-pooling for more information."我不知道该怎么办。你能帮我吗?
迈克”

@Mike某些事件可能会导致这种情况,您能否通过jsfiddle或rnplay.org共享组件代码
Bheru Lal Lohar

我在这里发表评论后不久就解决了这一问题,但不幸的是可以弄清楚问题出在哪里。
迈克,

使用正则表达式将是一个更明智的选择
Asif Ali,

4

我在iOS中遇到了同样的问题,使用onChangeText事件更新了用户键入的文本的值,但我无法更新TextInput的值,因此用户仍然会看到他键入的非数字字符。

这是因为,当按下非数字字符时,状态不会改变,因为this.setState将使用相同的数字(删除非数字字符后剩余的数字),然后TextInput将不会重新呈现。

我发现解决此问题的唯一方法是使用在onChangeText事件之前发生的keyPress事件,并在其中使用setState将状态值更改为另一个完全不同的状态,从而在调用onChangeText事件时强制重新呈现。对此不是很满意,但是它起作用了。


4
if (!/^[0-9]+$/.test('123456askm')) {
  consol.log('Enter Only Number');
} else {
    consol.log('Sucess');
}

!/ ^ [0-9] + $ /。test('123456askm')它将检查输入字符串是否为数字。test(您的值)
ANKIT-DETROJA '19

1
嗨,请扩大您的答案,以解决为什么这是OP的解决方案。这将有助于OP和网站的未来访问者。谢谢!
d_kennetz

3

我编写了此功能,发现该功能有助于防止用户输入我不愿意接受的任何内容。我也用keyboardType="decimal-pad"我的onChangeText={this.decimalTextChange}

  decimalTextChange = (distance) =>
{
    let decimalRegEx = new RegExp(/^\d*\.?\d*$/)
    if (distance.length === 0 || distance === "." || distance[distance.length - 1] === "."
        && decimalRegEx.test(distance)
    ) {
        this.setState({ distance })
    } else {
        const distanceRegEx = new RegExp(/^\s*-?(\d+(\.\d{ 1, 2 })?|\.\d{ 1, 2 })\s*$/)
        if (distanceRegEx.test(distance)) this.setState({ distance })
    }
}

if对于用户删除所有文本或使用小数点作为第一个字符的事件,第一个块是错误处理,或者,如果他们尝试输入多个小数位,则第二个if块确保他们可以输入小数点前需要多少个数字,但小数点后最多只能有两个小数位。


2

使用RegExp替换任何非数字。请注意,下一个代码将为您提供他找到的第一个数字,因此,如果用户粘贴一个具有多个数字(xx.xx)的段落,则该代码将为您提供第一个数字。如果您想要价格而不是手机,这将有所帮助。

将此用于您的onTextChange处理程序:

onChanged (text) {
    this.setState({
        number: text.replace(/[^(((\d)+(\.)\d)|((\d)+))]/g,'_').split("_"))[0],
    });
}

2

您可以使用正则表达式删除非数字字符

onTextChanged (text) {
    this.setState({
        myNumber: text.replace(/\D/g, ''),
    });
}

1

这不适用于IOS,setState-> render->不能更改文本,但是可以更改其他文本。当textOnChange时,textinput不能更改其自身值。

顺便说一句,这在Android上运作良好。


请用示例代码说明,以便其他人可以理解。
Bheru Lal Lohar



1

对于十进制/浮点数,仅尝试此

    onChangeMyFloatNumber(text){
let newText = '';
let numbers = '0123456789.';

for (var i=0; i < text.length; i++) {
    if(numbers.indexOf(text[i]) > -1 ) {
        newText = newText + text[i];
        if(text[i]=="."){
          numbers = '0123456789'
        }
    }
    else {
        // your call back function
        alert("please enter numbers only");
    }
}
this.setState({ MyFloatNumber: newText });

}


0

好吧,这是一种验证不等于0的数字的非常简单的方法。

if (+inputNum)

如果inputNum不是数字,则为NaN;如果为0,则为false

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.