Reagieren Sie auf Native TextInput, das nur numerische Zeichen akzeptiert

85

Ich benötige eine React Native- TextInputKomponente, mit der nur numerische Zeichen (0 - 9) eingegeben werden können. Ich kann das einstellen, keyboardTypeauf numericdas ich bis auf den Punkt (.) Fast zur Eingabe komme. Dies verhindert jedoch nicht, dass nicht numerische Zeichen in das Feld eingefügt werden.

Was ich mir bisher ausgedacht habe, ist, das OnChangeTextEreignis zu verwenden, um den eingegebenen Text zu betrachten. Ich entferne alle nicht numerischen Zeichen aus dem Text. Fügen Sie dann den Text in ein Statusfeld ein. Aktualisieren TextInputSie dann die ValueEigenschaft through . Code-Snippet unten.

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

Dies scheint zu funktionieren, aber es scheint wie ein Hack. Gibt es einen anderen Weg, dies zu tun?

Terry
quelle
Ich habe dieses Beispiel nie zum Laufen gebracht. Haben Sie es geschafft, es anders zu lösen?
Amb
Beachten Sie, dass ab React Native 0.54 die meisten der hier vorgeschlagenen Antworten fehlerhaft sind: github.com/facebook/react-native/issues/18874 (bis zu mindestens 0.56, der neuesten Version zum Zeitpunkt des Schreibens).
Tomty
Schauen wir uns
1
@sumitkumarpradhan In diesem Blog-Beitrag wird vorgeschlagen, den Tastaturtyp auf "numerisch" zu setzen, was die Texteingabe nicht wirklich verhindert. Sie können kopieren und alles einfügen, was Sie wollen.
Jmathew

Antworten:

21

Dies ist der richtige Weg, bis eine solche Komponente (oder ein solches Attribut im TextInput) speziell entwickelt wurde.

Das Web hat den Typ 'number' für das Eingabeelement, aber das ist webbasiert und React-Native verwendet keine Webansicht.

Sie können diese Eingabe auch als eigenständige Reaktionskomponente erstellen (möglicherweise NumberInput aufrufen). Auf diese Weise können Sie sie wiederverwenden oder sogar als Open Source-Datei verwenden, da Sie viele TextInputs mit unterschiedlichen Wertefiltern / -prüfern erstellen können.

Der Nachteil einer sofortigen Korrektur besteht darin, sicherzustellen, dass dem Benutzer ein korrektes Feedback gegeben wird, um Verwirrung darüber zu vermeiden, was mit seinem Wert geschehen ist

Tjorriemorrie
quelle
Wie kann ich mit dem Ländercode einstellen
?
83

Die Verwendung eines RegExp zum Ersetzen von Nicht-Ziffern ist schneller als die Verwendung einer for-Schleife mit einer Whitelist, wie dies bei anderen Antworten der Fall ist.

Verwenden Sie dies für Ihren onTextChange-Handler:

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

Leistungstest hier: https://jsperf.com/removing-non-digit-characters-from-a-string

Jake Taylor
quelle
Wie kann ich mit dieser Methode nur Buchstaben im englischen Alphabet zulassen?
CraZyDroiD
2
@CraZyDroiD Passen Sie einfach den regulären Ausdruck an. Wenn Sie nur mit AZ übereinstimmen möchten, benötigen Sie so etwas wietext.replace(/[^A-Za-z]/g, '')
Jake Taylor
81

Sie können es so machen. Es werden nur numerische Werte akzeptiert und auf Wunsch auf 10 Zahlen begrenzt.

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

Sie können den eingegebenen Wert sehen, indem Sie den folgenden Code auf Ihre Seite schreiben:

{this.state.myNumber}

In der Funktion onChanged () sieht der Code folgendermaßen aus:

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

Ich hoffe das ist hilfreich für andere.

Venkatesh Somu
quelle
Kleine Korrektur: onChanged (Text) {var newText = ''; var numbers = '0123456789'; if (text.length <1) {this.setState ({myNumber: ''}); } für (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
Gute Antwort, aber warum hasst du die Nummer '9'
Stanley Luo
19
Weil 7 9 hassen?
Bootscodierer
4
Gibt es sowieso ein Flackern zu verhindern?
Waltari
1
Schauen wir uns
14

React Native TextInput bietet KeyboardType-Requisiten die folgenden möglichen Werte: Standard-Ziffernblock mit numerischer E-Mail-Adresse

In Ihrem Fall können Sie also keyboardType = 'Nummernblock' verwenden, um nur Zahlen zu akzeptieren. Dies beinhaltet nicht '.'

so,

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

ist das, was Sie in Ihrem Fall verwenden müssen.

Weitere Informationen finden Sie unter dem offiziellen Dokumentlink für TextInput: https://facebook.github.io/react-native/docs/textinput#keyboardtype

Ganesh Krishna
quelle
8

Erlaube Zahlen nur mit einem regulären Ausdruck

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

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

Möglicherweise möchten Sie mehr als eine Validierung haben


<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
quelle
Sie müssen diese ersten beiden Funktionen nicht erstellen, sondern können nur validations(value: string) { return /0/.test(value) && /^\d+$/.test(value) ? this.setState({ numColumns: value }) : false; }
Frederiko Cesar
1
@FrederikoCesar Werfen Sie einen Blick auf das Prinzip der
Einzelverantwortung
7

Funktion zur Validierung der Eingabe:

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

Ich hoffe das ist hilfreich.

Abdul Karim Khan
quelle
Das ist effizienter, es sollte anstelle der Schleifenmethode befolgt werden
Asif Ali
7

Eine freundliche Erinnerung an diejenigen, die auf das Problem gestoßen sind, dass "onChangeText" den TextInput-Wert unter iOS nicht wie erwartet ändern kann: Dies ist tatsächlich ein Fehler in ReactNative und wurde in Version 0.57.1 ​​behoben. Siehe: https://github.com/facebook/react-native/issues/18874

Flügel
quelle
Dies sollte ein Kommentar und keine Antwort sein
Haris Nadeem
1
Entschuldigen Sie, dass ich nicht genug Ruf habe, um die Frage zu kommentieren, und erhalte am Ende eine Antwort, um hoffentlich die Aufmerksamkeit auf Leute zu lenken, die nach praktikablen Lösungen suchen.
Flügel
Gutes Argument. Ich sehe, dass man 50 Ruf braucht, um zu kommentieren. Leider kann ich diese Einschränkung nicht aufheben, aber ich kann Ihnen 10 Ruf geben und hoffentlich einige der Einschränkungen aufheben.
Haris Nadeem
Nehmen Sie es 10 weitere, um Kommentar Bereitstellung zu erhalten ... Cheers @Wing
Venkatesh Somu
Danke :) @VenkateshSomu
Wing
6

Erste Lösung

Sie können verwenden keyboardType = 'numeric' für numerische Tastatur verwenden.

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

Im ersten Fall sind Satzzeichen enthalten, z. B.: - . und -

Zweite Lösung

Verwenden Sie reguläre Ausdrücke, um Satzzeichen zu entfernen.

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

Bitte überprüfen Sie den Snack-Link

https://snack.expo.io/@vishal7008/1e004c

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

und onChanged-Methode:

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
quelle
Ihre Lösung löst zwar mein Problem, warnt jedoch: "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."Ich weiß nicht, was ich damit anfangen soll. Kannst du helfen?
Mike
@Mike ein Ereignis könnte dies verursachen, können Sie Ihren Komponentencode über jsfiddle oder rnplay.org
Bheru Lal Lohar
Ich habe das kurz nach dem Kommentieren hier gelöst, kann aber leider herausfinden, was das Problem war.
Mike
Die Verwendung eines regulären Ausdrucks wäre eine klügere Wahl
Asif Ali
3

Ich hatte das gleiche Problem in iOS, als ich das Ereignis onChangeText verwendete, um den Wert des vom Benutzer eingegebenen Textes zu aktualisieren. Ich konnte den Wert des TextInput nicht aktualisieren, sodass der Benutzer weiterhin die nicht numerischen Zeichen sehen konnte, die er eingegeben hatte.

Dies lag daran, dass sich der Status beim Drücken eines nicht numerischen Zeichens nicht ändern würde, da this.setState dieselbe Nummer verwenden würde (die Nummer, die nach dem Entfernen der nicht numerischen Zeichen übrig blieb) und der TextInput dann nicht erneut gerendert würde.

Die einzige Möglichkeit, dies zu lösen, bestand darin, das keyPress-Ereignis zu verwenden, das vor dem onChangeText-Ereignis auftritt, und darin setState zu verwenden, um den Wert des Status in einen anderen, völlig anderen Wert zu ändern und das erneute Rendern zu erzwingen, wenn das onChangeText-Ereignis aufgerufen wird . Nicht sehr zufrieden damit, aber es hat funktioniert.

Gustavo Franco
quelle
3
if (!/^[0-9]+$/.test('123456askm')) {
  consol.log('Enter Only Number');
} else {
    consol.log('Sucess');
}
ANKIT-DETROJA
quelle
! / ^ [0-9] + $ /. Test ('123456askm') prüft, ob die Eingabezeichenfolge numerisch ist oder nicht. Test (Ihr Wert)
ANKIT-DETROJA
1
Hallo, bitte erweitern Sie Ihre Antwort, warum dies eine Lösung für das Problem von OP wäre. Dies wird OP und zukünftigen Besuchern der Website helfen. Vielen Dank!
d_kennetz
2

Ich habe diese Funktion geschrieben, die ich als hilfreich empfand, um zu verhindern, dass der Benutzer etwas anderes eingeben kann, als ich zu akzeptieren bereit war. Ich habe auch benutzt keyboardType="decimal-pad"und meineonChangeText={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 })
    }
}

Der erste ifBlock ist die Fehlerbehandlung für den Fall, dass der Benutzer den gesamten Text löscht oder einen Dezimalpunkt als erstes Zeichen verwendet. Wenn er versucht, mehr als eine Dezimalstelle einzugeben, stellt der zweite ifBlock sicher, dass er als eingeben kann viele Zahlen, wie sie wollen, vor der Dezimalstelle, aber nur bis zu zwei Dezimalstellen nach dem Punkt.

Andrew M Yasso
quelle
1

Verwenden eines RegExp zum Ersetzen von Nicht-Ziffern. Achten Sie darauf, dass der nächste Code Ihnen die erste Ziffer gibt, die er gefunden hat. Wenn der Benutzer einen Absatz mit mehr als einer Nummer (xx.xx) einfügt, gibt Ihnen der Code die erste Nummer. Dies hilft, wenn Sie etwas wie Preis wollen, nicht ein Handy.

Verwenden Sie dies für Ihren onTextChange-Handler:

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

Dies funktioniert nicht unter IOS, setState -> Rendern -> ändert den Text nicht, kann aber andere ändern. Die Texteingabe kann ihren Wert bei textOnChange nicht selbst ändern.

Übrigens, das funktioniert gut auf Android.

wv1124
quelle
Bitte erklären Sie mit Beispielcode, damit andere verstehen können.
Bheru Lal Lohar
0

Sie können nicht numerische Zeichen mit Regex entfernen

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

Hier ist meine andere einfache Antwort, um nur Zahlen im Textfeld mit regulären Ausdrücken zu akzeptieren.

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

Versuchen Sie dies nur für die Dezimal- / Gleitkommazahl

    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
quelle