microsoft / reactxp

Library for cross-platform app development.
https://microsoft.github.io/reactxp/
Other
8.29k stars 491 forks source link

how to Handling Multiple Inputs with a Single onChange Handler? #1205

Open GolfredoPerezFernandez opened 4 years ago

GolfredoPerezFernandez commented 4 years ago

Im creating a form with multiple TextInputs how i can handle with a single onChange handler?

mikehardy commented 4 years ago

Hi there! I'm not sure this is exactly on target, but I have had no problem integrating Formik and ReactXP. It allows me to do everything I want?

I'm sure there are cleaner ways to do it. But this gives the idea - it has a single handler but Formik does a lot of the busy work

Here's an example


type ProfileFormikValues = {
  firstName: string | undefined;
  secondName: string | undefined;
  citizenNumber: string | undefined;
  dateOfBirth: string;
  profileEmoji: string | undefined;
  emailReadOnly: string | undefined;
  phoneReadOnly: string | undefined;
  memberSinceReadOnly: number | undefined;
};

  private onEnterProfile = async (
    values: ProfileFormikValues,
    actions: FormikHelpers<ProfileFormikValues>
  ) => {
    let { firstName, secondName, citizenNumber, profileEmoji } = values;

    this.setState({ animationState: 'reward' });
    let updatedUser = this.state.user;
    updatedUser!.firstName = firstName;
    updatedUser!.secondName = secondName;
    updatedUser!.citizenNumber = citizenNumber;
    updatedUser!.profileEmoji = profileEmoji;
    UserStore.setUser(updatedUser!);
    actions.setSubmitting(false);

    Analytics.analyticsEvent('successProfileUpdate');
    RX.Alert.show(
      I18NService.translate('ProfileUpdatedTitle'),
      I18NService.translate('ProfileUpdatedText'),
      [
        {
          text: 'OK',
          onPress: () => {
            if (UserStore.isNewUser()) {
              this.props.navigation.navigate('Permisos');
            } else {
              this.props.navigation.navigate('Tablero');
            }
          },
        },
      ]
    );
  };

// ....
render() {
// ...
 return (
//...
          <Formik
            initialValues={{
              firstName: this.state.user && this.state.user.firstName,
              secondName: this.state.user && this.state.user.secondName,
              citizenNumber: this.state.user && this.state.user.citizenNumber,
              dateOfBirth: localeDateString,
              profileEmoji: this.state.user && this.state.user.profileEmoji,
              emailReadOnly: this.state.user && this.state.user.email,
              phoneReadOnly: this.state.user && this.state.user.phoneNumber,
              memberSinceReadOnly: this.state.user && this.state.user.registerTime,
            }}
            onSubmit={(values, actions) => this.onEnterProfile(values, actions)}
            validate={(values) => this.onValidateProfile(values)}
            validateOnBlur={false}
            validateOnChange={false}
          >
            {(props: any) => (
              <RX.ScrollView keyboardDismissMode="on-drag" keyboardShouldPersistTaps="handled">
                <RX.View style={Styles.middleInputBlock}>
                  <RX.View style={{ flex: 0, flexDirection: 'row' }}>
                    <RX.Text style={Styles.profileLabelNames}>
                      {I18NService.translate('ProfileFirstNameLabel')}{' '}
                      {props.errors.firstName && (
                        <RX.Text style={Styles.inputInstructionError}>
                          {props.errors.firstName}
                        </RX.Text>
                      )}
                    </RX.Text>
                    <RX.TextInput
                      autoCorrect={false}
                      // autoComplete={email} - FIXME are these possible in ReactXP?
                      returnKeyType={'next'}
                      keyboardType={'default'}
                      style={Styles.profileInputNames}
                      onChangeText={props.handleChange('firstName')}
                      onBlur={props.handleBlur('firstName')}
                      value={props.values.firstName ? props.values.firstName : ''}
                    />
                  </RX.View>

                  <RX.View style={{ flex: 0, flexDirection: 'row' }}>
                    <RX.Text style={Styles.profileLabelNames}>
                      {I18NService.translate('ProfileSecondNameLabel')}{' '}
                      {props.errors.secondName && (
                        <RX.Text style={Styles.inputInstructionError}>
                          {props.errors.secondName}
                        </RX.Text>
                      )}
                    </RX.Text>
                    <RX.TextInput
                      autoCorrect={false}
                      // autoComplete={email} - FIXME are these possible in ReactXP?
                      returnKeyType={'next'}
                      keyboardType={'default'}
                      style={Styles.profileInputNames}
                      onChangeText={props.handleChange('secondName')}
                      onBlur={props.handleBlur('secondName')}
                      value={props.values.secondName ? props.values.secondName : ''}
                    />
                  </RX.View>

                  <RX.View style={{ flex: 0, flexDirection: 'row' }}>
                    <RX.Text style={Styles.profileLabelNames}>
                      {I18NService.translate('ProfileCedulaLabel')}{' '}
                      {props.errors.citizenNumber && (
                        <RX.Text style={Styles.inputInstructionError}>
                          {props.errors.citizenNumber}
                        </RX.Text>
                      )}
                    </RX.Text>
                    <RX.TextInput
                      autoCorrect={false}
                      // autoComplete={email} - FIXME are these possible in ReactXP?
                      returnKeyType={'next'}
                      keyboardType={'default'}
                      style={Styles.profileInputNames}
                      onChangeText={props.handleChange('citizenNumber')}
                      onBlur={props.handleBlur('citizenNumber')}
                      value={!props.values.citizenNumber ? '' : String(props.values.citizenNumber)}
                    />
                  </RX.View>

                  <RN.TouchableOpacity
                    style={{
                      flex: 1,
                      borderBottomWidth: 0,
                      width: 300,
                      borderColor: '#4D67AC',
                      margin: 5,
                    }}
                    onPress={this._showDatePicker}
                  >
                    <RX.View style={{ flex: 0, flexDirection: 'row' }}>
                      <RX.Text style={Styles.profileInputNames}>
                        {I18NService.translate('ProfileBirthdateLabel')}{' '}
                        {props.errors.dateOfBirth && (
                          <RX.Text style={Styles.inputInstructionError}>
                            {props.errors.dateOfBirth}
                          </RX.Text>
                        )}
                      </RX.Text>
                      <RX.Text style={Styles.profileInputNames}>{localeDateString}</RX.Text>
                    </RX.View>
                    {AppConfig.getPlatformType() === 'ios' && (
                      <DateTimePicker
                        date={
                          this.state.user && this.state.user.dateOfBirth
                            ? new Date(this.state.user!.dateOfBirth!)
                            : new Date()
                        }
                        isDarkModeEnabled={Appearance.getColorScheme() === 'dark' ? true : false}
                        isVisible={this.state.datePickerVisible}
                        onConfirm={this._handleDatePicked}
                        onCancel={this._hideDatePicker}
                      />
                    )}
                  </RN.TouchableOpacity>

                  <RX.View style={{ flex: 0, flexDirection: 'row' }}>
                    <RX.Text style={Styles.profileLabelNames}>
                      <Emoji name={'email'} />
                    </RX.Text>
                    <RX.Text style={Styles.profileLabelNames}>{props.values.emailReadOnly}</RX.Text>
                  </RX.View>

                  <RX.View style={{ flex: 0, flexDirection: 'row' }}>
                    <RX.Text style={Styles.profileLabelNames}>
                      <Emoji name={'telephone'} />
                    </RX.Text>
                    <RX.Text style={Styles.profileLabelNames}>
                      {props.values.phoneReadOnly
                        ? props.values.phoneReadOnly
                        : I18NService.translate('ProfileNoPhone')}
                    </RX.Text>
                  </RX.View>

                  <RX.View style={{ flex: 0, flexDirection: 'row' }}>
                    <RX.Text style={Styles.profileLabelNames}>
                      {I18NService.translate('MemberSinceLabel')}
                    </RX.Text>
                    <RX.Text style={Styles.profileLabelNames}>{localeRegisterDateString}</RX.Text>
                  </RX.View>

                  <RewardsComponent
                    animationType="confetti"
                    state={this.state.animationState}
                    onRest={() => this.setState({ animationState: 'rest' })}
                  >
                    <RX.Button
                      style={[
                        Styles.loginIngresarButton,
                        { alignSelf: 'center', margin: 50, marginRight: 120, width: 200 },
                      ]}
                      onPress={
                        props.isSubmitting
                          ? () => {
                              console.log('we are already submitting');
                            }
                          : props.submitForm
                      }
                    >
                      <RX.Text style={Styles.buttonText}>
                        {I18NService.translate('ProfileSave')}
                      </RX.Text>
                    </RX.Button>
                  </RewardsComponent>
                </RX.View>
              </RX.ScrollView>
            )}
          </Formik>