mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-29 05:00:43 +10:00
Create FieldCheckboxGroup: using FieldGroupCheckbox as starting point
This commit is contained in:
parent
0e86cd5322
commit
7a81956dd1
5 changed files with 278 additions and 0 deletions
28
src/components/FieldCheckboxGroup/FieldCheckboxGroup.css
Normal file
28
src/components/FieldCheckboxGroup/FieldCheckboxGroup.css
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
@import '../../marketplace.css';
|
||||
|
||||
.root {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.list {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.twoColumns {
|
||||
@media (--viewportMedium) {
|
||||
columns: 2;
|
||||
}
|
||||
}
|
||||
|
||||
.item {
|
||||
padding: 2px 0;
|
||||
|
||||
/* Fix broken multi-column layout in Chrome */
|
||||
page-break-inside: avoid;
|
||||
|
||||
@media (--viewportMedium) {
|
||||
padding: 4px 0;
|
||||
}
|
||||
}
|
||||
151
src/components/FieldCheckboxGroup/FieldCheckboxGroup.example.js
Normal file
151
src/components/FieldCheckboxGroup/FieldCheckboxGroup.example.js
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
import React from 'react';
|
||||
import { Form as FinalForm, FormSpy } from 'react-final-form';
|
||||
import arrayMutators from 'final-form-arrays';
|
||||
import { Button } from '../../components';
|
||||
import FieldCheckboxGroup from './FieldCheckboxGroup';
|
||||
import { requiredFieldArrayCheckbox } from '../../util/validators';
|
||||
|
||||
const formName = 'Styleguide.FieldCheckboxGroup';
|
||||
const formNameRequired = 'Styleguide.FieldCheckboxGroupRequired';
|
||||
|
||||
const label = <h3>Amenities</h3>;
|
||||
|
||||
const commonProps = {
|
||||
label: label,
|
||||
options: [
|
||||
{
|
||||
key: 'towels',
|
||||
label: 'Towels',
|
||||
},
|
||||
{
|
||||
key: 'bathroom',
|
||||
label: 'Bathroom',
|
||||
},
|
||||
{
|
||||
key: 'swimming_pool',
|
||||
label: 'Swimming pool',
|
||||
},
|
||||
{
|
||||
key: 'own_drinks',
|
||||
label: 'Own drinks allowed',
|
||||
},
|
||||
{
|
||||
key: 'jacuzzi',
|
||||
label: 'Jacuzzi',
|
||||
},
|
||||
{
|
||||
key: 'audiovisual_entertainment',
|
||||
label: 'Audiovisual entertainment',
|
||||
},
|
||||
{
|
||||
key: 'barbeque',
|
||||
label: 'Barbeque',
|
||||
},
|
||||
{
|
||||
key: 'own_food_allowed',
|
||||
label: 'Own food allowed',
|
||||
},
|
||||
],
|
||||
twoColumns: true,
|
||||
};
|
||||
|
||||
const optionalProps = {
|
||||
name: 'amenities-optional',
|
||||
id: 'amenities-optional',
|
||||
...commonProps,
|
||||
};
|
||||
|
||||
const requiredProps = {
|
||||
name: 'amenities-required',
|
||||
id: `${formNameRequired}.amenities-required`,
|
||||
...commonProps,
|
||||
validate: requiredFieldArrayCheckbox('this is required'),
|
||||
};
|
||||
const tosProps = {
|
||||
name: 'terms-of-service',
|
||||
id: `${formNameRequired}.tos-accepted`,
|
||||
options: [
|
||||
{
|
||||
key: 'tos',
|
||||
label: 'Terms of Service',
|
||||
},
|
||||
],
|
||||
validate: requiredFieldArrayCheckbox('You need to accept Terms of Service'),
|
||||
};
|
||||
|
||||
const formComponent = country => props => (
|
||||
<FinalForm
|
||||
{...props}
|
||||
mutators={{ ...arrayMutators }}
|
||||
render={fieldRenderProps => {
|
||||
const { handleSubmit, invalid, submitting, componentProps, onChange } = fieldRenderProps;
|
||||
|
||||
const submitDisabled = invalid || submitting;
|
||||
|
||||
return (
|
||||
<form
|
||||
onSubmit={e => {
|
||||
e.preventDefault();
|
||||
handleSubmit(e);
|
||||
}}
|
||||
>
|
||||
<FormSpy onChange={onChange} />
|
||||
<FieldCheckboxGroup {...componentProps} />
|
||||
|
||||
<Button style={{ marginTop: 24 }} type="submit" disabled={submitDisabled}>
|
||||
Submit
|
||||
</Button>
|
||||
</form>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
export const Optional = {
|
||||
component: formComponent(formName),
|
||||
props: {
|
||||
onChange: formState => {
|
||||
if (formState.dirty) {
|
||||
console.log('form values changed to:', formState.values);
|
||||
}
|
||||
},
|
||||
onSubmit: values => {
|
||||
console.log('Submit values: ', values);
|
||||
},
|
||||
initialValues: { [optionalProps.name]: ['jacuzzi', 'towels'] },
|
||||
componentProps: optionalProps,
|
||||
},
|
||||
group: 'inputs',
|
||||
};
|
||||
|
||||
export const Required = {
|
||||
component: formComponent(formNameRequired),
|
||||
props: {
|
||||
onChange: formState => {
|
||||
if (formState.dirty) {
|
||||
console.log('form values changed to:', formState.values);
|
||||
}
|
||||
},
|
||||
onSubmit: values => {
|
||||
console.log('Submit values: ', values);
|
||||
},
|
||||
componentProps: requiredProps,
|
||||
},
|
||||
group: 'inputs',
|
||||
};
|
||||
|
||||
export const ToSAccepted = {
|
||||
component: formComponent(formNameRequired),
|
||||
props: {
|
||||
onChange: formState => {
|
||||
if (formState.dirty) {
|
||||
console.log('form values changed to:', formState.values);
|
||||
}
|
||||
},
|
||||
onSubmit: values => {
|
||||
console.log('Submit values: ', values);
|
||||
},
|
||||
componentProps: tosProps,
|
||||
},
|
||||
group: 'inputs',
|
||||
};
|
||||
96
src/components/FieldCheckboxGroup/FieldCheckboxGroup.js
Normal file
96
src/components/FieldCheckboxGroup/FieldCheckboxGroup.js
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
/**
|
||||
* NOTE this component is part of react-final-form instead of Redux Form.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Renders a group of checkboxes that can be used to select
|
||||
* multiple values from a set of options.
|
||||
*
|
||||
* The corresponding component when rendering the selected
|
||||
* values is PropertyGroup.
|
||||
*
|
||||
*/
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { arrayOf, bool, node, shape, string } from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import { FieldArray } from 'react-final-form-arrays';
|
||||
import { FieldCheckbox, ValidationError } from '../../components';
|
||||
|
||||
import css from './FieldCheckboxGroup.css';
|
||||
|
||||
class FieldCheckboxRenderer extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { touched: false };
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
// FieldArray doesn't have touched prop, so we'll keep track of it
|
||||
if (!this.state.touched) {
|
||||
this.setState({ touched: nextProps.meta.dirty });
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { className, rootClassName, label, twoColumns, id, fields, options, meta } = this.props;
|
||||
|
||||
const touched = this.state.touched;
|
||||
|
||||
const classes = classNames(rootClassName || css.root, className);
|
||||
const listClasses = twoColumns ? classNames(css.list, css.twoColumns) : css.list;
|
||||
|
||||
return (
|
||||
<fieldset className={classes}>
|
||||
{label ? <legend>{label}</legend> : null}
|
||||
<ul className={listClasses}>
|
||||
{options.map((option, index) => {
|
||||
const fieldId = `${id}.${option.key}`;
|
||||
return (
|
||||
<li key={fieldId} className={css.item}>
|
||||
<FieldCheckbox
|
||||
id={fieldId}
|
||||
name={fields.name}
|
||||
label={option.label}
|
||||
value={option.key}
|
||||
/>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
<ValidationError fieldMeta={{ ...meta, touched }} />
|
||||
</fieldset>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
FieldCheckboxRenderer.defaultProps = {
|
||||
rootClassName: null,
|
||||
className: null,
|
||||
label: null,
|
||||
twoColumns: false,
|
||||
};
|
||||
|
||||
FieldCheckboxRenderer.propTypes = {
|
||||
rootClassName: string,
|
||||
className: string,
|
||||
id: string.isRequired,
|
||||
label: node,
|
||||
options: arrayOf(
|
||||
shape({
|
||||
key: string.isRequired,
|
||||
label: node.isRequired,
|
||||
})
|
||||
).isRequired,
|
||||
twoColumns: bool,
|
||||
};
|
||||
|
||||
const FieldCheckboxGroup = props => <FieldArray component={FieldCheckboxRenderer} {...props} />;
|
||||
|
||||
// Name and component are required fields for FieldArray.
|
||||
// Component-prop we define in this file, name needs to be passed in
|
||||
FieldCheckboxGroup.propTypes = {
|
||||
name: string.isRequired,
|
||||
};
|
||||
|
||||
export default FieldCheckboxGroup;
|
||||
|
|
@ -32,6 +32,7 @@ export { default as ExternalLink } from './ExternalLink/ExternalLink';
|
|||
export { default as FieldBirthdayInput } from './FieldBirthdayInput/FieldBirthdayInput';
|
||||
export { default as FieldBoolean } from './FieldBoolean/FieldBoolean';
|
||||
export { default as FieldCheckbox } from './FieldCheckbox/FieldCheckbox';
|
||||
export { default as FieldCheckboxGroup } from './FieldCheckboxGroup/FieldCheckboxGroup';
|
||||
export { default as FieldCurrencyInput } from './FieldCurrencyInput/FieldCurrencyInput';
|
||||
export { default as FieldDateInput } from './FieldDateInput/FieldDateInput';
|
||||
export { default as FieldDateRangeInput } from './FieldDateRangeInput/FieldDateRangeInput';
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import * as ExpandingTextarea from './components/ExpandingTextarea/ExpandingText
|
|||
import * as FieldBirthdayInput from './components/FieldBirthdayInput/FieldBirthdayInput.example';
|
||||
import * as FieldBoolean from './components/FieldBoolean/FieldBoolean.example';
|
||||
import * as FieldCheckbox from './components/FieldCheckbox/FieldCheckbox.example';
|
||||
import * as FieldCheckboxGroup from './components/FieldCheckboxGroup/FieldCheckboxGroup.example';
|
||||
import * as FieldCurrencyInput from './components/FieldCurrencyInput/FieldCurrencyInput.example';
|
||||
import * as FieldDateInput from './components/FieldDateInput/FieldDateInput.example';
|
||||
import * as FieldDateRangeInput from './components/FieldDateRangeInput/FieldDateRangeInput.example';
|
||||
|
|
@ -100,6 +101,7 @@ export {
|
|||
FieldBirthdayInput,
|
||||
FieldBoolean,
|
||||
FieldCheckbox,
|
||||
FieldCheckboxGroup,
|
||||
FieldCurrencyInput,
|
||||
FieldDateInput,
|
||||
FieldDateRangeInput,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue