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

ดูเหมือนจะใช้งานได้ แต่ดูเหมือนว่าเป็นการแฮ็ก มีวิธีอื่นในการทำเช่นนี้หรือไม่?


ไม่เคยมีตัวอย่างนี้ในการทำงาน คุณจัดการเพื่อแก้ปัญหาด้วยวิธีอื่นหรือไม่?
ซุ่ม

ดูเพิ่มเติม: stackoverflow.com/questions/40630918/…
hippietrail

โปรดทราบว่าสำหรับ React Native 0.54 คำตอบส่วนใหญ่ที่แนะนำที่นี่จะใช้งานไม่ได้: github.com/facebook/react-native/issues/18874 (มากถึงอย่างน้อย 0.56 ซึ่งเป็นเวอร์ชันใหม่ล่าสุดในขณะที่เขียน)
Tomty

1
@sumitkumarpradhan บล็อกโพสต์นั้นแนะนำให้ตั้งค่าประเภทแป้นพิมพ์เป็น "ตัวเลข" ซึ่งไม่ได้ป้องกันการป้อนข้อความ คุณสามารถคัดลอกวางสิ่งที่ต้องการลงในนั้นได้
jmathew

ฉันใช้keyboardType='numeric'prop ใน TextInput เพื่อแสดงเฉพาะแป้นพิมพ์ตัวเลข (duh) และยังแทนที่ข้อความด้วย regex text.replace(/[^0-9]/g, '')ตามที่แนะนำด้านล่างเพื่อป้องกันไม่ให้ใครก็ตามวางสตริงใน TextInput ทำงานได้ดีใน React Native v0.62
keshavDulal

คำตอบ:


28

นั่นเป็นวิธีที่ถูกต้องในการทำเช่นนั้นจนกว่าส่วนประกอบดังกล่าว (หรือแอตทริบิวต์บน TextInput) จะได้รับการพัฒนาโดยเฉพาะ

เว็บมีประเภท "หมายเลข" สำหรับองค์ประกอบอินพุต แต่เป็นแบบเว็บและตอบสนองเนทีฟไม่ได้ใช้มุมมองเว็บ

คุณสามารถพิจารณาสร้างอินพุตนั้นเป็นส่วนประกอบการตอบสนองด้วยตัวมันเอง (อาจเรียกว่า NumberInput): ซึ่งจะช่วยให้คุณสามารถใช้ซ้ำหรืออาจเป็นโอเพ่นซอร์สได้เนื่องจากคุณสามารถสร้าง TextInputs จำนวนมากที่มีตัวกรอง / ตัวตรวจสอบค่าที่แตกต่างกัน

ข้อเสียของการแก้ไขในทันทีคือเพื่อให้แน่ใจว่าได้ให้คำติชมที่ถูกต้องแก่ผู้ใช้เพื่อป้องกันความสับสนว่าเกิดอะไรขึ้นกับคุณค่าของเขา


ฉันจะตั้งรหัสประเทศได้อย่างไร (เช่น) ฉันจะตั้งรหัสประเทศด้วยอุปกรณ์ประกอบฉากในองค์ประกอบการป้อนข้อความได้อย่างไร
sejn

101

การใช้ RegExp เพื่อแทนที่ตัวเลขที่ไม่ใช่ตัวเลขนั้นเร็วกว่าการใช้ for loop ที่มีรายการที่อนุญาตเหมือนคำตอบอื่น ๆ

ใช้สิ่งนี้สำหรับตัวจัดการ onTextChange ของคุณ:

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

ทดสอบประสิทธิภาพที่นี่: https://jsperf.com/removing-non-digit-characters-from-a-string


ฉันจะอนุญาตเฉพาะตัวอักษรภาษาอังกฤษโดยใช้วิธีนี้ได้อย่างไร?
CraZyDroiD

2
@CraZyDroiD แค่ปรับ regex หากคุณต้องการจับคู่ AZ เท่านั้นคุณจะต้องมีบางอย่างเช่นtext.replace(/[^A-Za-z]/g, '')
Jake Taylor

1
ส่งkeyboardType='numeric'prop ไปยังช่อง 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: ''}); } สำหรับ (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'
Stanley Luo

19
เพราะ 7 เกลียด 9?
boatcoder

4
มีไว้เพื่อป้องกันการริบหรี่หรือไม่?
Waltari

คุณเป็นเพื่อนที่ดีที่สุด
Khadam Ikhwanus

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

ฉันหวังว่านี้จะเป็นประโยชน์.


นั่นเป็นวิธีที่มีประสิทธิภาพมากกว่าควรปฏิบัติตามแทนที่จะใช้วิธีการวนซ้ำ
Asif Ali

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


นี่ควรเป็นความคิดเห็นไม่ใช่คำตอบ
Haris Nadeem

1
ขออภัยที่ฉันไม่มีชื่อเสียงเพียงพอที่จะแสดงความคิดเห็นในคำถามดังนั้นฉันจึงได้รับคำตอบหวังว่าจะดึงดูดความสนใจให้กับผู้ที่กำลังมองหาวิธีแก้ปัญหาที่ใช้งานได้
กองบิน

จุดยุติธรรม ฉันเห็นว่าต้องมีชื่อเสียง 50 คนเพื่อแสดงความคิดเห็น น่าเศร้าที่ฉันไม่สามารถลบข้อ จำกัด นั้นได้ แต่ฉันสามารถมอบชื่อเสียงให้คุณได้ 10 อย่างและหวังว่าจะลบข้อ จำกัด บางอย่างออกไป
Haris Nadeem

รับอีก 10 ข้อเพื่อแสดงความคิดเห็น ... ไชโย @Wing
Venkatesh Somu

ขอบคุณ :) @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

@Mike มีเหตุการณ์บางอย่างที่อาจทำให้เกิดสิ่งนี้คุณสามารถแบ่งปันรหัสส่วนประกอบของคุณผ่าน jsfiddle หรือ rnplay.org
Bheru Lal Lohar

ฉันแก้ไขได้ไม่นานหลังจากแสดงความคิดเห็นที่นี่ แต่น่าเสียดายที่สามารถเข้าใจได้ว่าอะไรคือปัญหา
Mike

การใช้ regex จะเป็นทางเลือกที่ชาญฉลาดกว่า
Asif Ali

4

ฉันมีปัญหาเดียวกันใน iOS โดยใช้เหตุการณ์ onChangeText เพื่ออัปเดตค่าของข้อความที่ผู้ใช้พิมพ์ฉันไม่สามารถอัปเดตค่าของ TextInput ได้ดังนั้นผู้ใช้จะยังคงเห็นอักขระที่ไม่ใช่ตัวเลขที่เขาพิมพ์

เนื่องจากเมื่อกดอักขระที่ไม่ใช่ตัวเลขสถานะจะไม่เปลี่ยนเนื่องจากสิ่งนี้ setState จะใช้ตัวเลขเดิม (ตัวเลขที่ยังคงอยู่หลังจากลบอักขระที่ไม่ใช่ตัวเลขออกแล้ว) จากนั้น TextInput จะไม่แสดงผล

วิธีเดียวที่ฉันพบในการแก้ปัญหานี้คือการใช้เหตุการณ์ keyPress ซึ่งเกิดขึ้นก่อนเหตุการณ์ onChangeText และในนั้นใช้ setState เพื่อเปลี่ยนค่าของสถานะเป็นอื่นที่แตกต่างกันโดยสิ้นเชิงบังคับให้ render เมื่อเหตุการณ์ onChangeText ถูกเรียก . ไม่ค่อยมีความสุขกับสิ่งนี้ แต่ได้ผล


4
if (!/^[0-9]+$/.test('123456askm')) {
  consol.log('Enter Only Number');
} else {
    consol.log('Sucess');
}

! / ^ [0-9] + $ /. test ('123456askm') จะตรวจสอบว่าสตริงอินพุตเป็นตัวเลขหรือไม่ทดสอบ (ค่าของคุณ)
ANKIT-DETROJA

1
สวัสดีโปรดขยายคำตอบของคุณว่าเหตุใดจึงเป็นวิธีแก้ปัญหาของ OP สิ่งนี้จะช่วย 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

คุณสามารถลบอักขระที่ไม่ใช่ตัวเลขโดยใช้ regex

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

1

สิ่งนี้ใช้ไม่ได้กับ IOS, setState -> render -> ไม่เปลี่ยนข้อความ แต่สามารถเปลี่ยนอื่น ๆ ได้ textinput ไม่สามารถเปลี่ยนค่าตัวเองเมื่อ 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 ไม่ใช่ตัวเลขหรือเป็นเท็จถ้าเป็น 0

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.