No More Posting New Topics!

If you have a question or an issue, please start a thread in our Github Discussions Forum.
This forum is closed for new threads/ topics.

Navigation

    Quasar Framework

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search

    Close dialog/bottomSheet when clicking browser back?

    Help
    2
    4
    835
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • C
      codebreaker last edited by codebreaker

      Is there a way of closing dialog or bottom sheet when a user clicks the back button (desktop and mobile browser)?

      Currently I’m doing this:

      boot file

      Vue.prototype.$a = {
          bottomSheet: function(opt) {
            const self = opt.parent;
            const sheet = BottomSheet.create(opt).onDismiss(() => {
              self.$router.history.stack[self.$router.history.index].params.$dialog = null;
            });
            self.$router.history.stack[self.$router.history.index].params.$dialog = sheet;
            return sheet;
          },
          dialog: function(opt) {
            const self = opt.parent;
            const dialog = Dialog.create(opt).onDismiss(() => {
              self.$router.history.stack[self.$router.history.index].params.$dialog = null;
            });
            self.$router.history.stack[self.$router.history.index].params.$dialog = dialog;
            return dialog;
          }
        };
      

      router file

      Router.beforeEach((to, from, next) => {
          // close any open dialog
          const dialog = get(from, "params.$dialog", false);
          if (!!dialog) {
            dialog.hide();
          }
      }
      

      But this has its downsides:

      1. It won’t work if there’s no going back (stack is 1)
      2. It will go back a route not just close the dialog
      metalsadman 1 Reply Last reply Reply Quote 0
      • metalsadman
        metalsadman @codebreaker last edited by metalsadman

        @codebreaker dialog has a hide method.

          ...
          data
             dialog: null
          ....
          methods
             someFunc
                this.dialog = this.$q.dialog...
          ...
          beforeDestroy
             ...
             this.dialog.hide()
        
        1 Reply Last reply Reply Quote 0
        • C
          codebreaker last edited by

          That is correct and I am using it to close the dialog in router file. Although, I did complicate it a lot.

          In the end, this does not solve the main two problems:

          1. It won’t work if the parent component won’t be destroyed
          2. It will go back a route not just close the dialog

          I have improved upon my previous attempt that solve these issues:

          boot file

          
          function dialogHideLogic(dialog) {
            const hideDialog = () => dialog.hide();
          
            // listen for browser back button
            window.addEventListener("popstate", hideDialog);
            // add to current state a signal so that the router change routes
            window.history.replaceState({ ...window.history.state, freeze: true }, "", window.location.href);
            // add new state so that the back button will not go to previous route
            window.history.pushState({}, "", window.location.href);
          
            return dialog.onDismiss(() => {
              window.removeEventListener("popstate", hideDialog);
              // if hide isn't called by popstate event, go back one step to remove the freeze step
              if (!get(window.history.state, "popstate", false)) window.history.back();
            });
          }
          
          export default () => {
            Vue.prototype.$a = {
              bottomSheet: function(opt) {
                return dialogHideLogic(BottomSheet.create(opt));
              },
              dialog: function(opt) {
                return dialogHideLogic(Dialog.create(opt));
              }
            };
          };
          

          router file

            // hook into browser back button
            window.addEventListener("popstate", function(event) {
              if (get(event.state, "freeze", false)) {
                // clear freeze so that we can call this route again when user uses the browser back
                window.history.replaceState({ ...window.history.state, freeze: false }, "", window.location.href);
              } else {
                Router.back();
              }
              // don't allow user to go back since we can't handle browser forward (no event)
              window.history.pushState({ popstate: true }, "", window.location.href);
            });
          

          It’s a bit of a hack, but it works.

          Note: I am using abstract routing so that why I can do this. I don’t know if it can be done in other modes.

          1 Reply Last reply Reply Quote 0
          • C
            codebreaker last edited by

            A few bug fixes later:

            boot file

            function dialogHideLogic(dialog) {
              const hideDialog = () => dialog.hide();
            
              // listen for browser back button
              window.addEventListener("popstate", hideDialog, { once: true });
              // append to current state a signal so that the vue router does not go back it's history stack
              window.history.replaceState({ ...window.history.state, freeze: true }, "", window.location.href);
              // push new state so when back button is pressed, window.history.state contains the freeze property
              window.history.pushState({ ...window.history.state, freeze: false }, "", window.location.href);
            
              return dialog.onDismiss(() => {
                // remove popstate listener
                window.removeEventListener("popstate", hideDialog);
                // push a fresh state onto history stack
                window.history.pushState({}, "", window.location.href);
              });
            }
            
            export default () => {
              Vue.prototype.$a = {
                bottomSheet: function(opt) {
                  return dialogHideLogic(BottomSheet.create(opt));
                },
                dialog: function(opt) {
                  return dialogHideLogic(Dialog.create(opt));
                }
              };
            };
            
            

            router file

              // hook into browser back button
              window.addEventListener("popstate", function(event) {
                if (!get(event.state, "freeze", false)) {
                  Router.back();
                }
                // don't allow user to go back since we can't handle browser forward (no event, not that we want to)
                window.history.pushState({ popstate: true }, "", window.location.href);
              });
            
            1 Reply Last reply Reply Quote 0
            • First post
              Last post