@ackee/mateus v1.0.1
We're moving to modern form solutions like Formik, Final Form or React Hook form and therefore these Redux Form bindings are not needed anymore.

Mateus
Antd components as a form fields + redux-saga flow for easier handle of redux-form form's submit.
Name of package Mateus refers to name of the apostole Matthew which is a patron of all office workers. Mateus is a Portuguese equivalent for Matthew.
Table of contents
Installation
Using npm:
npm i -S @ackee/mateusAPI
Action creators
submitForm(formId: string, submitActionCreator: () => object): function
formIdForm unique identificatorsubmitActionCreatorAction creator for form specific submit actionReturns Form submit handler that is used for
handleSubmitprop ofredux-formForm.Example - use
submitForminreact-reduxcontainerimport { connect } from 'react-redux'; import { bindActionCreators, compose } from 'redux'; import UserForm from './components/UserForm'; const createUserAction = () => ({ type: 'CREATE_USER' }) const formId = 'createUserForm'; export default compose( connect( (state) => ({ initialValues: { }, }), dispatch => ({ onSubmit: bindActionCreators( formActions.submitForm(formId, createUserAction), dispatch, ), }), ), reduxForm({ form: formId, }), )(UserForm);
Action types
FORM_SUBMIT
import { actionTypes } from '@ackee/mateus';
import { takeEvery } from 'redux-saga/effects';
takeEvery(actionTypes.FORM_SUBMIT, action => {
const { data, form } = action;
console.log('Submitted form', form);
});Sagas
submitFormSaga(): void
Form saga ensures you receive all neccessary data and methods (eg. for handling form flow) in form submit handler. Just use it as your only saga, or in list of sagas.
In parallel with form submit saga, you will likely want to use submitForm action creator.
Examples - Usage
import { submitFormSaga as formSaga } from 'ackee-frontend-toolkit/sagas';
// main saga
export default function* () {
yield all([
// ... other sagas
formSaga(),
]);
}Complete example of using form saga flow
Handling form submit using our submitForm saga in redux-form is easy and enable separation of concerns.
It's all divided into few simple steps
- Plug
submitFormSagainto main saga - Use
submitFormaction as a handler of form submit - Catch action provided as a second parameter to
submitFormand hadle it by custom saga. - Manage whole
redux-formsubmit process, including startSubmit, stopSubmit and reset, in custom saga.
Example is a bit shortened and simplified:
// config/index.js
export default {
// ...
forms: {
addUser: 'addUserForm',
}
api: {
user: '/api/v1/user',
}
}// actions/user.js
export const addUserAction = () => ({
type: 'ADD_USER'
})// components/UserForm.js
const UserForm = ({ handleSubmit, submitting }) => (
<Form onSubmit={handleSubmit}>
<Field
disabled={submitting}
id="firstname"
name="firstname"
component={Input}
type="text"
/>
<Field
disabled={submitting}
id="lastname"
name="lastname"
component={Input}
type="text"
/>
<button type="submit">Add user</button>
</Form>
);
UserForm.propTypes = {
// these props are automatically supplied by reduxForm()
handleSubmit: PropTypes.func.isRequired,
submitting: PropTypes.bool.isRequired,
invalid: PropTypes.bool.isRequired,
};
export default UserForm;// containers/UserForm.js
import { submitForm } from '@ackee/mateus';
import { addUserAction } from '../actions/user';
import config from '../config';
export default compose(
connect(
(state) => ({
initialValues: {},
}),
dispatch => ({
onSubmit: bindActionCreators(
submitForm(config.forms.addUser, addUserAction),
dispatch,
),
}),
),
reduxForm({
form: config.forms.addUser,
}),
)(UserForm);// sagas/index.js
import { submitFormSaga } from '@ackee/mateus';
import userSaga from '../sagas/userSaga';
export default function* () {
yield all([
submitFormSaga(),
userSaga(),
]);
}// sagas/userSaga.js
import config from '../config';
function* handleAddUserForm(action) {
const { data, startSubmit, stopSubmit, reset } = action;
yield startSubmit();
try {
yield api.post(
config.api.user,
{
firstname: data.firstname,
lastname: data.lastname,
},
);
yield stopSubmit();
yield reset();
} catch (e) {
const errors = { 'user add error': e };
yield stopSubmit(errors);
}
}
export default function* () {
yield all([
takeEvery('ADD_USER', handleAddUserForm),
]);
}Form fields
All form fields are available either as an Antd component (eg. TextInput) wrapped with FormItem or the same, but enclosed into redux-form Field.
List of fields:
Text
TextInputaccept AntdInputprops.TextFieldaccept same props as Input plus all the props you can pass to redux-form Field.import { TextInput, TextField } from '@ackee/mateus';
TextArea
TextAreaInputaccept AntdTextAreaprops.TextAreaFieldaccept same props as Input plus all the props you can pass to redux-form Field.import { TextAreaInput, TextAreaField } from '@ackee/mateus';
Select
SelectInputaccept AntdSelectprops, but instead of passing options as children components, they'are passed as an array in props.Default name for that prop is
optionsand it's shape is{ label: ReactNode, value: string|number }. The names can be changed by specifyingoptionsKey,labelKeyorvalueKeyprop (look at example below).SelectFieldaccept same props as Input plus all the props you can pass to redux-form Field.import { SelectInput, SelectField } from '@ackee/mateus'; const select = ( <SelectInput options={[ { label: 'Option1': value: 1 }, { label: <span>Option2</span>: value: 2 }, ]} /> ); const selectWithCustomNames = ( <SelectInput optionsKey="users" labelKey="name" valueKey="id" users={[ { name: 'Anakin', id: 'siths1' }, { name: 'Luke', id: 'jedis1' }, ]} /> );
NumberInput
NumberInputaccept AntdInputNumberprops.NumberFieldaccept same props as Input plus all the props you can pass to redux-form Field.import { NumberInput, NumberField } from '@ackee/mateus';
Switch
SwitchInputaccept AntdSwitchprops.SwitchFieldaccept same props as Input plus all the props you can pass to redux-form Field.import { SwitchInput, SwitchField } from '@ackee/mateus';
Slider
SliderInputaccept AntdSliderprops.SliderFieldaccept same props as Input plus all the props you can pass to redux-form Field.import { SliderInput, SliderField } from '@ackee/mateus';
Radio
This is a bit confusing, because RadioInput is actually RadioGroup - in most cases we want to render group of radios to let user select one option so we don't need an individual Radio. If from any reason you realy need only one Radio without RadioGroup just feel free to use it directly from antd.
RadioInputaccept AntdRadioGroupprops, but with several differencies- the definition
optionsprop is a bit changed. It lacksdisabledfield so the shape is just{ label: ReactNode, value: string|number }. - on the other hand, as same as for
Selectyou can specify custom names for props and the shape keys by specifyingoptionsKey,labelKeyorvalueKeyprop (look at example below). - you can pass
buttonprop of type boolean that force use of radio buttons instead of plain radios.
- the definition
RadioFieldaccept same props as Input plus all the props you can pass to redux-form Field.import { RadioInput, RadioField } from '@ackee/mateus'; const selectYourFavourite = ( <RadioInput optionsKey="southPark" labelKey="name" valueKey="color" southPark={[ { name: 'Kenny', color: 'orange' }, { name: 'Cartman', color: 'fat' }, { name: 'Stan', color: 'blue' }, { name: 'Kyle', color: 'green' }, ]} button /> );
CheckboxGroup
CheckboxGroupInputaccept AntdCheckboxGroupprops.CheckboxGroupFieldaccept same props as Input plus all the props you can pass to redux-form Field.import { CheckboxGroupInput, CheckboxGroupField } from '@ackee/mateus';
DatePicker & TimePicker
- Both pickers accept props from shared API plus:
DatePickerInputaccept AntdDatePickerprops.TimePickerInputaccept AntdTimePickerprops.- both accept
displayFormatprop which is the same asformatprop defined in picker's API. But since redux-formFieldhas alsoformatprop and so Input's one would be overriden when usingDatePickerFieldorTimePickerField, wee need to provide an alternative.
DatePickerField/TimePickerFieldaccept same props asDatePickerInput/TimePickerInputplus all the props you can pass to redux-form Field.import { DatePickerInput, DatePickerField, TimePickerInput, TimePickerField } from '@ackee/mateus';
pickerEnhancer
TBD
import { pickerEnhancer } from '@ackee/mateus';
HOC
wrapWithField(component: React.Component, injectProps?: InjectPropsType): React.Component
Hight order component that wrap supplied component with redux-form's Field and inject extra properties into it (see InjectPropsType). This is useful for form fields that are not part of @ackee/mateus.
InjectPropsTypeis either an propsobjector function(props: object): objectthat receives props passed to component and returns extra props that will be also passed to componentExample - use it fo Antd
Ratecomponentconst Rate = wrapWithField( AntdRate, { character: <Icon type="heart" /> } ); const RateForm = ({ handleSubmit, invalid }) => ( <Form onSubmit={handleSubmit}> <Rate /> </Form> );