React Native TextInput yang hanya menerima karakter numerik

106

Saya perlu memiliki TextInputkomponen React Native yang hanya memungkinkan karakter numerik (0 - 9) untuk dimasukkan. Saya bisa mengatur keyboardTypeuntuk numericyang hampir membuat saya ada untuk input kecuali untuk periode (.). Namun ini tidak berhenti menempelkan karakter non-numerik ke dalam bidang.

Apa yang saya dapatkan sejauh ini adalah menggunakan OnChangeTextacara tersebut untuk melihat teks yang dimasukkan. Saya menghapus karakter non-numerik dari teks. Kemudian letakkan teks di bidang negara bagian. Kemudian perbarui TextInputmelalui Valueproperti itu. Cuplikan kode di bawah ini.

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

Ini sepertinya berhasil tetapi sepertinya hack. Apakah ada cara lain untuk melakukan ini?

Terry
sumber
Jangan pernah membuat contoh ini berhasil. Apakah Anda berhasil menyelesaikannya dengan cara lain?
amb
Perhatikan bahwa pada React Native 0,54, sebagian besar jawaban yang disarankan di sini rusak: github.com/facebook/react-native/issues/18874 (hingga setidaknya 0,56, yang merupakan versi terbaru pada saat penulisan).
Tomty
1
@sumitkumarpradhan Posting blog itu menyarankan pengaturan jenis keyboard ke 'numerik' yang sebenarnya tidak mencegah input teks. Anda dapat menyalin dan menempelkan apa pun yang Anda inginkan ke sana.
jmathew
Saya menggunakan keyboardType='numeric'prop di TextInput untuk hanya menampilkan Numeric Keyboard (duh) dan juga mengganti teks dengan regex text.replace(/[^0-9]/g, '')seperti yang disarankan di bawah ini untuk mencegah siapa pun menempelkan string di dalam TextInput. Sejauh ini berfungsi dengan baik di React Native v0.62
keshavDulal

Jawaban:

30

Itu adalah cara yang benar untuk melakukannya hingga komponen seperti itu (atau atribut pada TextInput) dikembangkan secara khusus.

Web memiliki tipe 'angka' untuk elemen masukan, tetapi yang berbasis web dan react-native tidak menggunakan tampilan web.

Anda dapat mempertimbangkan untuk membuat input itu sebagai komponen react sendiri (mungkin memanggil NumberInput): yang akan memungkinkan Anda untuk menggunakannya kembali atau bahkan mungkin open source karena Anda dapat membuat banyak TextInputs yang memiliki filter / pemeriksa nilai yang berbeda.

Kelemahan dari koreksi langsung adalah memastikan umpan balik yang benar diberikan kepada pengguna untuk mencegah kebingungan tentang apa yang terjadi pada nilainya

Tjorriemorrie
sumber
Bagaimana saya dapat mengatur dengan kode negara. (Yaitu) dapatkah saya mengatur kode negara dengan alat peraga apa pun dalam komponen input teks
sejn
106

Menggunakan RegExp untuk mengganti bukan digit lebih cepat daripada menggunakan perulangan for dengan daftar putih, seperti yang dilakukan jawaban lain.

Gunakan ini untuk penangan onTextChange Anda:

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

Uji kinerja di sini: https://jsperf.com/removing-non-digit-characters-from-a-string

Jake Taylor
sumber
Bagaimana saya hanya mengizinkan huruf dalam alfabet bahasa Inggris menggunakan metode ini?
CraZyDroiD
2
@CraZyDiD cukup sesuaikan regex. Jika Anda hanya ingin mencocokkan AZ, Anda memerlukan sesuatu sepertitext.replace(/[^A-Za-z]/g, '')
Jake Taylor
1
Juga berikan keyboardType='numeric'prop ke bidang TextInput.
keshavDulal
94

Anda bisa melakukannya seperti ini. Ini hanya akan menerima nilai numerik, dan membatasi hingga 10 angka sesuai keinginan Anda.

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

Anda dapat melihat nilai yang dimasukkan dengan menulis kode berikut di halaman Anda:

{this.state.myNumber}

Dalam fungsi onChanged (), kodenya terlihat seperti ini:

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

Saya harap ini bermanfaat bagi orang lain.

Venkatesh Somu
sumber
Koreksi kecil: onChanged (text) {var newText = ''; nomor var = '0123456789'; if (text.length <1) {this.setState ({myNumber: ''}); } untuk (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
Jawaban yang bagus, tapi mengapa Anda membenci angka '9'
Stanley Luo
20
Karena 7 benci 9?
boatcoder
4
Apakah ada cara untuk mencegah kedipan?
Waltari
Anda adalah teman terbaik
Khadam Ikhwanus
18

React Native TextInput menyediakan alat peraga keyboardType dengan kemungkinan nilai berikut: default nomor-pad desimal-pad numerik alamat email-pad telepon

jadi untuk kasus Anda, Anda dapat menggunakan keyboardType = 'number-pad' untuk hanya menerima angka. Ini tidak termasuk '.'

begitu,

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

adalah apa yang harus Anda gunakan dalam kasus Anda.

untuk lebih jelasnya silakan lihat tautan dokumen resmi untuk TextInput: https://facebook.github.io/react-native/docs/textinput#keyboardtype

Ganesh Krishna
sumber
10

Fungsi untuk memvalidasi masukan:

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

Semoga bermanfaat.

Abdul Karim Khan
sumber
Itu cara yang lebih efisien, itu harus diikuti daripada metode perulangan
Asif Ali
10

Hanya izinkan angka menggunakan ekspresi reguler

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

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

Anda mungkin ingin memiliki lebih dari satu validasi


<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
sumber
Tidak perlu membuat dua fungsi pertama ini, Anda cukup menggunakan:validations(value: string) { return /0/.test(value) && /^\d+$/.test(value) ? this.setState({ numColumns: value }) : false; }
Frederiko Cesar
2
@FrederikoCesar Mengintip prinsip tanggung jawab tunggal
jasonleonhard
10

Solusi Pertama

Anda dapat menggunakan keyboardType = 'numeric'untuk keyboard numerik.

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

Dalam kasus pertama, tanda baca disertakan, misalnya: - . dan -

Solusi Kedua

Gunakan ekspresi reguler untuk menghapus tanda baca.

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

Silakan periksa tautan makanan ringan

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

Vishal Dhanotiya
sumber
8

Pengingat bagi mereka yang mengalami masalah bahwa "onChangeText" tidak dapat mengubah nilai TextInput seperti yang diharapkan di iOS: itu sebenarnya adalah bug di ReactNative dan telah diperbaiki di versi 0.57.1. Lihat: https://github.com/facebook/react-native/issues/18874

Sayap
sumber
Ini harus menjadi komentar dan bukan jawaban
Haris Nadeem
1
Mohon maaf karena saya tidak memiliki reputasi yang cukup untuk mengomentari pertanyaan jadi saya berakhir dengan sebuah jawaban, semoga dapat menarik perhatian orang-orang yang mencari solusi yang bisa diterapkan.
Sayap
Poin yang adil. Saya melihat bahwa seseorang membutuhkan 50 reputasi untuk berkomentar. Sayangnya, saya tidak dapat menghapus batasan itu, tetapi saya dapat memberi Anda 10 reputasi dan mudah-mudahan menghapus beberapa batasan.
Haris Nadeem
ambillah 10 lagi untuk mendapatkan ketentuan komentar ... Cheers @Wing
Venkatesh Somu
Terima kasih :) @VenkateshSomu
Wing
4
<TextInput autoCapitalize={'none'} maxLength={10} placeholder='Mobile Number'  value={this.state.mobile} onChangeText={(mobile) => this.onChanged(mobile)}/>

dan metode 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 });
    }
}
Bheru Lal Lohar
sumber
Solusi Anda, meskipun memecahkan masalah saya, menghasilkan peringatan: "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."Saya tidak tahu harus berbuat apa dengan ini. Bisakah kamu menolong?
Mike
@Mike beberapa peristiwa mungkin menyebabkan ini, dapatkah Anda membagikan kode komponen Anda melalui jsfiddle atau rnplay.org
Bheru Lal Lohar
Saya menyelesaikannya tak lama setelah berkomentar di sini, tetapi sayangnya dapat mengetahui apa masalahnya.
Mike
menggunakan regex akan menjadi pilihan yang lebih cerdas
Asif Ali
4

Saya memiliki masalah yang sama di iOS, menggunakan acara onChangeText untuk memperbarui nilai teks yang diketik oleh pengguna. Saya tidak dapat memperbarui nilai TextInput, jadi pengguna masih akan melihat karakter non numerik yang diketiknya.

Ini karena, ketika karakter non numerik ditekan, status tidak akan berubah karena this.setState akan menggunakan angka yang sama (angka yang tersisa setelah menghapus karakter non numerik) dan kemudian TextInput tidak akan dirender ulang.

Satu-satunya cara yang saya temukan untuk menyelesaikan ini adalah dengan menggunakan acara keyPress yang terjadi sebelum acara onChangeText, dan di dalamnya, gunakan setState untuk mengubah nilai status ke yang lain, sama sekali berbeda, memaksa render ulang saat acara onChangeText dipanggil . Tidak terlalu senang dengan ini tetapi berhasil.

Gustavo Franco
sumber
4
if (!/^[0-9]+$/.test('123456askm')) {
  consol.log('Enter Only Number');
} else {
    consol.log('Sucess');
}
ANKIT DETROJA
sumber
! / ^ [0-9] + $ /. Test ('123456askm') itu akan memeriksa string input numerik atau tidak .test (Nilai Anda)
ANKIT DETROJA
1
Hai, mohon kembangkan jawaban Anda tentang mengapa ini akan menjadi solusi untuk masalah OP. Ini akan membantu OP dan pengunjung situs di masa mendatang. Terima kasih!
d_kennetz
3

Saya menulis fungsi ini yang menurut saya berguna untuk mencegah pengguna memasukkan apa pun selain yang ingin saya terima. Saya juga menggunakan keyboardType="decimal-pad"dan milik sayaonChangeText={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 })
    }
}

ifBlok pertama adalah penanganan error jika pengguna menghapus semua teks, atau menggunakan titik desimal sebagai karakter pertama, atau jika mereka mencoba memasukkan lebih dari satu tempat desimal, ifblok kedua memastikan mereka dapat mengetik sebagai banyak angka yang mereka inginkan sebelum tempat desimal, tetapi hanya maksimal dua tempat desimal setelah titik.

Andrew M Yasso
sumber
2

Menggunakan RegExp untuk mengganti non digit. Berhati-hatilah kode berikutnya akan memberi Anda digit pertama yang dia temukan, jadi jika pengguna menempelkan paragraf dengan lebih dari satu angka (xx.xx) kode akan memberi Anda angka pertama. Ini akan membantu jika Anda menginginkan sesuatu seperti harga, bukan ponsel.

Gunakan ini untuk penangan onTextChange Anda:

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

Anda dapat menghapus karakter non numerik menggunakan regex

onTextChanged (text) {
    this.setState({
        myNumber: text.replace(/\D/g, ''),
    });
}
Anoop
sumber
2
const [text, setText] = useState('');

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

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

Ini harus menghemat dari keyboard fisik

Zyfar Bektashov
sumber
1

Ini tidak berfungsi di IOS, setState -> render -> tidak mengubah teks, tetapi dapat mengubah lainnya. Textinput tidak dapat mengubah nilainya sendiri saat textOnChange.

Omong-omong, ini berfungsi dengan baik di Android.

wv1124
sumber
Tolong jelaskan dengan kode contoh agar orang lain bisa mengerti.
Bheru Lal Lohar
1

Berikut adalah jawaban sederhana saya yang lain untuk hanya menerima angka di kotak teks menggunakan Regular Expressions.

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

Untuk angka Desimal / Floating point hanya coba ini

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

Nah, ini adalah cara yang sangat sederhana untuk memvalidasi angka yang berbeda dengan 0.

if (+inputNum)

Ini akan menjadi NaN jika inputNum bukan angka atau salah jika 0

Félix Andersson
sumber