Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions src/modules/wizard/components/PagesWithReduxForm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from "react";
import WithReduxFormWizardPageValidation from "./WithReduxFormWizardPageValidation";

const PagesWithReduxForm = ({
handleSubmit,
currentPageIndex,
pagesCount,
currentPage
}) => {
return (
<form
onSubmit={
currentPageIndex + 1 === pagesCount
? handleSubmit(currentPage.props.onSubmit)
: handleSubmit
}
>
{React.createElement(currentPage.component)}
</form>
);
};

export default WithReduxFormWizardPageValidation(PagesWithReduxForm, props => {
return {
isLastPage:
props && props.currentPageIndex + 1 === props.pagesCount ? true : false,
formName: "PageWithReduxFormsValidations",
requiresInitialization: false
};
});
113 changes: 56 additions & 57 deletions src/modules/wizard/components/WithReduxFormWizardPageValidation.js
Original file line number Diff line number Diff line change
@@ -1,69 +1,68 @@
import React from "react";
import ValidatingReduxFormWizardPageContainer from "./ValidatingReduxFormWizardPageContainer";
import { reduxForm, SubmissionError } from "redux-form";
import _ from "lodash";
import { reduxForm, SubmissionError } from "redux-form";
import ValidatingReduxFormWizardPageContainer from "./ValidatingReduxFormWizardPageContainer";
import { getWizardErrors } from "../wizard.selectors";
import { getState } from "../../store";

const WithReduxFormWizardPageValidation = (
wrappedComponent,
{
formName,
handlesValidation,
requiresInitialization = false,
isLastPage = false
}
) => {
let config;
const WithReduxFormWizardPageValidation = (wrappedComponent, data) => {
return class extends React.Component {
constructor(props) {
super(props);
let config = {};
if (data(props).isLastPage) {
config = {
form: data(props).formName,
destroyOnUnmount: false,
forceUnregisterOnUnmount: true,
keepDirtyOnReinitialize: true,
enableReinitialize: true
};
} else {
config = {
form: data(props).formName,
destroyOnUnmount: false,
forceUnregisterOnUnmount: true,
onSubmit: submit
};
}
this.state = {
config
};
}

if (isLastPage) {
config = {
form: formName,
destroyOnUnmount: false,
forceUnregisterOnUnmount: true,
keepDirtyOnReinitialize: true,
enableReinitialize: true
};
} else {
config = {
form: formName,
destroyOnUnmount: false,
forceUnregisterOnUnmount: true,
onSubmit: submit
};
}
render() {
const page = reduxForm(this.state.config)(wrappedComponent);
return (
<ValidatingReduxFormWizardPageContainer
formName={this.state.config.form}
handlesValidation
requiresInitialization={data(this.props).requiresInitialization}
{...this.props}
>
{React.createElement(page, this.props)}
</ValidatingReduxFormWizardPageContainer>
);
}
};

const page = reduxForm(config)(wrappedComponent);
// values left so we know it's available
function submit() {
// We can do form level validations here if needed using values
const wizardErrors = getWizardErrors(getState());

return props => (
<ValidatingReduxFormWizardPageContainer
formName={formName}
handlesValidation={handlesValidation}
requiresInitialization={requiresInitialization}
{...props}
>
{React.createElement(page, props)}
</ValidatingReduxFormWizardPageContainer>
);
};

// values left so we know it's available
function submit() {
// We can do form level validations here if needed using values

const wizardErrors = getWizardErrors(getState());
if (!_.isEmpty(wizardErrors)) {
// We've got errors so let redux form know by returning a rejected promise
return Promise.reject(
new SubmissionError({
...wizardErrors
})
);
}

if (!_.isEmpty(wizardErrors)) {
// We've got errors so let redux form know by returning a rejected promise
return Promise.reject(
new SubmissionError({
...wizardErrors
})
);
// No errors so let redux form know we are all good by returning a resolved promise
return Promise.resolve();
}

// No errors so let redux form know we are all good by returning a resolved promise
return Promise.resolve();
}
};

export default WithReduxFormWizardPageValidation;
14 changes: 13 additions & 1 deletion src/modules/wizard/components/Wizard.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { Fragment } from "react";
import classNames from "classnames";
import "./wizard.css";
import PagesWithReduxForm from "./PagesWithReduxForm";

const Step = ({ stepNumber, currentStep, page }) => {
const isCurrentStep = stepNumber === currentStep;
Expand Down Expand Up @@ -78,9 +79,20 @@ const Wizard = ({
<div>
<h3>{pages && pages[currentPage] && pages[currentPage].title}</h3>
{currentPage >= 0 &&
pages[currentPage].hasOwnProperty("props") &&
pages[currentPage].props.hasOwnProperty("formName") ? (
<PagesWithReduxForm
currentPage={pages[currentPage]}
pagesCount={pages.length}
currentPageIndex={currentPage}
/>
) : (
currentPage >= 0 &&
React.createElement(pages[currentPage].component, {
...pages[currentPage].props
})}
})
)}

<WizardBreadCrub pages={pages} currentStep={currentPage + 1} />
<div style={{ overflow: "auto" }}>
<div>
Expand Down
13 changes: 12 additions & 1 deletion src/modules/wizard/components/WizardContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import { wizardStates } from "../wizard.constants";
export class WizardContainer extends Component {
componentDidMount() {
const { pages, startWizard, name } = this.props;

startWizard(name, pages.length);
}

Expand All @@ -36,6 +35,17 @@ export class WizardContainer extends Component {
nextClicked
} = this.props;

let pagesWithReduxForm = [];
if (pages) {
pagesWithReduxForm = pages.reduce((acc, field, index) => {
if (field.props && field.props.formName) {
field.index = index;
acc.push(field);
}
return acc;
}, []);
}

return (
<Wizard
pages={pages}
Expand All @@ -45,6 +55,7 @@ export class WizardContainer extends Component {
handleCancel={cancelClicked}
handleNext={nextClicked}
isLastPage={isLastPage}
pagesWithReduxForm={pagesWithReduxForm}
/>
);
}
Expand Down
32 changes: 30 additions & 2 deletions src/screens/wizardExample/components/WizardExampleContainer.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { Component } from "react";
import { connect } from "react-redux";
import { SubmissionError } from "redux-form";
import wizard from "../../../modules/wizard";
import PageWithValidations from "./samplePages/PageWithValidations";
import PageWithInitializations from "./samplePages/PageWithInitializations";
Expand Down Expand Up @@ -30,6 +31,26 @@ class WizardExampleContainer extends Component {
}
}

handleSubmit = values => {
if (
values.requiredText &&
values.requiredText.toLowerCase() === "servererror"
) {
const errors = {
requiredText: "A fake server error occurred. Please try again."
};

const addEditPromoDetailsPage = 4;
this.props.pageNotValid(addEditPromoDetailsPage);

throw new SubmissionError(errors);
}

alert(`Submit succeeded with values: ${JSON.stringify(values)}`);

return Promise.resolve("Success!");
};

render() {
return (
<div className="wizard-container">
Expand Down Expand Up @@ -58,10 +79,14 @@ class WizardExampleContainer extends Component {
title: "Step 5: Page with redux forms validations",
props: { formName: "PageWithReduxFormsValidations" }
},

{
component: LastPageOfWizardWithReduxFormsValidations,
title: "Step 6: Last page with redux forms validations",
props: { formName: "PageWithReduxFormsValidations" }
props: {
formName: "PageWithReduxFormsValidations",
onSubmit: this.handleSubmit
}
}
]}
formName="PageWithReduxFormsValidations"
Expand All @@ -75,4 +100,7 @@ const mapStateToProps = state => ({
wizard: getWizardState(state)
});

export default connect(mapStateToProps)(WizardExampleContainer);
export default connect(
mapStateToProps,
{ pageNotValid: wizard.actions.pageNotValid }
)(WizardExampleContainer);
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from "react";
import { Field, SubmissionError } from "redux-form";
import { Field } from "redux-form";
import { connect } from "react-redux";
import "../wizardExample.css";
import wizard from "../../../../modules/wizard";
Expand All @@ -10,53 +10,19 @@ const {
validators: { required }
} = forms;

const {
components: { WithReduxFormWizardPageValidation }
} = wizard;

let PageWithReduxFormsValidations = ({ onSubmit, handleSubmit, ...rest }) => (
<form onSubmit={handleSubmit(onSubmit)}>
<Field
component={ValidatingInputField}
type="number"
name="requiredNumber"
validate={[required]}
label="Required Number"
/>
</form>
);

PageWithReduxFormsValidations = WithReduxFormWizardPageValidation(
PageWithReduxFormsValidations,
{
formName: "PageWithReduxFormsValidations",
isLastPage: true
}
const PageWithReduxFormsValidations = () => (
<Field
component={ValidatingInputField}
type="number"
name="requiredNumber"
validate={[required]}
label="Required Number"
/>
);

class PageWithReduxFormsValidationsContainer extends React.Component {
handleSubmit = values => {
if (
values.requiredText &&
values.requiredText.toLowerCase() === "servererror"
) {
const errors = {
requiredText: "A fake server error occurred. Please try again."
};

const addEditPromoDetailsPage = 4;
this.props.pageNotValid(addEditPromoDetailsPage);

throw new SubmissionError(errors);
}

alert(`Submit succeeded with values: ${JSON.stringify(values)}`);

return Promise.resolve("Success!");
};

render() {
return <PageWithReduxFormsValidations onSubmit={this.handleSubmit} />;
return <PageWithReduxFormsValidations />;
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,21 @@
import React from "react";
import { Field } from "redux-form";
import "../wizardExample.css";
import wizard from "../../../../modules/wizard";
import forms from "../../../../modules/forms";

const {
components: { ValidatingInputField },
validators: { required }
} = forms;

const {
components: { WithReduxFormWizardPageValidation }
} = wizard;

const PageWithReduxFormsValidations = props => (
<form onSubmit={props.handleSubmit}>
<Field
component={ValidatingInputField}
type="text"
name="requiredText"
validate={[required]}
label="Required Text"
/>
</form>
const PageWithReduxFormsValidations = () => (
<Field
component={ValidatingInputField}
type="text"
name="requiredText"
validate={[required]}
label="Required Text"
/>
);

export default WithReduxFormWizardPageValidation(
PageWithReduxFormsValidations,
{ formName: "PageWithReduxFormsValidations" }
);
export default PageWithReduxFormsValidations;