React Native TextInput, который принимает только числовые символы

101

Мне нужен TextInputкомпонент React Native , который позволяет вводить только числовые символы (0–9). Я могу установить keyboardTypeна numericкоторый почти заставляет меня есть для ввода в течение периода , за исключением (.). Однако это не мешает вставлять в поле нечисловые символы.

До сих пор я придумал использовать 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
См. Также: stackoverflow.com/questions/40630918/…
hippietrail 01
Обратите внимание, что с React Native 0.54 большинство предлагаемых здесь ответов не работают: github.com/facebook/react-native/issues/18874 (не менее 0,56, что является новейшей версией на момент написания).
Tomty
1
@sumitkumarpradhan В этом сообщении блога предлагается установить тип клавиатуры «числовой», что фактически не препятствует вводу текста. Вы можете скопировать туда все, что захотите.
jmathew
Я использую keyboardType='numeric'опору в TextInput, чтобы отображать только числовую клавиатуру (да), а также заменяю тексты регулярным выражением, text.replace(/[^0-9]/g, '')как предлагается ниже, чтобы никто не вставлял строки внутри TextInput. Пока работает нормально на React Native v0.62
keshavDulal

Ответы:

28

Это правильный способ делать это до тех пор, пока такой компонент (или атрибут в TextInput) не будет специально разработан.

В Интернете для элемента ввода есть «числовой» тип, но он основан на веб-технологиях и не использует веб-представление.

Вы можете подумать о создании этого ввода как собственного компонента реакции (возможно, вызовите NumberInput): это позволит вам повторно использовать его или, возможно, даже открыть исходный код, поскольку вы можете создать много TextInputs, которые имеют разные фильтры / средства проверки значений.

Обратной стороной немедленного исправления является обеспечение правильной обратной связи с пользователем во избежание путаницы относительно того, что случилось с его значением.

Tjorriemorrie
источник
Как я могу установить код страны (т.е. могу ли я установить код страны с любыми реквизитами в компоненте ввода текста
sejn
101

Использование 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 просто отрегулируйте регулярное выражение. Если вы хотите соответствовать только А-Я, вам понадобится что-то вродеtext.replace(/[^A-Za-z]/g, '')
Джейк Тейлор
1
Также передайте keyboardType='numeric'опору в поле 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 (текст) {var newText = ''; var числа = '0123456789'; если (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}); }}
Беру Лал Лохар
1
Хороший ответ, но почему вы ненавидите число «9»
Стэнли Луо
19
Потому что 7 ненавидят 9?
boatcoder
4
Есть ли способ предотвратить мерцание?
Waltari
вы лучшие ребята
Хадам Ихванус
17

React Native TextInput предоставляет свойства keyboardType со следующими возможными значениями: цифровая клавиатура по умолчанию, десятичная клавиатура, числовой адрес электронной почты, телефонная клавиатура.

поэтому в вашем случае вы можете использовать keyboardType = 'number-pad' для приема только чисел. Это не включает '.'

так,

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

Надеюсь, это поможет.

Абдул Карим Хан
источник
это более эффективный способ, его следует использовать вместо метода зацикливания
Асиф Али
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» не может изменить значение TextInput должным образом на iOS: на самом деле это ошибка в ReactNative, которая была исправлена ​​в версии 0.57.1. Обратитесь к: https://github.com/facebook/react-native/issues/18874

Крыло
источник
Это должен быть комментарий, а не ответ
Харис Надим
1
Приношу извинения за то, что у меня недостаточно репутации, чтобы прокомментировать вопрос, поэтому я получаю ответ, надеюсь, привлечь внимание людей, ищущих работающие решения.
Крыло
Честная оценка. Я вижу, что для комментария нужно 50 репутации. К сожалению, я не могу снять это ограничение, но я могу дать вам 10 репутации и, надеюсь, снять некоторые ограничения.
Харис Надим
возьмите еще 10, чтобы получить комментарий ... Ура @Wing
Венкатеш Сому
Спасибо :) @VenkateshSomu
Wing
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
Лал Лохар
Я решил это вскоре после комментария, но, к сожалению, могу понять, в чем проблема.
Майк
использование регулярного выражения было бы более
Асиф Али
4

У меня была такая же проблема в iOS, когда я использовал событие onChangeText для обновления значения текста, введенного пользователем, я не мог обновить значение TextInput, поэтому пользователь все равно будет видеть нечисловые символы, которые он набрал.

Это произошло потому, что при нажатии нечислового символа состояние не изменилось, поскольку this.setState будет использовать тот же номер (число, которое осталось после удаления нечисловых символов), и тогда TextInput не будет повторно отображаться.

Единственный способ решить эту проблему, который я нашел, - это использовать событие keyPress, которое происходит перед событием onChangeText, и в нем использовать setState для изменения значения состояния на другое, совершенно другое, заставляя повторную визуализацию при вызове события onChangeText . Не очень доволен этим, но это сработало.

Густаво Франко
источник
4
if (!/^[0-9]+$/.test('123456askm')) {
  consol.log('Enter Only Number');
} else {
    consol.log('Sucess');
}
АНКИТ-ДЕТРОЯ
источник
! / ^ [0-9] + $ /. Test ('123456askm') он проверит, является ли входная строка числовой или нет .test (ваше значение)
ANKIT-DETROJA
1
Привет, пожалуйста, расскажите подробнее о своем ответе, почему это могло бы стать решением проблемы OP. В этом помогут ОП и будущие посетители сайта. Благодарность!
d_kennetz 08
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, ''),
    });
}
Anoop
источник
1

Это не работает на IOS, setState -> render -> не изменяет текст, но может изменять другие. Текстовый ввод не может изменить свое значение, когда textOnChange.

Кстати, это хорошо работает на Android.

wv1124
источник
Пожалуйста, объясните пример кода, чтобы другие могли понять.
Бхеру Лал Лохар
1

Вот мой другой простой ответ: принимать только числа в текстовом поле с использованием регулярных выражений.

onChanged(text){
    this.setState({ 
         myNumber: text.replace(/[^0-9]/g, '') 
    });
}
Венкатеш Сому
источник
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 });

}

абинтомы12914
источник
0

Что ж, это очень простой способ проверить число, отличное от 0.

if (+inputNum)

Это будет NaN, если inputNum не является числом, или false, если это 0

Феликс Андерссон
источник