Closing this modal when another opens


#1

Hi, I’m trying to work out how I would close the first modal when another is opened, if you imagine a 2 step process using modals:

@Page({
    templateUrl: 'build/pages/modal1/modal1.html'
})
export class Modal1 {
    ...

    openSecondModal() {
        // We open the second modal
        let myModal = Modal.create(Modal2);
        this.nav.present(myModal);

        // We then close this modal
        this.viewCtrl.dismiss();
    }
}

Modal2 opens fine but in closing the first modal, the animations become broken for the app. I wonder if it believes all modals are closed?

Any thoughts on how I would do this? It seems like I would be better opening modal2 using a callback when modal1 closes but I’m not sure thats possible? I tried using .onDismiss but I still need to dismiss Modal1 without opening Modal2 and it also still gets the same visual bug.

Thanks for any help!


#2

First call the dismiss above the opening of the second modal, if that still broke your animations you will have to timeout the opening of second modal, unfortunately the way it works when presenting the modal is that if it is in the middle of a transition, the second modal doesn’t get presented properly, i had the same issue before with Popups, now named Alerts, and i had to timeout the close of the first one with a promise and at least 200 ms delay in calling the Promise.resolve() or Promise.reject().


#3

Hey luchillo, I gave this a go:

// Close modal
this.viewCtrl.dismiss();

setTimeout(function(){
    let myModal = Modal.create(Modal2);
    this.nav.present(myModal);
}, 1000);

But get:

EXCEPTION: TypeError: Cannot read property 'present' of undefined

Any ideas?


#4

Fat arrow functions, in this case the this context changes due to the callback function, the easy way to fix this is:

// Close modal
this.viewCtrl.dismiss();
setTimeout(() => {
  let myModal = Modal.create(Modal2);
  this.nav.present(myModal);
}, 1000);

#5

luchillo that works a treat! I’ve actually swapped it round a little so that the new modal opens and the old modal closes in the background:

let myModal = Modal.create(Modal2);
this.nav.present(myModal);

setTimeout(() => {
    // Close modal
    this.viewCtrl.dismiss();
}, 500);

But works great! Thanks.


#6

So you’re letting them stack and then close the first behind, i had the same approach but with an array of Alerts, but in mobile give me some issues with background getting full white so i had to change it, test in device to see if it will actually work as expected.


#7

Good to know, thanks!


#8

There’s actually an issue i made that relates to this but with alerts:


#10

I got error kinda like the one you had before. “browser_adapter.ts:73 EXCEPTION: TypeError: Cannot read property ‘dismiss’ of undefined”. Any ideas?


#11

@lianghua19 Could you provide some details, e.g. run ionic info and paste the output here?


#12

@iignatov Here you go:

Cordova CLI: 6.1.1
Gulp version:  CLI version 3.9.0
Gulp local:   Local version 3.9.1
Ionic Framework Version: 2.0.0-beta.6
Ionic CLI Version: 2.0.0-beta.25
Ionic App Lib Version: 2.0.0-beta.15
OS: Windows 8.1
Node Version: v0.12.7
  showSignup() {
    let modal = Modal.create(Signup);
    this.nav.present(modal);
    setTimeout(function(){
      this.viewCtrl.dismiss();
    }, 500);
  }

close() {
    this.viewCtrl.dismiss(); // This works fine
  }

Thank you.:slight_smile:


#13

@lianghua19 First of all I would recommend you to upgrade Node to the latest LTS or one of v5-releases (however not to Node v6). About the code - could you explain what exactly are you trying to achieve? Otherwise I can’t tell you if this is the right way.


#14

@iignatov What I’d like to achieve is both Signup and Login pages are modal based and they can switch each other using the link provided. Once user hit “CLOSE” button on top, both modal would be dismissed. And here is the screenshot if makes more sense.:slight_smile:


#15

This might be a really stupid question, but why are you using modals at all for this sort of thing? Why not just ordinary pages?


#16

@lianghua19 I would recommend you to rethink your workflow, even looking at the screenshots I can’t quite figure it out what the exact workflow is - are they calling each other in a closed loop?


#17

Thank you @iignatov. I changed my code to use lambda expression, and now it works. My previous post missed one image so I hope this one makes more sense.

  setTimeout(()=>{
      this.viewCtrl.dismiss();
    }, 500);


#18

Any time I feel the urge to use setTimeout I instead walk away from the computer and go play with my cat. In the end, that turns out better overall for everybody involved.


#19

Not a bad idea. I’ll try next time lol. I believe setTimeout is wrong use here as it just a workaround. I didn’t choose page instead b/c IMO my app’s pages should be on the same level which is after authorization. While login and register they are unsecured(before authorization happen) , I figured overlay might be a good choice. :slight_smile:


#20

Please, stop build a bicycle! :slight_smile:

public toAnotherModal(): void {
  this.nav.present(Modal.create(AnotherModal)).then(() => {
    this.viewCtrl.dismiss();
  });
}

#21

Ok, now it makes more sense. I would recommend you instead of opening multiple modals at once to close the first when a second is shown, just as @xr0master suggested. Using setTimeout for such things is a bad practice and indicates that you’re doing something wrong, as mentioned by @rapropos .