loading...
Cover image for Create a FormBuilder component in React Native (Part 6)

Create a FormBuilder component in React Native (Part 6)

dev_nope profile image Vasile Stefirta πŸ‡²πŸ‡© ✈️ πŸ‡ΊπŸ‡Έ ・4 min read

This series contents:

Part 6: Create a Sign Up form

Now that we have our FormBuilder helper component ready, we can try it in action once more and create another form. As an example, let's assume we need a basic Sign Up form for our mobile app. Let's create a new SignUp.js file within the root of our project with the following content:

import React, { Component } from 'react';
import {
    StyleSheet, KeyboardAvoidingView, SafeAreaView, Text, Alert,
} from 'react-native';

import FormBuilder from './js/components/FormBuilder';

export default class SignUp extends Component {
    getFormFields = () => {
        const formFields = [
            [
                {
                    name: 'firstName',
                    label: 'First Name',
                    type: 'text',
                    inputProps: {
                        autoCorrect: false,
                    },
                },
                {
                    name: 'lastName',
                    label: 'Last Name',
                    type: 'text',
                    inputProps: {
                        autoCorrect: false,
                    },
                },
            ],
            [
                {
                    name: 'email',
                    label: 'Email',
                    type: 'text',
                    inputProps: {
                        autoCorrect: false,
                        autoCapitalize: 'none',
                        keyboardType: 'email-address',
                    },
                },
            ],
            [
                {
                    name: 'skills',
                    label: 'Skills',
                    type: 'text',
                    inputProps: {
                        autoCorrect: false,
                        multiline: true,
                        numberOfLines: 4,
                        blurOnSubmit: false,
                    },
                },
            ],
            [
                {
                    name: 'password',
                    label: 'Password',
                    type: 'text',
                    inputProps: {
                        secureTextEntry: true,
                    },
                },
            ],
        ];

        return formFields;
    };

    /**
     * Grab user's input data.
     */
    handleSubmit = (state) => {
        const {
            firstName, lastName, email, skills, password,
        } = state;

        Alert.alert(
            'Your info',
            `First Name: ${firstName}\n Last Name: ${lastName}\n Email: ${email}\n Skills: ${skills} \n Password: ${password}`,
        );
    };

    render() {
        return (
            <SafeAreaView style={styles.safeArea}>
                <KeyboardAvoidingView behavior="padding" style={styles.container}>
                    <Text style={styles.screenTitle}>Sign Up</Text>
                    <FormBuilder
                        formFieldsRows={this.getFormFields()}
                        handleSubmit={this.handleSubmit}
                        submitBtnTitle="Sign Up"
                    />
                </KeyboardAvoidingView>
            </SafeAreaView>
        );
    }
}

const styles = StyleSheet.create({
    safeArea: {
        flex: 1,
        backgroundColor: '#3F4EA5',
    },
    container: {
        flex: 1,
        justifyContent: 'center',
        paddingHorizontal: 10,
        backgroundColor: '#3F4EA5',
    },
    screenTitle: {
        fontSize: 35,
        textAlign: 'center',
        margin: 10,
        color: '#FFF',
    },
});

As you can see we're defining our form fields within getFormFields() which are the following:

  • First Name
  • Last Name
  • Email
  • Skills
  • Password

Because we have introduced the idea of having form rows, we are able to control the form layout and place First Name and Last Name in the same row next to each other.

Also, the fact that we can provide default React Native props to our form inputs/controls via the inputProps object property, we are able to:

  • mask the Password field's value using the secureTextEntry prop;
  • have the Skills field be a multiline text input (same as an HTML textarea) by using the multiline and numberOfLines props.

The multiline prop should work out-of-the-box but from a UI perspective, our Skills field will look the same as a one-line regular text input. We can fix that by conditionally adding some styles to our custom FormTextInput component when the multiline prop is true like so (please note that I have replaced some existing code with comments just to highlight the changes we've made):

// ...
class FormTextInput extends React.Component {
    render() {
        const { labelText, multiline, ...inputProps } = this.props;

        return (
            <View style={styles.inputWrapper}>
                {/* ... */}
                <TextInput
                    style={[styles.textInput, multiline && styles.textarea]}
                    blurOnSubmit
                    {...inputProps}
                    multiline={multiline}
                />
            </View>
        );
    }
}

FormTextInput.propTypes = {
    // ...
    multiline: PropTypes.bool,
};

FormTextInput.defaultProps = {
    // ...
    multiline: false,
};

const styles = StyleSheet.create({
    // ...
    textarea: {
        height: 80,
    },
});

export default FormTextInput;

Now it's time to show our new form when the app loads. For that, we need to modify our index.js file and instruct the app to use our SignUp component as the first screen instead of App. We'll also add a flag here called showCalculatorForm which we can set to true if we want the Calculator form to show up, or to false - if we want to see the Sign Up form. Here's the modified version of index.js:

import { AppRegistry } from 'react-native';
import App from './App';
import SignUp from './SignUp';
import { name as appName } from './app.json';

// NOTE: set this flag to `true` if you want to see the Salary Calculator form
const showCalculatorForm = false;

AppRegistry.registerComponent(appName, () => (showCalculatorForm ? App : SignUp));

That's it! Run the app again and you should see the following:

Sign Up Form

For a full list of changes, check out this commit on GitHub.


Awesome, that looks great! πŸ‘ πŸ”₯ BUT, what about supporting some other field types beside regular text inputs? πŸ€” πŸ€“ Well, check out Part 7 where we'll add support for a new Boolean field type πŸ‘‰.

Discussion

pic
Editor guide