DEV Community

HarmonyOS
HarmonyOS

Posted on

How to Solve TextInput Input Restriction Abnormality Issues

Read the original article:How to Solve TextInput Input Restriction Abnormality Issues

Context

In HarmonyOS, the $$ two-way binding symbol can synchronize state variables with the internal state of system components. When using the TextInput component for text input, you can perform operations such as limiting input content in the onChange event.

Description

Adding restriction conditions to TextInput component to only allow input of numbers within a certain range. Implementing specific logic in onChange callback, but it doesn't take effect after running. Two issues occur:

  1. Set input range in callback, but can still input numbers beyond the range
  2. After adding $$ two-way binding to text, range restriction works but cannot input decimal points, resulting in only integer input

Problem code:

@Entry
@Component
struct TextInputPage {
  @State inputValue: string = '';

  build() {
    Column() {
      TextInput({
        text: this.inputValue, // Cannot input decimal points after adding two-way binding symbol $$
        placeholder: 'Please enter a number between -50 and 150.'
      })
        .type(InputType.NUMBER_DECIMAL)
        .onChange((value: string) => {
          // Convert to number for range judgment
          let numValue = parseFloat(value) ;
          if (numValue <= -50) { 
            this.inputValue = '-50';
          }else if (numValue >= 150) {
            this.inputValue = '150';
          }else {
            this.inputValue = numValue.toString()
          }
        })
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Problem analysis:

  1. Check whether $$ two-way binding symbol is used when passing values to TextInput component's text parameter
  2. Trace the source of final displayed numeric values, check if there are operations limiting decimal point input or if decimal points are lost during data conversion

Root cause:

  1. Not using $$ two-way binding symbol when passing values to TextInput text parameter, causing state variable changes unable to synchronize with TextInput component
  2. Decimal points lost after conversion through parseFloat() and toString() methods, causing input failure

Solution

Fix Recommendations:

  1. Add $$ two-way binding symbol to TextInput component's text parameter
  2. Use original string value - onChange event's value is already string type, use value directly for text display instead of converting parseFloat() result back to string
  3. Use inputFilter for negative decimals - When type is set to InputType.NUMBER_DECIMAL, negative decimals are not supported. Use inputFilter to implement negative decimal input

Corrected code:

@Entry
@Component
struct TextInputPage {
  @State inputValue: string = '';

  build() {
    Column() {
      TextInput({
        text: $$this.inputValue,
        placeholder: 'Please enter a number between -50 and 150.'
      })
        .onChange((value: string) => {
          // Convert to number for range judgment
          let numValue = parseFloat(value) ;
          if (numValue <= -50) {
            this.inputValue = '-50';
          }else if (numValue >= 150) {
            this.inputValue = '150';
          }else {
            this.inputValue = value
          }
        })
        .inputFilter('^-?\\d*\\.?\\d{0,2}$', (val) => { // Use regex to limit input content
          return 0
        })
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Key Takeaways

  • Two-way Binding: Use $$ symbol for TextInput text parameter to synchronize state changes
  • Data Type Handling: Avoid unnecessary type conversions that cause decimal point loss
  • Input Validation: Use inputFilter with regex for complex input restrictions like negative decimals
  • Range Limitations: InputType.NUMBER_DECIMAL doesn't support negative numbers; use inputFilter as alternative
  • Performance: Direct string usage is more efficient than parseFloat() + toString() conversion chain

Written by Emincan Ozcan

Top comments (0)