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

Здається, це спрацьовує, але, здається, це хак. Чи є інший спосіб зробити це?


Ніколи не працював цей приклад. Чи вдалося це вирішити по-іншому?
амбіція


Зауважте, що станом на React Native 0.54, більшість запропонованих тут відповідей розбиті: github.com/facebook/react-native/issues/18874 (щонайменше до 0,56, що є найновішою версією на момент написання статті).
Томті,

1
@sumitkumarpradhan Цей допис у блозі пропонує встановити тип клавіатури на "числовий", що насправді не перешкоджає введенню тексту. Ви можете скопіювати туди все, що завгодно.
jmathew

Я використовую keyboardType='numeric'prop у TextInput, щоб показувати лише цифрову клавіатуру (duh), а також замінюючи тексти регулярними виразами, text.replace(/[^0-9]/g, '')як пропонується нижче, щоб запобігти кожному вставці рядків всередину TextInput. Поки що чудово працює над React Native v0.62
keshavDulal

Відповіді:


28

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

Мережа має тип `` число '' для вхідного елемента, але це веб-заснована і реакція-рідна не використовує веб-перегляд.

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

Недоліком негайної корекції є забезпечення правильного зворотного зв’язку з користувачем, щоб запобігти плутанині щодо того, що сталося з його цінністю


Як я можу встановити код країни. (Тобто) чи можу я встановити код країни за допомогою будь-якого реквізиту в компоненті введення тексту
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 просто відрегулюйте регулярний вираз. Якщо ви хочете лише відповідати AZ, вам знадобиться щось на зразокtext.replace(/[^A-Za-z]/g, '')
Jake Taylor

1
Також передайте keyboardType='numeric'prop в поле TextInput.
keshavDulal

92

Ви можете зробити це так. Він приймає лише числові значення та обмежує 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'; 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
Хороша відповідь, але чому ви ненавидите цифру '9'
Стенлі Ло

19
Тому що 7 ненавиджу 9?
човновий кодер

4
Чи є спосіб запобігти мерехтінню?
Waltari

ви найкращі хлопці
Хадам Іхванус

17

React Native TextInput надає реквізити клавіатури з наступними можливими значеннями: цифрова клавіатура за замовчуванням десяткова цифрова цифрова адреса електронна адреса електронна адреса

тож для вашого випадку ви можете використовувати 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')}
/>

Сподіваюся, це корисно.


це більш ефективний спосіб, його слід дотримуватися замість циклу
Асіф Алі,

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; }
Фредеріко Сезар

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


Це повинен бути коментар, а не відповідь
Haris

1
Вибачтесь, що у мене недостатньо репутації, щоб коментувати це питання, тому я в кінцевому підсумку отримаю відповідь, сподіваюся, щоб звернути увагу на людей, які шукають працездатні рішення.
Крило

Справедливий момент. Я бачу, що для коментарів потрібно було б 50 репутації. На жаль, я не можу зняти це обмеження, але я можу надати вам 10 репутації і, сподіваюся, скасувати деякі обмеження.
Haris

візьміть ще 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

Я вирішив це незабаром після коментарів тут, але, на жаль, можу зрозуміти, в чому була проблема.
Майк

використання регулярного виразу було б розумнішим вибором
Асіф Алі

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

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.

до речі, це добре працює на Android.


Будь ласка, поясніть на прикладі коду, щоб інші могли зрозуміти.
Bheru Lal Lohar


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

}


0

Ну, це дуже простий спосіб перевірити число, відмінне від 0.

if (+inputNum)

Це буде NaN, якщо inputNum не є числом, або false, якщо воно дорівнює 0

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.