Get data From IonModal In Ionic React

Viewed 418

Good afternoon Devs.

My Problem:

I need to read data returned from an ion modal in the parent page. Specifically, I Want to await a user entering some text on an ion modal and when the user clicks ok, the page can read and use the entered data returned from the modal. I need to await as I need the data from the modal before i can proceed with processing. As a note, I am using TypeScript on an ionic react project.

Things I've tried: I looked through various sites and it is suggested that I can get data by listening to the onDidDismiss event. I have tried this but I get no data (I have also tried waiting for a promise to resolve and look for data in the .then ) It seems the documentation says that the dismiss() function for useIonModal allows data to be passed as a prop, but the code will not allow args to the dismiss function.

I have some code snipptes below to illustrate my code so far

 const ModalBody = ()=>{
        const [text,setText] = useState<string>("") 
        const Dismiss=(data:{isText:boolean, note:string})=>{handleDismiss(data)} 
            return(
            <div>
                <div className={"ion-text-center ion-padding"}>
                    <IonTitle>Enter Your Data Here</IonTitle>
                    <IonTextarea 
                        rows={10} 
                        inputMode="text" 
                        spellCheck={true} 
                        maxlength={2000} 
                        className={"ReasonBox"} 
                        onIonChange={(e)=>setText(e.detail.value!)}
                         />
                </div>
                <div className={"modalButton"}>
                    <IonButton expand={"block"} color="logoText" onClick={()=>Dismiss({isText:true,note:text})}>Save</IonButton>
                    <IonButton color="logoText" expand="block" onClick={()=>handleDismiss({isText:false,note:""})}>Cancel</IonButton>
                </div>
            </div>
            )
    }

const [present, dismiss] = useIonModal(ModalBody); // Where ModalBody is my component

const noteModal =():Promise<boolean>=>{
    return new Promise((resolve, reject)=>{
        const conf = present({
            cssClass: 'my-css',
            onDidDismiss: async (e) =>{
                console.log("modal test" , e); //get all event stuff, but no data 
                resolve(true)  
            }
        })   
    })
}

const handleDismiss=(data:{isText:boolean, note:string})=>{
            console.log(data.note, data.isText); //i have got data here but how to send it to my noteModal function?
            dismiss();  
        })
    }

What am I missing here? I assume I want to set some data to the modal so I can access it in the onDidDismiss event, or is there a better way? any help is greatly appreciated

1 Answers

this is the pattern I use... provide a callback function for when you are closing the modal and pass the data back through that function

Modal is opened by setting the state variable modalOpen using setModalOpen(true)

// code in the template
<IonModal isOpen={modalOpen}>
  <AddStudentModal
    onCloseModal={handleModalClose}
    initialData={modalData}
  />
</IonModal>

The code from the modal, data is passed in, and the callback function onCloseModal

const AddStudentModal = ({ onCloseModal, initialData }) => {
  const [section, setSection] = useState();
  const [name, setName] = useState();

  useEffect(() => {
    setSection(initialData?.section);
    setName(initialData?.name);
  }, []);


  // if user cancels, close and pass back null
  const handleCancel = () => {
    onCloseModal(null);
  };

  // if user has data, cloe and pass back the appropriate data
  const handleSave = () => {
    onCloseModal({
      name,
      section,
      id: initialData?.id
    });
  };

  return (
    <IonPage>
      <IonHeader>
        <IonToolbar />
      </IonHeader>
      <IonContent className="ion-padding">
        <strong>Ready to create an app?</strong>
        <IonItem>
          <IonLabel>Name</IonLabel>
          <IonInput value={name} onIonChange={e => setName(e.detail.value)} />
        </IonItem>

        <IonItem>
          <IonLabel>Section</IonLabel>
          <IonSelect
            value={section}
            placeholder="Select One"
            onIonChange={e => setSection(e.detail.value)}
          >
            <IonSelectOption value="advanced">Advanced</IonSelectOption>
            <IonSelectOption value="beginners">Beginners</IonSelectOption>
          </IonSelect>
        </IonItem>
        <div style={{ paddingTop: 10 }}>
          <IonButton onClick={handleSave}>SAVE STUDENT</IonButton>
          <IonButton onClick={handleCancel} color="danger">
            CANCEL
          </IonButton>
        </div>
      </IonContent>
    </IonPage>
  );
};

The code in the parent component to handle the closing of the modal, set response to null when the user selects cancel

  const handleModalClose = response => {
    setModalOpen(false);
    if (response) {
      console.log(response);
      if (response.id) {
        updateStudent({
          name: response.name,
          section: response.section,
          id: response.id
        });
      } else {
        addStudent({ name: response.name, section: response.section });
      }
    }
    modalData && setModalData(null);
  };

Working Stackblitz with complete example

Video Tutorial

Related