bhrott / react-native-masked-text

A pure javascript masked text and input text component for React-Native.
MIT License
1.61k stars 249 forks source link

Error while trying to focus TextInputMask #157

Open Luckygirlllll opened 5 years ago

Luckygirlllll commented 5 years ago

I want to focus onTextInputMask, while user is clicking next button in the previousTextInput, 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 commented 5 years ago

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 commented 5 years ago

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

bhrott commented 5 years ago

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>
Luckygirlllll commented 5 years ago

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

bhrott commented 5 years ago

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/

Luckygirlllll commented 5 years ago

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 commented 5 years ago

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

bhrott commented 5 years ago

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 =/.

ammichael commented 5 years ago

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;

RageOfJustice commented 5 years ago

Use refInput instead of ref

remmcal commented 5 years ago

thanks @ammichael it works

ArthurEgide commented 5 years ago

thanks @RageOfJustice it works!!!!

petreg commented 5 years ago

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

doponalopes commented 5 years ago

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?

petreg commented 5 years ago

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

louzada01 commented 4 years ago

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});
            }}
          />
willnrf commented 4 years ago

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

deserthurricane commented 4 years ago

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

ganholete commented 4 years ago

Use refInput instead of ref

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

lukemorales commented 4 years ago

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.

marceloambarc commented 3 years ago

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} /> `

itzfeltrin commented 3 years ago

valeu, @marceloambarc, tava quase desistindo já

syedamirali14 commented 2 years ago

nothing is working on functional component neither getElement() nor_inputElement

mbrandaocaio commented 1 year ago

Use refInput instead of ref @RageOfJustice thanks man