This series contents:
- Part 1: Create a new React Native app
- Part 2: Create a simple Salary Calculator Form
- Part 3: Create custom form input and button components
- Part 4: Work on the
FormBuilder
component - Part 5: Enable/disable form buttons on-the-fly (current)
- Part 6: Create a Sign Up form
- Part 7: Add support for Boolean field type
Part 5: Enable/disable form buttons on-the-fly
Wouldn't be nice to have our form buttons enabled only when we need? For example:
- disable the
Calculate
button by default, and only enable it when all form fields have been filled out; - disable the
Reset
button by default as well, and only enable it when at least one form field has been filled out.
Modify our FormButton
component
Let's take care of that. First of all, we need to modify our FormButton
component and allow it to accept a boolean disabled
prop which will use to enable or disable our button. The modified version looks like this:
import React from 'react';
import PropTypes from 'prop-types';
import { TouchableOpacity, Text, StyleSheet } from 'react-native';
/**
* A stateless function component which renders a button.
*
* @param {obj} props
*/
const FormButton = (props) => {
const { children, onPress, disabled } = props;
return (
<TouchableOpacity
style={[styles.button, disabled && styles.buttonDisabled]}
onPress={onPress}
disabled={disabled}
>
<Text style={styles.buttonText}>{children}</Text>
</TouchableOpacity>
);
};
FormButton.propTypes = {
onPress: PropTypes.func,
children: PropTypes.string.isRequired,
disabled: PropTypes.bool,
};
FormButton.defaultProps = {
onPress: f => f,
disabled: false,
};
const styles = StyleSheet.create({
button: {
backgroundColor: '#FD6592',
borderRadius: 3,
height: 40,
marginHorizontal: 10,
marginBottom: 15,
justifyContent: 'center',
alignItems: 'center',
},
buttonText: {
color: '#FFF',
fontWeight: 'bold',
fontSize: 16,
},
buttonDisabled: {
opacity: 0.5,
},
});
export default FormButton;
TouchableOpacity
accepts a boolean disabled
prop and when it's true
, it disables all interactions for this component. This is exactly what we need with one small exception: visually the button looks the same in both enabled and disabled states. We can fix that by conditionally adding some styles when the disabled
prop is true
like so (please note that I have replaced some existing code with comments just to highlight the changes we've made):
<TouchableOpacity
style={[styles.button, disabled && styles.buttonDisabled]}
{/* ... */}
const styles = StyleSheet.create({
// ...
buttonDisabled: {
opacity: 0.5,
},
});
Enable/disable the Calculate
button
As we mentioned above, we want our Calculate
button to be enabled only when all form fields have been filled out. Well, we already have our hasValidFormData
helper function which can tell us exactly that. We can use it like so:
<FormButton
onPress={this.attemptFormSubmission}
disabled={!this.hasValidFormData()}
>
{submitBtnTitle}
</FormButton>
Enable/disable the Reset
button
This button needs to be enabled when at least one form field has been filled out. Let's write a little helper function which can help us detect that:
/**
* Check if at least one field has been filled out.
*/
hasDirtyFormData = () => {
const formFields = this.getFormFields();
const isDirty = formFields.some(field => !!this.state[field.name]);
return isDirty;
};
Note how we're making use of the JavaScript Array some() method - very handy for our use-case.
Now we're ready to enable and disable the Reset
button on-the-fly like so:
<FormButton onPress={this.resetForm} disabled={!this.hasDirtyFormData()}>
Reset
</FormButton>
That's it! Let's take a look at how the form works at this point:
For a full list of changes, check out this commit on GitHub.
Great job if you made it so far!π But why stop here? π€ Let's try our component in action one more time and use it to create a Sign Up form in Part 6 of this series π.
Top comments (0)