so I have a 3 page redux wizard form, whenever a new page is opened the view starts at the middle of the form, meaning the user must scroll to the top themselves. My form is in a react-modal
. I played around with window.scrollTo
but this of course won't work as I don't want to change the window location, rather the form in the modal.
I can't find many similar situations as mine as I have a form inside a modal.
This problem only applies to the mobile view and tablet view of my site. The desktop view is fine.
Would anyone have any hints as to what I should look at?
modal component
import React, { Component } from "react";
import Modal from "react-modal";
//Components
import QuoteForm from "./form.js";
class GetQuote extends Component {
constructor(props) {
super(props);
this.state = {
showModal: false
};
}
componentDidMount() {
Modal.setAppElement("body");
}
toggleModal = () => {
this.setState(prevState => {
return { showModal: !prevState.showModal };
});
};
render() {
return (
<div className="modalBtn-container">
<button className={this.props.type} onClick={this.toggleModal}>
{this.props.text}
</button>
<Modal
className={this.props.modalStyle}
isOpen={this.state.showModal}
onRequestClose={this.toggleModal}
contentLabel="popup modal form"
>
<QuoteForm toggleModal={this.toggleModal} />
</Modal>
</div>
);
}
}
export default GetQuote;
form component
import React, { Component } from "react";
//Components
import QuoteFormFirstPage from "./formFirstPage.js";
import QuoteFormSecondPage from "./formSecondPage.js";
class QuoteForm extends Component {
constructor(props) {
super(props);
this.state = {
page: 1
};
this.myRef = React.createRef();
this.nextPage = this.nextPage.bind(this);
this.previousPage = this.previousPage.bind(this);
}
nextPage() {
this.setState({ page: this.state.page + 1 });
this.scrollToMyRef();
}
previousPage() {
this.setState({ page: this.state.page - 1 });
}
scrollToMyRef = () => {
console.log(this.myRef.current.offsetTop);
window.scrollTo(0, this.myRef.current.offsetTop);
};
render() {
const { page } = this.state;
return (
<div className="quote-container" ref={this.myRef}>
{page === 1 && (
<QuoteFormFirstPage
close={this.props.toggleModal}
onSubmit={this.nextPage}
currentPage={page}
initialValues={this.props.initialValues}
enableReinitialize={true}
/>
)}
{page === 2 && (
<QuoteFormSecondPage
close={this.props.toggleModal}
previousPage={this.previousPage}
onSubmit={this.nextPage}
currentPage={page}
/>
)}
</div>
);
}
}
export default QuoteForm;
form first page
import React from "react";
import { Field, reduxForm } from "redux-form";
const QuoteFormFirstPage = props => {
return (
<div className="quote-form">
<form onSubmit={props.handleSubmit}>
<div className="cancel-button-container">
<button className="cancel-btn" onClick={props.close}>
x
</button>
</div>
<div className="containerForm-row">
<div className="containerForm-col">
<div className="field-container">
<Field
name={`your_details.title`}
component={selectField}
labelClass=" hidden required"
className="small"
>
<option value="Mr">Mr</option>
<option value="Ms">Ms</option>
<option value="Mrs">Mrs</option>
<option value="Dr">Dr</option>
</Field>
<Field
name="your_details.first_name"
type="text"
placeholder="Forename"
containerClass="field-group medium"
component={dgInput}
label="What is your forename?"
labelClass="title-left required"
validate={[required]}
/>
</div>
</div>
</div>
<div className="form-container-button-first">
<button type="close" onClick={props.close} className="form-back">
Cancel
</button>
<button type="submit" className="btn-quote">
Next
</button>
</div>
</form>
</div>
);
};
export default reduxForm({
form: "quote", // <------ same form name
destroyOnUnmount: false, // <------ preserve form data
forceUnregisterOnUnmount: true // <------ unregister fields on unmount
})(QuoteFormFirstPage);
form second page
import React from "react";
import { Field, reduxForm } from "redux-form";
const QuoteFormSecondPage = props => {
const { close, currentPage, handleSubmit, previousPage } = props;
return (
<div className="quote-form">
<form onSubmit={handleSubmit}>
<div className="cancel-button-container">
<button className="cancel-btn" onClick={close}>
x
</button>
</div>
<div className="form-row">
<Field
name="your_insurance_details.policy_start_date"
type="date"
placeholder={getCurrentDate()}
containerClass="field-group large"
component={dgInput}
label="When would you like your policy to start?"
labelClass="required"
validate={[required]}
/>
</div>
<div className="form-container-button">
<button type="button" className="form-back" onClick={previousPage}>
Back to property details
</button>
<button type="submit" className="btn-quote">
Next
</button>
</div>
</form>
</div>
);
};
export default reduxForm({
form: "quote", //Form name is same
destroyOnUnmount: false, // <------ preserve form data
forceUnregisterOnUnmount: true // <------ unregister fields on unmount
})(QuoteFormSecondPage);
I trimmed a lot of the form to try and make it more readable. As you can see in the form component, I tried using createRef
and scrolling to it on lick of next page. But that uses window.scrollTo
which won't work as I need to scroll to the top of the modal I'm in not the window!