closing and submitting a form in react

I have a modal component built in react. I want to have 2 buttons. 1 that cancels the submission and another that submits (calls an axios post) to an endpoint.

I'm not sure the best way of doing this, but I thought if I : a) wrapped the modal in the form and used the onSubmit feature to submit to my end point. and b) used the onClick feature to close the button when close is clicked.

const handleSubmit = (event) => { event.preventDefault(); alert(hello); }

  return (
    <form onSubmit={handleSubmit}>
      
      <div className="modal" onClick={props.onClose}>
      <div className="background" onClick={e =>e.stopPropagation()}>
        <div>
          <h4 className="margin-bottom">Saving to Master</h4>
          <h4 className="margin-top">Confirming Your Booking</h4>
          <img src={logo} alt="logo image"/>
          <h2 class="reduce-text">Save and Submit Timeslot</h2>
          <h4>for <span class="bold underline">{test}</span></h4>
                <div><h5> {patientid}</h5>
                <img src={boxes} alt="Two Double Boxes"/>
                </div>
        </div>
      <div className="modal-footer">
        <button className="btn-close"  onClick={props.onClose}>Cancel</button>
        <button className="btn-submit" onClick={props.onClose}>Confirm</button>
      </div>
     </div>
    </div>
  
    </form>

The problem I'm getting is an old (already answered here) problem.

Getting Error "Form submission canceled because the form is not connected"

The problem is solved there. Removing the onClick allows me to submit the form, but the issue is now I'm not able to close the modal when i click on submit, which is certainly not a feasible solution.

Can someone help?

Here is the implementation of the modal:

import React, { useState,useEffect } from 'react';
import "./Modal.css";
import boxes from  "../../assets/boxes.svg";
import logo from "../../assets/logo.svg";
import axios from 'axios';

export const Modal = (props) => {
  const test = props.person.name;
  const fname = props.person.fname;
  const patientid = props.person.patientid;
  


  const url = "https://testcf-boisterous-ardvark-pc.mybluemix.net/test/addAppointment?pid=999998&date=${state.date}&starttime=${state.stime}:00&timecost=00:09:00&name=${state.fname},${state.lname}&reason=${state.type}";
  
  
  useEffect(async () => {
    try {
      const response = await axios(url);
      const data = response.data;
      console.log("testing our useeffect");
      console.log(data);
    }
    catch(error) { 
      console.log(error.response);


    }
  }, []);
  
  
  
  if (!props.show) {
    return null
  }
  
  
  
  
  const fetchData = async () => {
    //console.log("calling fetchData");
    try {
      const response = await axios(url);
      const data = response.data;
      console.log(data);
    }
    catch(error) { 
      console.log(error.response);


    }
  
  }

  const handleSubmit = (event) => {
    event.preventDefault();
    alert(`hello`);
  }
  

      return (
        <form onSubmit={handleSubmit}>
          
          <div className="modal" onClick={props.onClose}>
          <div className="background" onClick={e =>e.stopPropagation()}>
            <div>
              <h4 className="margin-bottom">Saving to Master</h4>
              <h4 className="margin-top">Confirming Your Booking</h4>
              <img src={logo} alt="logo image"/>
              <h2 class="reduce-text">Save and Submit Timeslot</h2>
              <h4>for <span class="bold underline">{test}</span></h4>
                    <div><h5> {patientid}</h5>
                    <img src={boxes} alt="Two Double Boxes"/>
                    </div>
            </div>
          <div className="modal-footer">
            <button className="btn-close"  onClick={props.onClose}>Cancel</button>
            <button className="btn-submit" onClick={props.onClose}>Confirm</button>
          </div>
         </div>
        </div>
      
        </form>
      )
    };
    
    export default Modal;

And here is how I'm calling it from the child component:

import React, { useState, useEffect } from "react";
import * as AiIcons from "react-icons/ai";
import * as FiIcon from "react-icons/fi";
import * as BiIcons from "react-icons/bi";
import "./SideBar.css";
import { Modal } from "../Modal/Modal";
//import { getDateMeta } from "@fullcalendar/react";


const SideBar = ({ activeState, setActiveState }) => {
  

  const [sidePanel1, setSidePanel1] = useState(true);
  const [sidePanel2, setSidePanel2] = useState(false);
  const [sidePanel3, setSidePanel3] = useState(false);
  
  const [items, setItems] = useState([]);
  const [finaldate, setFinaldate] = useState("");
  const [finalendDate, setFinalendDate] = useState("");
  
  const [show, setShow] = useState(false);

  const [state, setState] = useState({
    fname: "",
    lname: "",
    dob: "",
    phone: "",
    email: "",
    address: "",
    type: "",
    date: "",
    provider: "",
    message: "",
    patientid: "",
    title: "",
    gender: "",
    province: "",
    city: "",
    pcode: "",
    hcard: "",
    hcardversion: "",
    hctype: "",
    language: "",
    stime: "",
    etime: "",
  });

  useEffect(() => {
    function getAlldemographics() {
      var axios = require("axios");
      var qs = require("qs");
      var data = qs.stringify({});
      var config = {
        method: "post",
        url: "http://localhost:8080/test/getAllDemographicsnew",
        headers: {
          Cookie:
            "connect.sid=s%3AmsMTDXMN-i0Mmztsv3qCr2j-QPKZKupr.UnddXP1AzTm5x32PZSYHpGwueKRFl9kpsimaEowUWj8",
        },
        data: data,
      };

      axios(config)
        .then(function (response) {
          setItems(...items, response.data);
        })
        .catch(function (error) {
          console.log(error);
        });
    }
    getAlldemographics();
  }, []);

  function handleChange(e) {
    switch (e.target.name) {
      case "firstname":
        setState({ ...state, fname: e.target.value });
        break;
      case "lastname":
        setState({ ...state, lname: e.target.value });
        break;
      case "dob":
        setState({ ...state, dob: e.target.value });
        break;
      case "phone":
        setState({ ...state, phone: e.target.value });
        break;
      case "email":
        setState({ ...state, email: e.target.value });
        break;
      case "address":
        setState({ ...state, address: e.target.value });
        break;
      case "type":
        var id = e.target.selectedIndex;
        setState({ ...state, type: e.target[id].text });
        break;
      case "date":
        setState({ ...state, date: e.target.value });
        break;
      case "stime":
        setState({ ...state, stime: e.target.value });
        break;
      case "provider":
        setState({ ...state, provider: e.target.value });
        break;
      case "message":
        setState({ ...state, message: e.target.value });
        break;
      case "patientid":
        setState({ ...state, patientid: e.target.value });
        break;
    }
  }

  useEffect(() => {
    function finaldate() {
      if (state.date != "" && state.stime != "") {
        let finaldate = new Date(state.date + " " + state.stime);
        setFinaldate(finaldate.toISOString());
      }
    }
    finaldate();
  }, [state.stime]);

  useEffect(() => {
    function finaledate() {
      if (finaldate != "") {
        let minutesToAdd = 10;
        let currentDate = new Date(state.date + " " + state.stime);
        let finaledate = new Date(currentDate.getTime() + minutesToAdd * 59900);
        setFinalendDate(finaledate.toISOString());
      }
    }
    finaledate();
  }, [finaldate]);

  //use this method in the modal.js file to test out adding users into the database.
  //Chris Gauthier
  //October 6, 2022
  function submitALL(e) {
    e.preventDefault();

    var axios = require("axios");
    var qs = require("qs");
    
    var config = {
      method: "get",
      url: `https://testcf-boisterous-ardvark-pc.mybluemix.net/test/addAppointment?pid=999998&date=${state.date}&starttime=${state.stime}:00&timecost=00:09:00&name=${state.fname},${state.lname}&reason=${state.type}`,
      headers: {},
    };

    axios(config)
      .then(function (response) {
        console.log("layer1");
        var data2 = qs.stringify({
          patientid: state.patientid,
          notificationTitle: "Regular Appointment Testing",
          notification: state.type,
          message: state.message,
          time: state.stime,
          adate: state.date,
        });
        var config2 = {
          method: "post",
          url: "https://patientserver-nice-oribi-mp.mybluemix.net/notify/notificationAdding",
          headers: {
            Authorization: "Bearer 04347ef6920b5dc33c811a834f0138d33543ded5",
            "Content-Type": "application/x-www-form-urlencoded",
          },
          data: data2,
        };
        axios(config2).then(function (response) {
          console.log("layer2");
          var data3 = qs.stringify({
            username: state.email,
            sdate: state.date + state.stime,
          });
          var config3 = {
            method: "post",
            url: "https://patientserver-nice-oribi-mp.mybluemix.net/email/emailsending",
            headers: {
              Authorization: "Bearer 04347ef6920b5dc33c811a834f0138d33543ded5",
              "Content-Type": "application/x-www-form-urlencoded",
            },
            data: data3,
          };

          axios(config3).then(function (response) {
            console.log("layer3");
            var data4 = qs.stringify({
              lastname: state.lname,
              firstname: state.fname,
              title: state.title,
              address: state.address,
              city: state.city,
              province: state.province,
              Pcode: state.pcode,
              phone: state.phone,
              email: state.email,
              dobyear: state.dob.slice(0, 4),
              dobmonth: state.dob.slice(5, 7),
              dobday: state.dob.slice(8, 10),
              hcard: state.hcard,
              hcardversion: state.hcardversion,
              language: state.language,
              provider: state.provider,
              gender: state.gender,
              hctype: state.hctype,
            });
            var config4 = {
              method: "post",
              url: "https://patientserver-nice-oribi-mp.mybluemix.net/demographic/insertDemographic",
              headers: {
                Authorization:
                  "Bearer 04347ef6920b5dc33c811a834f0138d33543ded5",
                "Content-Type": "application/x-www-form-urlencoded",
              },
              data: data4,
            };

            axios(config4).then(function (response) {
              console.log("layer4");

              var data5 = qs.stringify({
                type: state.type,
                sdate: finaldate.slice(0, -2) + "Z",
                edate: finalendDate.slice(0, -2) + "Z",

                patientid: response.data,
                firstname: state.fname,
                lastname: state.lname,
              });
              console.log(data5);

              var config5 = {
                method: "post",
                url: "https://patientserver-nice-oribi-mp.mybluemix.net/booking/createapp",
                headers: {
                  Authorization:
                    "Bearer 04347ef6920b5dc33c811a834f0138d33543ded5",
                  "Content-Type": "application/x-www-form-urlencoded",
                },
                data: data5,
              };
              console.log(config5);

              axios(config5).then(function (response) {
                console.log("layer5");

                console.log(JSON.stringify(response.data));
                window.alert("The appointment is booked!");
              });
            });
          });
        });
      })
      .catch(function (error) {
        console.log(error);
      });
  }

  const handlePanelToggle = (sidePanel) => {
    switch (sidePanel) {
      case "sidePanel1":
        setSidePanel1(!sidePanel1);
        if (sidePanel1 === false) {
          setSidePanel2(false);
          setSidePanel3(false);
        }
        break;
      case "sidePanel2":
        setSidePanel2(!sidePanel2);
        if (sidePanel2 === false) {
          setSidePanel1(false);
          setSidePanel3(false);
        }
        break;
      case "sidePanel3":
        setSidePanel3(!sidePanel3);
        if (sidePanel3 === false) {
          setSidePanel1(false);
          setSidePanel2(false);
        }
        break;
      default:
        break;
    }
  };
  //console.log to see what format the dates are being stored in
  //Chris Gauthier September 30, 2022
  console.log(state.stime,state.date,state.fname,state.lname,state.type);
  console.log(state.patientid);
  return (
    <div className={activeState ? "side-bar active" : "side-bar"}>
      <div className="sidebar-header">
        <div className="info-panel-title">
          <p className="main-header-text-01">Lets get you set up</p>
          <p className="main-header-text-02">Appointment Booking</p>
        </div>
        <div
          className="close-button"
          onClick={() => setActiveState(!activeState)}
        >
          <AiIcons.AiOutlineClose size={14} />
        </div>
      </div>

      <div className="search-box">
        <input
          className="search-bar"
          type="text"
          placeholder="Search Patients, Practitioners,.."
        />
        <BiIcons.BiSearchAlt size={22} />
        
      </div>

      <div className="sidebar-form">
        <form method="post" className="sidebar-panel-form">
        <div className="sidebar-panel-handle">
            <span className="sidebar-panel-handle-number">01</span>
            <span className="sidebar-panel-handle-container">
              <span>Patient Details</span>
              <span
                className="sidebar-panel-handle-chevron"
                onClick={() => handlePanelToggle("sidePanel3")}
              >
                {sidePanel3 ? <FiIcon.FiChevronUp /> : <FiIcon.FiChevronDown />}
              </span>
            </span>
          </div>
          <span
            className={sidePanel3 ? "sidebar-panel active" : "sidebar-panel"}
          >
            <div>
              First Name 
              <input
                type="text"
                name="firstname"
                value={state.fname}
                onChange={handleChange}
              />
            </div>
            <br />
            <div>
              Last Name
              <input
                type="text"
                name="lastname"
                value={state.lname}
                onChange={handleChange}
              />
            </div>
            <br />
            <div>
              Patient ID*
              <input
                type="text"
                name="patientid"
                value={state.patientid}
                onChange={handleChange}
                required
              />
            </div>
            <br />
            <div>
              Date of Birth
              <input
                type="date"
                name="dob"
                value={state.dob}
                onChange={handleChange}
              />
            </div>
            <br />
            <div>
              Mobile
              <input
                type="text"
                name="phone"
                value={state.phone}
                onChange={handleChange}
              />
            </div>
            <br />
            <div>
              Email
              <input
                type="text"
                name="email"
                value={state.email}
                onChange={handleChange}
              />
            </div>
            <br />
            <div>
              Address
              <input
                type="text"
                name="address"
                value={state.address}
                onChange={handleChange}
              />
            </div>
            <br />
            <div>
              Message to Patient <br />
              <textarea
                rows="4"
                cols="50"
                name="message"
                value={state.message}
                onChange={handleChange}
              >
                Please book an appointment within next 3 weeks
              </textarea>
            </div>
            <br />
          </span>
          
          <div className="sidebar-panel-handle">
            <span className="sidebar-panel-handle-number">02</span>
            <span className="sidebar-panel-handle-container">
              <span>Booking Type</span>
              <span
                className="sidebar-panel-handle-chevron"
                onClick={() => handlePanelToggle("sidePanel2")}
              >
                {sidePanel2 ? <FiIcon.FiChevronUp /> : <FiIcon.FiChevronDown />}
              </span>
            </span>
          </div>
          <span
            className={sidePanel2 ? "sidebar-panel active" : "sidebar-panel"}
          >
            <div>
              Status*
              <select name="location">
                <option value="none">Please Select testing</option>
                <option value="1">Booked</option>
                <option value="2">Pending</option>
              </select>
            </div>
            <br />
            <div>
              Appointment Type*
              <select name="type" onChange={handleChange}>
                <option value="none">Please Select</option>
                <option value="CDM">Chronical Diseases Management</option>
                <option value="CPE">Complete Physical Exam</option>
                <option value="PAP">PAP Exam</option>
                <option value="IME">Immigration Medical Exam</option>
                <option value="MH">Mental Health</option>
                <option value="MVA">Motor Vehicle Accident (ICBC)</option>
                <option value="WCB">Worker's Compensation (WCB)</option>
                <option value="CC">Complex Care</option>
                <option value="ON">Immunization</option>
              </select>
            </div>
            <br />
            <div>
              Provider Number*
              <input
                type="text"
                name="provider"
                value={state.provider}
                onChange={handleChange}
              />
            </div>
            <br />
          </span>

          
          <div className="sidebar-panel-handle">
            <span className="sidebar-panel-handle-number">03</span>
            <span className="sidebar-panel-handle-container">
              <span>Booking Schedule</span>
              <span
                className="sidebar-panel-handle-chevron"
                onClick={() => handlePanelToggle("sidePanel1")}
              >
                {sidePanel1 ? <FiIcon.FiChevronUp /> : <FiIcon.FiChevronDown />}
              </span>
            </span>
          </div>
          <span
            className={sidePanel1 ? "sidebar-panel active" : "sidebar-panel"}
          >
            <div>
              Date*
              <input
                type="date"
                name="date"
                value={state.date}
                onChange={handleChange}
              />
            </div>
            <br />
            <div>
              Start Time*
              <input
                type="time"
                name="stime"
                value={state.stime}
                onChange={handleChange}
              />
            </div>
            <br />
            <div>
              Duration*
              <select name="duration">
                <option value="none">Please Select</option>
                <option value="15">15mins</option>
                <option value="30">30mins</option>
                <option value="45">45mins</option>
              </select>
            </div>
            <br />
            <div>
              Clinic Location*
              <select name="location">
                <option value="none">Please Select</option>
                <option value="1">Location 1</option>
                <option value="2">Location 2</option>
                <option value="3">Location 3</option>
              </select>
            </div>
            <br />
          </span>
          
          
          <span className="sidebar-submit-buttons">
            <button
              className="submit-secondary"
              onClick={() => setActiveState(!activeState)}
            >
              Close
            </button>
            <button
              className="submit-primary"
              onClick={() => setShow(true)}
            >
              Submit
            </button>
          </span>
        </form>
        <Modal 
          show={show}
          onClose={() => setShow(false)} 
          person={{ 
            name: state.fname, 
            imageId: '1bX5QH6',
            notificationTitle: 'Regular Appointment',
            time: state.stime,
            adate: state.date,
            timecost: state.timecost,
            reason: state.type,
            patientid: '999999'
            
          }}
          
          
          />    
      </div>
    </div>
  );
};

export default SideBar;

Upvotes: 0

Views: 1325

Answers (1)

Mefistofeles
Mefistofeles

Reputation: 51

Perhaps I'm misunderstanding your situation, but can you not simply close the modal with the handleSubmit function?

You didn't share your implementation of the modal, but usually a modal is open as long as a state variable, a boolean, is set to true. So, simply add a line in handleSubmit that sets said variable to false.

But that is rather obvious, so I imagine something is stopping you from doing that, what would that be?

Upvotes: 0

Related Questions