Refactor FieldDateRangeInput: use Field connector from Final Form

This commit is contained in:
Vesa Luusua 2018-04-16 11:49:52 +03:00
parent 4a85e04fd9
commit 8f3122df85
4 changed files with 60 additions and 35 deletions

View file

@ -21,7 +21,7 @@ import css from './DateRangeInput.css';
export const HORIZONTAL_ORIENTATION = 'horizontal';
export const ANCHOR_LEFT = 'left';
// Since redux-form tracks the onBlur event for marking the field as
// Since final-form tracks the onBlur event for marking the field as
// touched (which triggers possible error validation rendering), only
// trigger the event asynchronously when no other input within this
// component has received focus.
@ -89,6 +89,8 @@ const defaultProps = {
horizontalMargin: 0,
withPortal: false,
withFullScreenPortal: false,
appendToBody: false,
disableScroll: false,
daySize: 38,
isRTL: false,
initialVisibleMonth: null,
@ -202,12 +204,12 @@ class DateRangeInputComponent extends Component {
onBlur,
onChange,
onFocus,
onDragStart,
onDrop,
phrases,
screenReaderInputMessage,
useMobileMargins,
value,
children,
render,
...datePickerProps
} = this.props;
/* eslint-enable no-unused-vars */
@ -268,6 +270,8 @@ DateRangeInputComponent.defaultProps = {
DateRangeInputComponent.propTypes = {
className: string,
startDateId: string,
endDateId: string,
unitType: propTypes.bookingUnitType.isRequired,
focusedInput: oneOf([START_DATE, END_DATE]),
initialDates: instanceOf(Date),
@ -277,8 +281,6 @@ DateRangeInputComponent.propTypes = {
onChange: func.isRequired,
onBlur: func.isRequired,
onFocus: func.isRequired,
onDragStart: func.isRequired,
onDrop: func.isRequired,
phrases: shape({
closeDatePicker: string,
clearDate: string,

View file

@ -1,35 +1,48 @@
/* eslint-disable no-console */
import React from 'react';
import { reduxForm, propTypes as formPropTypes } from 'redux-form';
import { Form as FinalForm, FormSpy } from 'react-final-form';
import moment from 'moment';
import { Button } from '../../components';
import { required, bookingDatesRequired } from '../../util/validators';
import { required, bookingDatesRequired, composeValidators } from '../../util/validators';
import { LINE_ITEM_NIGHT } from '../../util/types';
import FieldDateRangeInput from './FieldDateRangeInput';
const FormComponent = props => {
const { form, handleSubmit, pristine, submitting, dateInputProps } = props;
const submitDisabled = pristine || submitting;
return (
<form onSubmit={handleSubmit}>
<FieldDateRangeInput {...dateInputProps} />
<Button type="submit" disabled={submitDisabled} style={{ marginTop: '24px' }}>
Select
</Button>
</form>
);
};
const FormComponent = props => (
<FinalForm
{...props}
render={fieldRenderProps => {
const {
form,
handleSubmit,
onChange,
pristine,
submitting,
dateInputProps,
} = fieldRenderProps;
const submitDisabled = pristine || submitting;
FormComponent.propTypes = formPropTypes;
return (
<form
onSubmit={e => {
e.preventDefault();
handleSubmit(e);
}}
>
<FormSpy onChange={onChange} />
<FieldDateRangeInput {...dateInputProps} />
<Button type="submit" disabled={submitDisabled} style={{ marginTop: '24px' }}>
Select
</Button>
</form>
);
}}
/>
);
const defaultFormName = 'Styleguide.DateRangeInput.Form';
const Form = reduxForm({
form: defaultFormName,
})(FormComponent);
const defaultFormName = 'FieldDateRangeInputExampleForm';
export const Empty = {
component: Form,
component: FormComponent,
props: {
dateInputProps: {
name: 'bookingDates',
@ -43,19 +56,22 @@ export const Empty = {
.add(1, 'days')
.format('ddd, MMMM D'),
format: null,
validate: [
validate: composeValidators(
required('Required'),
bookingDatesRequired('Start date is not valid', 'End date is not valid'),
],
bookingDatesRequired('Start date is not valid', 'End date is not valid')
),
onBlur: () => console.log('onBlur called from DateRangeInput props.'),
onFocus: () => console.log('onFocus called from DateRangeInput props.'),
},
onChange: values => {
const { startDate, endDate } = values;
console.log('Changed to', moment(startDate).format('L'), moment(endDate).format('L'));
onChange: formState => {
const { startDate, endDate } = formState.values;
if (startDate || endDate) {
console.log('Changed to', moment(startDate).format('L'), moment(endDate).format('L'));
}
},
onSubmit: values => {
console.log('Submitting a form with values:', values);
return false;
},
},
group: 'custom inputs',

View file

@ -1,6 +1,13 @@
/**
* Provides a date picker for Final Forms (using https://github.com/airbnb/react-dates)
*
* NOTE: If you are using this component inside BookingDatesForm,
* you should convert value.date to start date and end date before submitting it to API
*/
import React, { Component } from 'react';
import { bool, func, object, oneOf, string } from 'prop-types';
import { Field } from 'redux-form';
import { Field } from 'react-final-form';
import classNames from 'classnames';
import { START_DATE, END_DATE } from '../../util/dates';
import { propTypes } from '../../util/types';
@ -117,6 +124,8 @@ class FieldDateRangeInputComponent extends Component {
...restOfInput,
...rest,
focusedInput: this.state.focusedInput,
startDateId,
endDateId,
};
const classes = classNames(rootClassName || css.fieldRoot, className);
const errorClasses = classNames({ [css.mobileMargins]: useMobileMargins });

View file

@ -18,8 +18,6 @@ describe('DateRangeInput', () => {
onBlur: noop,
onChange: noop,
onFocus: noop,
onDragStart: noop,
onDrop: noop,
startDateId: 'bookingStartDate',
startDatePlaceholderText: 'today',
endDateId: 'bookingEndDate',