react-native-masked-text icon indicating copy to clipboard operation
react-native-masked-text copied to clipboard

Error while trying to focus TextInputMask

Open Luckygirlllll opened this issue 5 years ago • 24 comments

I want to focus on TextInputMask, while user is clicking next button in the previous TextInput, when I'm trying to do it, I'm getting an error, how is possible to focus TextInputMask programmatically?

Here is my code:

 <TextInput
                        style={styles.input}
                        placeholder='Last Name*'
                        ref={lastNameRef => this.lastNameRef = lastNameRef}
                        returnKeyType='next'
                        onSubmitEditing={() => this.phoneRef.focus()}
                        placeholderTextColor='#B1B1B1'
                        onChangeText={ text => this.onChangeLastName('lastName', text) }
                    /> 
 <TextInputMask
                        style={styles.input}
                        placeholder='Phone*'
                        ref={phoneRef => this.phoneRef = phoneRef}
                        returnKeyType='next'
                        type={'custom'}
                        value={this.state.phoneNumber}
                        options={{
                            mask: '(999) 999-9999'
                          }}
                          onChangeText={
                            text => this.onChangePhone('phoneNumber', text)
                        }
                    ></TextInputMask>

Luckygirlllll avatar May 10 '19 07:05 Luckygirlllll

I have also tried this code as well, and I also got an error "undefined is not an object evaluating u.refs.dateOfBirthInput.getElement()._root.focus ":

_onLastNameSubmitted() {
        const el = this.refs.dateOfBirthInput.getElement()
        el._root.focus()
      }

 <TextInput
                        style={styles.input}
                        placeholder='Last Name*'
                        ref={lastNameRef => this.lastNameRef = lastNameRef}
                        returnKeyType='next'
                        onSubmitEditing={() => { this._onLastNameSubmitted() }}
                        placeholderTextColor='#B1B1B1'
                        onChangeText={ text => this.onChangeLastName('lastName', text) }
                    /> 
 <TextInputMask
                        style={styles.input}
                        placeholder='Phone*'
                        ref='dateOfBirthInput'
                        returnKeyType='next'
                        type={'custom'}
                        value={this.state.phoneNumber}
                        options={{
                            mask: '(999) 999-9999'
                          }}
                          onChangeText={
                            text => this.onChangePhone('phoneNumber', text)
                        }
                    ></TextInputMask>

Luckygirlllll avatar May 10 '19 07:05 Luckygirlllll

I have also tried this solution:

  onBirthdaySubmitted = () => {
        this.refs['phoneInput'].getElement().focus();
      }

 <ScrollView 
            contentContainerStyle={{flexGrow: 1}} style={{zIndex: 101}}
            keyboardShouldPersistTaps='handled'
            >
  <KeyboardAvoidingView style={{zIndex: 100}} behavior="position">
 <TextInput
                        style={styles.input}
                        placeholder='Last Name*'
                        ref={lastNameRef => this.lastNameRef = lastNameRef}
                        returnKeyType='next'
                        onSubmitEditing={this.onBirthdaySubmitted}
                        placeholderTextColor='#B1B1B1'
                        onChangeText={ text => this.onChangeLastName('lastName', text) }
                    /> 
 <TextInputMask
                        style={styles.input}
                        placeholder='Phone*'
                        ref='phoneInput'
                        returnKeyType='next'
                        type={'custom'}
                        value={this.state.phoneNumber}
                        options={{
                            mask: '(999) 999-9999'
                          }}
                          onChangeText={
                            text => this.onChangePhone('phoneNumber', text)
                        }
                    ></TextInputMask>

 </KeyboardAvoidingView>
</ScrollView >

This code focusTextInputMaskfor 1 second and then unfocus it 1 second later automatically

Luckygirlllll avatar May 10 '19 08:05 Luckygirlllll

Hi @Luckygirlllll could you check this sample?

<View style={container}>
  <Text>Focusing next input</Text>
  <TextInput
    value={this.state.name}
    onChangeText={name => {
      this.setState({
        name
      })
    }}
    onSubmitEditing={() => {
      this._cpfRef.getElement().focus()
    }}
    placeholder='Name'
  />
  <TextInputMask
    ref={ref => this._cpfRef = ref}
    type={'cpf'}
    value={this.state.cpf}
    onChangeText={text => {
      this.setState({
        cpf: text
      })
    }}
    placeholder='Cpf'
  />
</View>

bhrott avatar May 10 '19 13:05 bhrott

@benhurott It's the same behavior field is focused for 1 second and then it becomes unfocused

Luckygirlllll avatar May 10 '19 14:05 Luckygirlllll

Ok, could you provide more info about the environment? Because it seems another component is requesting the focus. If you can, provide the current source code of the component, the device model and OS model and the ReactNative version to let me check.

Thanks o/

bhrott avatar May 10 '19 22:05 bhrott

I'm currently testing in IOS simulator 12.2, iPhone XR. react-native version 0.57.1

Here is the code of the component:

import DatePicker from 'react-native-datepicker'
import { TextInputMask } from 'react-native-masked-text'

class ExtraSignUp extends React.Component {

   onBirthdaySubmitted = () => {
        this.refs['phoneInput'].getElement().focus();
      }

render() {
      return (

 <ScrollView 
            contentContainerStyle={{flexGrow: 1}} style={{zIndex: 101}}
            keyboardShouldPersistTaps='handled'
            >
            <ImageBackground
            source={require('../../images/background.png')}
            style={styles.container}
            > 
              <KeyboardAvoidingView style={{zIndex: 100}} behavior="position">
              <View style={styles.extraContainer}>
              <View style={styles.topRow}>
              <TouchableOpacity onPress={this.goBack}>
                    <MaterialIcons name="arrow-back" size={48} color="white" style={styles.arrowBack} />
                </TouchableOpacity>
                <View  style={styles.middleView2}/>
             <Image
                    style={styles.logoStyle}
                    source={require('../../images/logo.png')}
                />
                <View  style={styles.middleView}/>
                </View>
                <Text style={styles.titleText}>Your Profile</Text>
                <Text style={styles.explanation}>We need a few more things then 
                        you’re good to go. We know you 
                        have some important work ahead of you!</Text> 
                <View style={styles.row}>
                    <MaterialIcons name="person" size={40} color="#B1B1B1" style={styles.iconStyle} />
                    <View>
                    <TextInput
                        style={styles.input}
                        placeholder='First Name*'
                        placeholderTextColor='#B1B1B1'
                        returnKeyType='next'
                        onSubmitEditing={() => this.lastNameRef.focus()} 
                        onChangeText={ text => this.onChangeFirstName('firstName', text) }
                    />
                    {!!firstNameError && showError &&  (
                    <View style={styles.emailErrorRow}>  
                        <Text style={styles.error}>{firstNameError}</Text>
                     </View>
                    )}  
                    </View>
                </View>

                <View style={styles.row}>
                    <MaterialIcons name="person" size={40} color="#B1B1B1" style={styles.iconStyle} />
                    <View>
                    <TextInput
                        style={styles.input}
                        placeholder='Last Name*'
                        ref={lastNameRef => this.lastNameRef = lastNameRef}
                        returnKeyType='next'
                        onSubmitEditing={() => this.dateRef.onPressDate()}
                        placeholderTextColor='#B1B1B1'
                        onChangeText={ text => this.onChangeLastName('lastName', text) }
                    /> 
                    {!!lastNameError && showError &&  (
                    <View style={styles.emailErrorRow}>   
                        <Text style={styles.error}>{lastNameError}</Text> 
                    </View>
                    )}
                  </View>     
                 </View>

                 <View style={styles.row}>
                    <MaterialIcons name="cake" size={40} color="#B1B1B1" style={styles.iconStyle} />
                    <View>
                    <DatePicker
                        style={styles.birthdayInput}
                        date={this.state.birthday}
                        ref={dateRef => this.dateRef = dateRef}
                        mode="date"
                        placeholder="Birthday*"
                        format="MM-DD-YYYY"
                        onCloseModal={this.onBirthdaySubmitted} 
                        confirmBtnText="Next"
                        cancelBtnText="Cancel"
                        onDateChange={(date) => this.onChangeBirthday('birthday', date)}
                    />
                    {!!birthdayError && showError && (
                    <View style={styles.birthdayErrorRow}>   
                        <Text style={styles.error}>{this.state.birthdayError}</Text>
                    </View>
                    )} 
                    </View>
                  </View>

                  <View style={styles.row}>
                    <MaterialIcons name="phone" size={40} color="#B1B1B1" style={styles.iconStyle} /> 
                    <View>
                    <TextInputMask
                        style={styles.input}
                        placeholder='Phone*'
                        ref='phoneInput'
                        returnKeyType='next'
                        onSubmitEditing={() => this.teamRef.focus()} 
                        type={'custom'}
                        value={this.state.phoneNumber}
                        options={{
                            mask: '(999) 999-9999'
                          }}
                          onChangeText={
                            text => this.onChangePhone('phoneNumber', text)
                        }
                    ></TextInputMask>
                    {!!phoneError && showError &&  (
                    <View style={styles.emailErrorRow}>   
                        <Text style={styles.error}>{phoneError}</Text> 
                    </View>
                    )}
                    </View>
                 </View>  

                  <View style={styles.row}>
                    <MaterialIcons name="domain" size={40} color="#B1B1B1" style={styles.iconStyle} /> 
                    <TextInput
                    style={styles.inputTeam}
                    ref={teamRef => this.teamRef = teamRef}
                    returnKeyType='done'
                    placeholder='Team or Company'
                    placeholderTextColor='#B1B1B1'
                    onChangeText={ text => this.onChangeText('company', text) } 
                    />
                  </View> 
                  <TouchableHighlight
                    style={styles.button} 
                    onPress={this.goNext}
                  >
                    <Text style={styles.buttonText}>Save My Profile</Text>
                </TouchableHighlight>     
      </ImageBackground>
            </ScrollView>
   )
    }
}

Luckygirlllll avatar May 11 '19 18:05 Luckygirlllll

@benhurott Any updates regarding this issue? What do you think can be a problem?

Luckygirlllll avatar May 14 '19 11:05 Luckygirlllll

Hi @Luckygirlllll I'm still investigating, I can't reproduce. I'm thinking it could be an issue with the scrollview. Probably the scroll render is removing the focus, but I'm still checking =/.

bhrott avatar May 14 '19 14:05 bhrott

Hey there, I'm also having trouble with maked input and refs. In my case I'm attaching the ref like this:

 valueInputRef = React.createRef();
 <MaskedInput
   ref={valueInputRef}
   type="money"
   { ...otherProps }
  />

Logging the ref out I get this:

image

The same result happens if I just log the ref out like this:

 <MaskedInput
   ref={ref => { console.log(ref) }}
   type="money"
   { ...otherProps }
  />

No "focus" property is found in current, but it's found in _inputElement, so if I call it this.valueInputRef.current._inputElement.focus(); it does work.

I'm using RN 0.58.5, masked-text 1.12.3;

ammichael avatar May 18 '19 23:05 ammichael

Use refInput instead of ref

RageOfJustice avatar Jul 15 '19 13:07 RageOfJustice

thanks @ammichael it works

remmcal avatar Aug 08 '19 20:08 remmcal

thanks @RageOfJustice it works!!!!

ArthurEgide avatar Sep 13 '19 21:09 ArthurEgide

Hi @Luckygirlllll could you check this sample?

<View style={container}>
  <Text>Focusing next input</Text>
  <TextInput
    value={this.state.name}
    onChangeText={name => {
      this.setState({
        name
      })
    }}
    onSubmitEditing={() => {
      this._cpfRef.getElement().focus()
    }}
    placeholder='Name'
  />
  <TextInputMask
    ref={ref => this._cpfRef = ref}
    type={'cpf'}
    value={this.state.cpf}
    onChangeText={text => {
      this.setState({
        cpf: text
      })
    }}
    placeholder='Cpf'
  />
</View>

It solved for me...

petreg avatar Sep 20 '19 14:09 petreg

Hello, I did like this:

react: 16.9.0 react-native: 0.61.2

refTelehone = React.createRef()
refCellPhone = React.createRef()

cellPhoneFocus = () => {
    if(this.refCellPhone.current) {
          this.refCellPhone.current._inputElement.focus()
    }
}

<LabelInput
    returnKeyType='next'
    haveMask={true}
    typeMask='custom'
    maskCustom='(99) 9999-9999'
    value={this.state.telephoneValue}
    innerRef={this.refTelehone}
    onSubmitEditing={this.cellPhoneFocus}
/>

// component
<TextInputMask
    type={this.props.typeMask}
    options={{ mask: this.props.maskCustom }}
    onChangeText={this.props.onChangeText}
    ref={ref => this.props.innerRef = ref}
    onSubmitEditing={this.props.onSubmitEditing}
 />

The problem is that when I click Next, it does not focus on the next entry, could anyone help?

doponalopes avatar Oct 11 '19 12:10 doponalopes

Hello, I did like this:

react: 16.9.0 react-native: 0.61.2

refTelehone = React.createRef()
refCellPhone = React.createRef()

cellPhoneFocus = () => {
    if(this.refCellPhone.current) {
          this.refCellPhone.current._inputElement.focus()
    }
}

<LabelInput
    returnKeyType='next'
    haveMask={true}
    typeMask='custom'
    maskCustom='(99) 9999-9999'
    value={this.state.telephoneValue}
    innerRef={this.refTelehone}
    onSubmitEditing={this.cellPhoneFocus}
/>

// component
<TextInputMask
    type={this.props.typeMask}
    options={{ mask: this.props.maskCustom }}
    onChangeText={this.props.onChangeText}
    ref={ref => this.props.innerRef = ref}
    onSubmitEditing={this.props.onSubmitEditing}
 />

The problem is that when I click Next, it does not focus on the next entry, could anyone help?

Try to do as I have shown above. May help you ...

petreg avatar Oct 11 '19 13:10 petreg

I got a similar result using a functional component.

I had to declare two variables at the beginning of my scope and used them to reference at the end of the input.

Would you have any other way to do it using the react hooks?

  const emailRef = useRef();
  let phoneRef, documentRef;

          <InputText
            icon="mail-outline"
            autoCorrect={false}
            autoCapitalize="none"
            placeholder="Email"
            returnKeyType="next"
            onSubmitEditing={() => phoneRef.getElement().focus()}
            ref={emailRef}
            value={user.email}
            onChangeText={text => setUser({...user, email: text})}
          />
          <InputTextMask
            type={'cel-phone'}
            options={{
              maskType: 'BRL',
              withDDD: true,
              dddMask: '(99) ',
            }}
            icon="call"
            autoCorrect={false}
            autoCapitalize="none"
            placeholder="Telefone para contato"
            returnKeyType="next"
            ref={ref => phoneRef = ref}
            onSubmitEditing={() => documentRef.getElement().focus()}
            value={user.telefone}
            onChangeText={text => {
              setUser({...user, telefone: text});
            }}
          />
          <InputTextMask
            type={'cpf'}
            icon="payment"
            autoCorrect={false}
            autoCapitalize="none"
            placeholder="CPF"
            returnKeyType="send"
            onSubmitEditing={handleAlterProfile}
            ref={ref => documentRef = ref}
            value={user.documento}
            onChangeText={text => {
              setUser({...user, documento: text});
            }}
          />

louzada01 avatar Dec 20 '19 19:12 louzada01

Ref InputTextMask better way onSubmitEditing={() => phoneField.current.getElement().focus()}

willnrf avatar Mar 12 '20 20:03 willnrf

Is it gonna be any update on this issue? current.getElement() worked for me, but it's not a good and safe solution...

deserthurricane avatar Apr 29 '20 10:04 deserthurricane

Use refInput instead of ref

This works for focus, but I lose the IsValid() method in a date field for example

ganholete avatar May 15 '20 14:05 ganholete

Use refInput instead of ref

This works for focus, but I lose the IsValid() method in a date field for example

Use both refs, refInput to get the focus working, and ref to get the isValid() and other methods provided by the lib.

lukemorales avatar May 19 '20 14:05 lukemorales

For Typescript users:

let ref_name = useRef<TextInput>(null); let ref_cnpj = createRef<any>();

<TextInput style={styles.input} placeholder="placeholder" autoCorrect={false} value={name} onChangeText={setName} ref={ref_name} returnKeyType='next' onSubmitEditing={() => ref_cnpj.current?._inputElement.focus()} />

<TextInputMask type={'cnpj'} style={styles.input} placeholder="CNPJ" autoCorrect={false} value={cnpj} onChangeText={setCnpj} ref={ref_cnpj} /> `

marceloambarc avatar Apr 06 '21 12:04 marceloambarc

valeu, @marceloambarc, tava quase desistindo já

itzfeltrin avatar May 18 '21 20:05 itzfeltrin

nothing is working on functional component neither getElement() nor _inputElement

syedamirali14 avatar Feb 18 '22 12:02 syedamirali14

Use refInput instead of ref @RageOfJustice thanks man

mbrandaocaio avatar Nov 25 '22 17:11 mbrandaocaio