Uddip Acharjee Shuvo
Uddip Acharjee Shuvo

Reputation: 183

How to close ion-select programmatically

In my ionic react app, I am using IonSelect in a form. I need to close the IonSelect dropdown programmatically inside a hardware back button event listener call when the dropdown is open. Here is the code

export const SingleSelection: React.FC = () => { 
   const [gender, setGender] = useState<string>();
   
    useEffect(() => {
     
      document.addEventListener('ionBackButton', (ev: any) => {
         ev.detail.register(1000, async (processNextHandler: any) => {
           console.log('Handler B was called!');
    
           processNextHandler();
         });
      });
      return () => {
        console.log("use effect return");
      }
   }, [])

   return (
     <IonPage>
        <IonContent>
          <IonItem>
              <IonLabel>Gender</IonLabel>
              <IonSelect value={gender} placeholder="Select One" onIonChange={e => setGender(e.detail.value)}>
                 <IonSelectOption value="female">Female</IonSelectOption>
                 <IonSelectOption value="male">Male</IonSelectOption>
               </IonSelect>
           </IonItem>
         </IonContent>
      </IonPage>   
    );
};

UPDATED: [solved]: here is my updated complete code with modal. Inside the hardware back button event listener method first the ion select is closed (if it kept open) and then the modal is closed

const ModalExample: React.FC = () => {
    const [showModal, setShowModal] = useState(false);
    const [gender, setGender] = useState<string>();

    useEffect(() => {
        document.addEventListener('ionBackButton', (ev: any) => {
            ev.detail.register(1000, async (processNextHandler: any) => {
                console.log('Handler B was called!');
                try {
                    console.log("close ion select");
                    const alert = await alertController.getTop();
                    if (alert) {
                        alert.dismiss();
                        return;
                    }
                    console.log("close modal")
                    const element = await modalController.getTop();
                    if (element) {
                        //element.dismiss();
                        setShowModal(false)
                        return;
                    }
                } catch (error) {
                    console.log(error);
                }
                processNextHandler();
            });
        });
        return () => {
            console.log("use effect return");
        }
    }, [])

    return (
        <IonContent>
            <IonModal isOpen={showModal} cssClass='my-custom-class'>
                <p>This is modal content</p>
                <IonItem>
                    <IonLabel>Gender</IonLabel>
                    <IonSelect value={gender} placeholder="Select One" onIonChange={e => setGender(e.detail.value)}>
                        <IonSelectOption value="female">Female</IonSelectOption>
                        <IonSelectOption value="male">Male</IonSelectOption>
                    </IonSelect>
                </IonItem>
                <IonButton onClick={() => setShowModal(false)}>Close Modal</IonButton>
            </IonModal>
            <IonButton onClick={() => setShowModal(true)}>Show Modal</IonButton>
        </IonContent>
    );
};

Upvotes: 3

Views: 1843

Answers (3)

Laith Bzour
Laith Bzour

Reputation: 111

in ionic 7 if you use interface popover

constructor(private popoverController: PopoverController) {}
closeSelect(){
if (this.popoverController && await this.popoverController.getTop()) {
  await this.popoverController.dismiss();
}
}

Upvotes: 0

Harshit Rastogi
Harshit Rastogi

Reputation: 2112

Although pressing the hardware back button automatically closes the IonSelect dropdown. If that doesn't work for you, here is a work-around using useRef hook:

export const SingleSelection: React.FC = () => { 
    const [gender, setGender] = useState<string>();
    const selectRef = useRef<any>(null);

    useEffect(() => {
     
      document.addEventListener('ionBackButton', (ev: any) => {
         ev.preventDefault(); // TO PREVENT THE CLOSING OF MODAL
         ev.detail.register(1000, async (processNextHandler: any) => {
           console.log('Handler B was called!');
           selectRef.current.close() // SEE HERE


           // HERE YOU CAN NOW CLOSE THE MODAL

           processNextHandler();
         });
      });
      return () => {
        console.log("use effect return");
      }
   }, [])

    return (
         ...
         <IonSelect ref={(ref: any) => selectRef.current = ref} value={gender} placeholder="Select One" onIonChange={e => setGender(e.detail.value)}>
            <IonSelectOption value="female">Female</IonSelectOption>
            <IonSelectOption value="male">Male</IonSelectOption>
         </IonSelect>
         ....
    
        );

};

Upvotes: 0

Uddip Acharjee Shuvo
Uddip Acharjee Shuvo

Reputation: 183

I have got the solution. Using alertController IonSelect dropdown can be closed programmatically,

import { alertController } from "@ionic/core";
.....

useEffect(() => {

    document.addEventListener('ionBackButton', (ev: any) => {
      ev.detail.register(1005, async (processNextHandler: any) => {
        console.log('Handler D was called!');
        const alert = await alertController.getTop();
        console.log(alert);
        if (alert) {
          alert.dismiss();
          return;
        }
        processNextHandler();
      });
    });
    return () => {
      console.log("use effect return");
    }
  }, [])

Upvotes: 3

Related Questions