React Native TextInput, który akceptuje tylko znaki numeryczne

106

Potrzebuję TextInputkomponentu React Native , który pozwoli na wprowadzanie tylko znaków numerycznych (0 - 9). Mogę ustawić, keyboardTypedo numericktórego prawie mnie tam doprowadza, z wyjątkiem kropki (.). Jednak to nic nie powstrzymuje wklejania znaków nienumerycznych do pola.

To, co do tej pory wymyśliłem, to użycie OnChangeTextzdarzenia do spojrzenia na wprowadzony tekst. Usuwam z tekstu wszelkie znaki nienumeryczne. Następnie umieść tekst w polu stanu. Następnie zaktualizuj TextInputpoprzez jego Valuewłaściwość. Fragment kodu poniżej.

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

Wydaje się, że to działa, ale wygląda na włamanie. Czy jest inny sposób, aby to zrobić?

Terry
źródło
Ten przykład nigdy nie zadziałał. Czy udało ci się rozwiązać to w inny sposób?
amb
Zobacz też: stackoverflow.com/questions/40630918/…
hippietrail
Zauważ, że od React Native 0.54, większość sugerowanych tutaj odpowiedzi jest zepsuta: github.com/facebook/react-native/issues/18874 (do co najmniej 0.56, co jest najnowszą wersją w momencie pisania).
Tomty,
1
@sumitkumarpradhan Ten post na blogu sugeruje ustawienie typu klawiatury na „numeryczny”, co w rzeczywistości nie zapobiega wprowadzaniu tekstu. Możesz tam skopiować i wkleić wszystko, co chcesz.
jmathew
Używam keyboardType='numeric'prop w TextInput, aby wyświetlać tylko klawiaturę numeryczną (duh), a także zastępując teksty wyrażeniem regularnym, text.replace(/[^0-9]/g, '')jak zasugerowano poniżej, aby nikt nie mógł wklejać ciągów wewnątrz TextInput. Jak dotąd działa dobrze na React Native v0.62
keshavDulal

Odpowiedzi:

30

Jest to właściwy sposób, aby to zrobić, dopóki taki komponent (lub atrybut w TextInput) nie zostanie specjalnie opracowany.

Sieć ma typ „numer” dla elementu wejściowego, ale jest on oparty na sieci i natywny dla reagowania nie korzysta z widoku internetowego.

Możesz rozważyć utworzenie tego wejścia jako samodzielnego komponentu reagującego (może zadzwonić do NumberInput): umożliwi to ponowne użycie, a może nawet otwarcie źródła, ponieważ możesz utworzyć wiele TextInput, które mają różne filtry / kontrolery wartości.

Wadą natychmiastowej korekty jest zapewnienie prawidłowej informacji zwrotnej użytkownikowi, aby uniknąć nieporozumień co do tego, co stało się z jego wartością

Tjorriemorrie
źródło
Jak mogę ustawić z kodem kraju (np) może stanie ustawić kod kraju z wszelkich rekwizytów w składniku wprowadzania tekstu.
sejn
107

Użycie RegExp do zastąpienia dowolnej liczby niebędącej cyfrą jest szybsze niż użycie pętli for z białą listą, tak jak robią to inne odpowiedzi.

Użyj tego dla swojej obsługi onTextChange:

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

Test wydajności tutaj: https://jsperf.com/removing-non-digit-characters-from-a-string

Jake Taylor
źródło
Jak mogę zezwolić tylko na litery alfabetu angielskiego przy użyciu tej metody?
CraZyDroiD,
2
@CraZyDroiD po prostu dostosuj wyrażenie regularne. Jeśli chcesz dopasować tylko AZ, będziesz potrzebować czegoś takiego jaktext.replace(/[^A-Za-z]/g, '')
Jake Taylor,
1
keyboardType='numeric'Przekaż także prop do pola TextInput.
keshavDulal
94

Możesz to zrobić w ten sposób. Przyjmuje tylko wartości liczbowe i ogranicza się do 10 liczb według własnego uznania.

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

Możesz zobaczyć wprowadzoną wartość, wpisując następujący kod na swojej stronie:

{this.state.myNumber}

W funkcji onChanged () kod wygląda następująco:

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

Mam nadzieję, że jest to pomocne dla innych.

Venkatesh Somu
źródło
Mała poprawka: onChanged (text) {var newText = ''; var numbers = '0123456789'; if (text.length <1) {this.setState ({myNumber: ''}); } for (var i = 0; i <text.length; i ++) {if (numbers.indexOf (tekst [i])> -1) {newText = newText + text [i]; } this.setState ({myNumber: newText}); }}
Bheru Lal Lohar
1
Dobra odpowiedź, ale dlaczego nienawidzisz cyfry „9”
Stanley Luo
21
Ponieważ 7 nienawidzi 9?
boatcoder
4
Czy istnieje sposób, aby zapobiec migotaniu?
Waltari,
jesteście najlepszymi
kolesiami
18

React Native TextInput zapewnia właściwości keyboardType z następującymi możliwymi wartościami: domyślna klawiatura numeryczna klawiatura dziesiętna numeryczna adres e-mail klawiatura telefoniczna

więc w twoim przypadku możesz użyć keyboardType = 'number-pad' do akceptowania tylko liczb. Nie obejmuje to „.”

więc,

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

jest tym, czego musisz użyć w swoim przypadku.

Aby uzyskać więcej informacji, zapoznaj się z oficjalnym linkiem do dokumentu TextInput: https://facebook.github.io/react-native/docs/textinput#keyboardtype

Ganesh Krishna
źródło
10

Funkcja sprawdzania poprawności danych wejściowych:

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

Mam nadzieję, że to jest pomocne.

Abdul Karim Khan
źródło
to bardziej efektywny sposób, należy go stosować zamiast metody zapętlonej
Asif Ali
10

Zezwalaj tylko na liczby używające wyrażeń regularnych

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

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

Możesz chcieć mieć więcej niż jedną weryfikację


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

jasonleonhard
źródło
Nie ma potrzeby tworzenia tych dwóch pierwszych funkcji, możesz po prostu użyć:validations(value: string) { return /0/.test(value) && /^\d+$/.test(value) ? this.setState({ numColumns: value }) : false; }
Frederiko Cesar
2
@FrederikoCesar Rzuć okiem na zasadę pojedynczej odpowiedzialności
jasonleonhard
10

Pierwsze rozwiązanie

Możesz użyć keyboardType = 'numeric'do klawiatury numerycznej.

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

W pierwszym przypadku uwzględniane są znaki interpunkcyjne, np .: - . i -

Drugie rozwiązanie

Użyj wyrażenia regularnego, aby usunąć znaki interpunkcyjne.

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

Sprawdź link do przekąski

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

Vishal Dhanotiya
źródło
8

Uprzejme przypomnienie dla tych, którzy napotkali problem, że „onChangeText” nie może zmienić wartości TextInput zgodnie z oczekiwaniami na iOS: jest to w rzeczywistości błąd w ReactNative i został naprawiony w wersji 0.57.1. Zobacz: https://github.com/facebook/react-native/issues/18874

Skrzydło
źródło
To powinien być komentarz, a nie odpowiedź
Haris Nadeem
1
Przepraszam, że nie mam wystarczającej reputacji, aby skomentować to pytanie, więc otrzymuję odpowiedź, miejmy nadzieję, że zwrócę uwagę na ludzi szukających praktycznych rozwiązań.
Wing
Słuszna uwaga. Widzę, że do skomentowania potrzeba 50 punktów reputacji. Niestety nie mogę usunąć tego ograniczenia, ale mogę dać Ci 10 punktów reputacji i mam nadzieję, że usunę niektóre ograniczenia.
Haris Nadeem
weź jeszcze 10, aby uzyskać przepis na komentarz ... Cheers @Wing
Venkatesh Somu
Dzięki :) @VenkateshSomu
Wing
4
<TextInput autoCapitalize={'none'} maxLength={10} placeholder='Mobile Number'  value={this.state.mobile} onChangeText={(mobile) => this.onChanged(mobile)}/>

i onChanged metoda:

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 });
    }
}
Bheru Lal Lohar
źródło
Twoje rozwiązanie, chociaż rozwiązuje mój problem, daje ostrzeżenie: "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."nie wiem, co z tym zrobić. Możesz pomóc?
Mike
@Mike, które może spowodować jakieś zdarzenie, czy możesz udostępnić swój kod komponentu przez jsfiddle lub rnplay.org
Bheru Lal Lohar
Rozwiązałem to wkrótce po skomentowaniu tutaj, ale niestety mogę dowiedzieć się, w czym był problem.
Mike
użycie wyrażenia regularnego byłoby mądrzejszym wyborem
Asif Ali
4

Miałem ten sam problem w iOS, używając zdarzenia onChangeText do aktualizacji wartości tekstu wpisanego przez użytkownika. Nie byłem w stanie zaktualizować wartości TextInput, więc użytkownik nadal widziałby znaki nienumeryczne, które wpisał.

Dzieje się tak, ponieważ po naciśnięciu znaku nienumerycznego stan się nie zmieni, ponieważ this.setState używałby tej samej liczby (liczby, która pozostała po usunięciu znaków nienumerycznych), a następnie TextInput nie byłby ponownie renderowany.

Jedynym sposobem rozwiązania tego problemu było użycie zdarzenia keyPress, które ma miejsce przed zdarzeniem onChangeText i użycie w nim setState do zmiany wartości stanu na inny, zupełnie inny, wymuszając ponowne renderowanie, gdy wywołano zdarzenie onChangeText . Niezbyt zadowolony z tego, ale zadziałało.

Gustavo Franco
źródło
4
if (!/^[0-9]+$/.test('123456askm')) {
  consol.log('Enter Only Number');
} else {
    consol.log('Sucess');
}
ANKIT DETROJA
źródło
! / ^ [0-9] + $ /. Test ('123456askm') sprawdzi, czy łańcuch wejściowy jest liczbowy, czy nie .test (Twoja wartość)
ANKIT DETROJA
1
Cześć, proszę rozszerzyć swoją odpowiedź, dlaczego byłoby to rozwiązanie problemu OP. Pomoże to OP i przyszłym odwiedzającym witrynę. Dzięki!
d_kennetz
3

Napisałem tę funkcję, która okazała się pomocna, aby uniemożliwić użytkownikowi wprowadzenie czegokolwiek innego, niż byłbym skłonny zaakceptować. Użyłem też keyboardType="decimal-pad"i mójonChangeText={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 })
    }
}

Pierwszy ifblok to obsługa błędów w przypadku, gdy użytkownik usuwa cały tekst lub używa kropki dziesiętnej jako pierwszego znaku, lub jeśli próbuje wstawić więcej niż jedno miejsce dziesiętne, drugiif blok zapewnia, że ​​może wpisać jako dowolną liczbę liczb przed miejscem dziesiętnym, ale tylko do dwóch miejsc po przecinku.

Andrew M Yasso
źródło
2

Użycie RegExp do zastąpienia dowolnej cyfry. Uważaj, gdy następny kod da ci pierwszą znalezioną cyfrę, więc jeśli użytkownik wklei akapit z więcej niż jedną liczbą (xx.xx), kod da ci pierwszą liczbę. To pomoże, jeśli chcesz mieć coś w rodzaju ceny, a nie telefonu komórkowego.

Użyj tego dla swojej obsługi onTextChange:

onChanged (text) {
    this.setState({
        number: text.replace(/[^(((\d)+(\.)\d)|((\d)+))]/g,'_').split("_"))[0],
    });
}
Daniel Jose Padilla Peña
źródło
2

Możesz usunąć znaki nienumeryczne za pomocą wyrażenia regularnego

onTextChanged (text) {
    this.setState({
        myNumber: text.replace(/\D/g, ''),
    });
}
Anoop
źródło
2
const [text, setText] = useState('');

const onChangeText = (text) => {
  if (+text) {
    setText(text);
  }
};

<TextInput
  keyboardType="numeric"
  value={text}
  onChangeText={onChangeText}
/>

Powinno to zaoszczędzić na fizycznych klawiaturach

Zyfar Bektashov
źródło
1

To nie działa na IOS, setState -> render -> nie zmienia tekstu, ale może zmienić inne. Textinput nie może zmienić swojej wartości, gdy textOnChange.

przy okazji, to działa dobrze na Androida.

wv1124
źródło
Proszę wyjaśnić przykładowym kodem, aby inni mogli to zrozumieć.
Bheru Lal Lohar
1

Oto moja inna prosta odpowiedź, aby zaakceptować tylko liczby w polu tekstowym za pomocą wyrażeń regularnych.

onChanged(text){
    this.setState({ 
         myNumber: text.replace(/[^0-9]/g, '') 
    });
}
Venkatesh Somu
źródło
1

Spróbuj tego tylko dla liczb dziesiętnych / zmiennoprzecinkowych

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

}

abinthomas12914
źródło
0

Cóż, jest to bardzo prosty sposób sprawdzenia poprawności liczby innej niż 0.

if (+inputNum)

Będzie NaN, jeśli inputNum nie jest liczbą lub false, jeśli jest równe 0

Félix Andersson
źródło