0

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!

Neil
  • 95
  • 1
  • 16

1 Answers1

1

Could you provide a stackblitz or anything else so we could implement something?

I would suggest to use an anchor and scroll to the element as described in How to scroll HTML page to given anchor?

Hellmy
  • 76
  • 6