quasarframework / quasar

Quasar Framework - Build high-performance VueJS user interfaces in record time
https://quasar.dev
MIT License
25.73k stars 3.49k forks source link

Modal cannot be closed #994

Closed dfmelicor closed 6 years ago

dfmelicor commented 6 years ago

Software version

Quasar: 0.14.4 OS: Windows 7 Node: 4.2.4 NPM: 2.14.12 Browsers: Chrome 61.0.3163.91 64 Bit iOS: Android: Any other software related to your bug:

What did you get as the error?

There is an un-handled case where modal cannot be closed

What were you expecting?

Modal should be closed when one of the configured events are triggered

What steps did you take, to get the error?

This can be replicated in the quasar play app. http://quasar-framework.org/quasar-play/android/index.html#/showcase/popups/modal

Steps:

  1. Open a modal
  2. Refresh the page
  3. Open a modal again

The modal opened in step 3 cannot be closed.

dmig commented 6 years ago

I cannot reproduce this in quasar play app, but often experience it in my project. Can't tell why this happens, maybe js errors.

Somehow, toggleInProgress prop left with true value and nothing happens then. Changing it to false doesn't help.

igorgo commented 6 years ago

It seems I've managed to reproduce bug in browser (chrome & ff).

  1. While on the page (the forward nav button of the browser is disabled - the last in the history) open a maximized modal.
  2. Close modal (with button on modal). After that the forward nav button becomes available.
  3. Press forward nav button - nothing happens.
  4. Open modal again.

After that modal becomes not closable.

dmig commented 6 years ago

Yes, that somehow related to history. Modal is not necessary to be maximized. I have one case that's 100% reproducible on dev server, but doesn't occur on production build. May be vue-devtool for chrome is connected to this issue

Iworb commented 6 years ago

It also could be reproduced in the dev server of the dev branch:

  1. Open (local link)[http://localhost:8080/#/components/modal]
  2. Open any modal
  3. Refresh page
  4. Open any modal again: it can't be closed now. Only page refresh helps.
TKafassis commented 6 years ago

I can reproduce something similar, dunno if it's intended.

  1. Open a modal
  2. Close it and forward nav button becomes available.
  3. Click forward nav button and then open modal again.
  4. Now modal needs 2 clicks on Close button to close and forward nav button becomes available again but can now be pressed 2 times.

And so on and so forth, seems like each time you do that you get +1 History and you need to click +1 times for a new modal to close.

jkole commented 6 years ago

@igorgo Same issue here

Interesting that, for me at least, refreshing the page (on Chrome, haven't tested ff) does not help. In other words, for me in the dev environment the following steps could be added:

  1. Refresh the page (after refresh the forward nav button will immediately be available)
  2. Open the modal
  3. The modal cannot be closed.
  4. Close the tab running the application
  5. Open a new tab with the same url
  6. Open the modal
  7. The modal can be closed as expected

I would also note that clicking the mysterious forward nav button after closing the modal has the same effect as refreshing the page (i.e. subsequent modals can't be closed).

jkole commented 6 years ago

Don't have time to dig into this further at the moment, but seems to me the issue arises where the modalId is checked in line 184 of QModal.vue. I think the flow goes like this:

  1. After opening then closing the first modal, we are left with openModelNumber == 0, but with the last entry in window.history containing a state object with modalId == 1. (This is what produces the odd forward nav button after closing the modal).
  2. Clicking the browser forward nav button points the current window history state to the one containing that state object with modalId == 1.
  3. Opening a new modal then assigns a modalId of 1 again, and a new window.history state object with modalID of 1 is pushed to the top of the stack.
  4. When we try close that modal, line 184 checks if state.modalId >= this.__modalId...and since both == 1, it returns immediately rather than closing the modal.

I imagine something similar must be happening with browser refresh rather than clicking the forward nav button.

zagreusinoz commented 6 years ago

The same thing appears to also be happening with Dialogs and ActionSheets. They cannot be closed, either with the esc key or through code.

zagreusinoz commented 6 years ago

Actually, I've noticed the doco mentions this issue:

During development open/close might not be triggered because of HMR. Best would be before updating source files to close the Modal. This way HMR will correctly do its job. In production this scenario can’t happen, so no bugs for final product.

Having said that, I'm not sure what it means we should do to fix it in development. We should close the dialog on the destroy method?

jkole commented 6 years ago

Don’t think the entire issue is due to HMR since the quasar docs desktop examples have the same behavior (though maybe not after page refresh - need to check that).

lucien-theron commented 6 years ago

@zagreusinoz have you found a development fix for this yet? Its really really annoying to constantly refresh the page to close a modal.

rstoenescu commented 6 years ago

Fixed in future v0.15 already. Closing this. Please be patient. Sorry for the inconvenience.

rettigd commented 6 years ago

I was able to work around this issue by setting the toggleInProgress to false on the nextTick. No idea if there are any side-effects or will work in all circumstances.

  this.$refs.modal.close()
  this.$nextTick(() => {
     this.$refs.modal.toggleInProgress = false
  })
Trellian commented 6 years ago

@rettigd Thanks for that, it solved my modal close problem on Chrome!

[Update] Wait... nope. Not yet. It worked once. [Update] It seems to be intermittent, but still definitely better than it was

AYapejian commented 6 years ago

Just ran into this myself, found the same workaround except it was the active property that needed deferred changing. Not sure if it's related however I saw this issue when emitting an event from within a custom component contained within the q-modal, the listener hook in the parent is doing the dialog toggling. Here is my workaround in the parent emit listener (just different prop than above)

this.$nextTick(() => {
    this.$refs.theModal.active = false;
    this.$refs.theModal.toggleInProgress = false; 
});
Cheese-Yu commented 6 years ago

I can reproduce something similar in production(Quasar: 0.14.4). Here is my work to fix this.

// in main.js
import { Platform } from 'quasar'
Platform.has.popstate = false
vhq2016 commented 6 years ago

@Cheese-Yu Thanks for that,it works!