Skip to content

Commit

Permalink
Add support for Boolean field type
Browse files Browse the repository at this point in the history
  • Loading branch information
vasilestefirta committed Mar 18, 2019
1 parent fdf9a54 commit 87d8ca9
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 6 deletions.
12 changes: 10 additions & 2 deletions SignUp.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ export default class SignUp extends Component {
},
},
],
[
{
name: 'subscribe',
label: 'Subscribe me to weekly news from Tech world.',
type: 'boolean',
defaultValue: true,
},
],
];

return formFields;
Expand All @@ -71,12 +79,12 @@ export default class SignUp extends Component {
*/
handleSubmit = (state) => {
const {
firstName, lastName, email, skills, password,
firstName, lastName, email, skills, password, subscribe,
} = state;

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

Expand Down
46 changes: 46 additions & 0 deletions js/components/FormBooleanInput.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
View, Switch, Text, StyleSheet,
} from 'react-native';

/**
* A stateless function component which renders a Boolean input (Switch).
*
* @param {obj} props
*/
const FormBooleanInput = (props) => {
const { labelText, ...inputProps } = props;

return (
<View style={styles.switchWrapper}>
<Switch {...inputProps} />
{labelText && <Text style={styles.label}>{labelText}</Text>}
</View>
);
};

FormBooleanInput.propTypes = {
labelText: PropTypes.string,
};

FormBooleanInput.defaultProps = {
labelText: null,
};

const styles = StyleSheet.create({
switchWrapper: {
flex: 1,
marginBottom: 15,
paddingHorizontal: 10,
flexDirection: 'row',
alignItems: 'center',
},
label: {
flex: 1,
color: '#FFF',
marginLeft: 10,
},
});

export default FormBooleanInput;
65 changes: 61 additions & 4 deletions js/components/FormBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
} from 'react-native';

import FormTextInput from './FormTextInput';
import FormBooleanInput from './FormBooleanInput';
import FormButton from './FormButton';

/**
Expand All @@ -20,7 +21,7 @@ class FormBuilder extends React.Component {
// dynamically construct our initial state by using
// each form field's name as an object property.
const formFieldNames = formFields.reduce((obj, field) => {
obj[field.name] = '';
obj[field.name] = this.getFormFieldDefaultValue(field);
return obj;
}, {});

Expand Down Expand Up @@ -49,13 +50,35 @@ class FormBuilder extends React.Component {
return formFields;
};

/**
* Determine what should be the default value
* for a given field.
*/
getFormFieldDefaultValue = ({ defaultValue, type }) => {
if (defaultValue !== undefined) {
return defaultValue;
}

switch (type) {
case 'boolean':
return false;
default:
return '';
}
};

/**
* Check if all fields have been filled out.
*/
/* eslint-disable react/destructuring-assignment */
hasValidFormData = () => {
const formFields = this.getFormFields();
const isFilled = formFields.every(field => !!this.state[field.name]);
const isFilled = formFields
// filter out Boolean fields because they will always have a value
.filter(field => field.type !== 'boolean')
// check if all remaining fields have been filled out
.every(field => !!this.state[field.name]);

return isFilled;
};

Expand All @@ -64,7 +87,18 @@ class FormBuilder extends React.Component {
*/
hasDirtyFormData = () => {
const formFields = this.getFormFields();
const isDirty = formFields.some(field => !!this.state[field.name]);
const isDirty = formFields.some((field) => {
switch (field.type) {
case 'boolean':
// because Boolean fields will have a default value,
// we need to check if the current value is not the default one
return this.state[field.name] !== this.getFormFieldDefaultValue(field);

default:
return !!this.state[field.name];
}
});

return isDirty;
};
/* eslint-enable react/destructuring-assignment */
Expand Down Expand Up @@ -105,6 +139,20 @@ class FormBuilder extends React.Component {
);
/* eslint-enable react/destructuring-assignment */

/* eslint-disable react/destructuring-assignment */
renderBooleanInput = ({ name, label, inputProps }) => (
<FormBooleanInput
{...inputProps}
value={this.state[name]}
onValueChange={(value) => {
this.setState({ [name]: value });
}}
labelText={label}
key={name}
/>
);
/* eslint-enable react/destructuring-assignment */

render() {
const { submitBtnTitle, formFieldsRows } = this.props;

Expand All @@ -113,7 +161,15 @@ class FormBuilder extends React.Component {
{/* eslint-disable react/no-array-index-key */}
{formFieldsRows.map((formFieldsRow, i) => (
<View style={styles.row} key={`r-${i}`}>
{formFieldsRow.map(field => this.renderTextInput(field))}
{formFieldsRow.map((field) => {
switch (field.type) {
case 'boolean':
return this.renderBooleanInput(field);

default:
return this.renderTextInput(field);
}
})}
</View>
))}
{/* eslint-enable react/no-array-index-key */}
Expand Down Expand Up @@ -142,6 +198,7 @@ FormBuilder.propTypes = {
label: PropTypes.string,
type: PropTypes.string,
inputProps: PropTypes.object,
defaultValue: PropTypes.any,
}),
),
).isRequired,
Expand Down

0 comments on commit 87d8ca9

Please sign in to comment.