Green
Green

Reputation: 386

Vue router history

I'm working with Vue 2 and I have some issues with the history when navigating back.

I have the following:

/page-1/{id}
        |
        v
/page-1/{id}/overview
        |
        v
user clicks on edit
        |
        v
/page-1/{id}/overview/edit
        |
        v
user navigate pages, example /page-1/{id}/details/edit
        |
        v
user confirms changes
        |
        v
/page-1/{id}

When the user confirm the changes it will be redirected back to /page-1/{id}. However, if the user then clicks the back button it will be redirected to /page-1/{id}/details/edit, which is the previous route. Instead I would like to be able to go back to the route that was visited before entering the edit mode: /page-1/{id}/overview.

/page-1/{id}
        |
        v
/page-1/{id}/overview <-------------------------------------+
        |                                                   |
        v                                                   |
user clicks on edit                                         |
        |                                                   |
        v                                                   |
/page-1/{id}/overview/edit <-----------------------------+  |
 |      |                                                |  |
 |      v                                                |  |
 |  user navigate pages, ex: /page-1/{id}/details/edit   |  |
 |      |                                                |  |
 |      v                                                |  |
 |  back button -----------------------------------------+  |
 V                                                          |
user confirms changes                                       |
        |                                                   |
        v                                                   |
/page-1/{id}                                                |
        |                                                   |      
        v                                                   |
     back button -------------------------------------------+

It looks like I have to erase the "edit" history when the changes are confirmed. Is there a way to do this in vue? Or kind of create a separate history for the edit pages...

Thank you

UPDATE

I found an npm package that looks like is doing what Im looking for

https://www.npmjs.com/package/vue-router-back-button

However, looks like I need to hard reload the page at each page visit to make it work....

UPDATE

Ok, found a solution, I keep different Histories depending on in which state Im in:

  1. normal state (view pages) -> use history
  2. edit state -> use editHistory

When we move out from the edit state, the edit history is erased and we return to the regular history. This can be further improved with sub hisotries if needed.

/page-1/{id} -> /page-1/{id}/overview                   History[
                                                            /page-1/{id},
                                                            /page-1/{id}/overview
                                                        ]

/page-1/{id}/overview -> /page-1/{id}/overview/edit     EditHistory[
                                                           /page-1/{id}/overview/edit
                                                        ] (switch to edit history)

/page-1/{id}/overview/edit -> /page-1/{id}/details/edit   EditHistory[
                                                           /page-1/{id}/overview,
                                                           /page-1/{id}/overview/edit,                                      /page-1/{id}/details/edit
                                                        ]

/page-1/{id}/overview/edit <- /page-1/{id}/details/edit   EditHistory[
                                                           /page-1/{id}/overview/edit
                                                        ]

User save                                               EditHistory[
                                                        ] (switch to history)

/page-1/{id}/overview/                                  User is now at the most recent entry in the history

If the user saved in the  /page-1/{id}/overview/details/edit page, then the edit history is erased and the url /page-1/{id}/overview/details/ will be pushed in the History:

History[
    /page-1/{id},
    /page-1/{id}/overview,
    /page-1/{id}/details,
]

If now the user clicks back it will be sent back to the overview :)

Btw, seems to work nice, but for some reason, sometimes the popState event is not catched by the listener (probably not even thrown by the browser?) This results in having to click back twice. Are there situation where the popstate event is not raised even if the user clicks the back button?

Upvotes: 1

Views: 4190

Answers (1)

Antonio Milicic
Antonio Milicic

Reputation: 31

If you want you can avoid this issue, instead of using router.push (which is default for vue router), you can use router.replace, which will replace current URL in history mode with new one. Really useful for blocking user from re-entering the page you don't want them to enter again via history.

Use router.replace('<wanted-route>') instead of router.push('<wanted-route>')

How it would be applicable in your case (thank you for the quick route diagram, really useful for explanations):

router.push(`/page-1/${id}`)
        |
        v
router.push(`/page-1/${id}/overview`) <--------------------+
        |                                                   |
        v                                                   |
user clicks on edit                                         |
        |                                                   |
        v                                                   |
router.push(`/page-1/${id}/overview/edit`) <--------------+ |
 |      |                                                |  |
 |      v                                                |  |
 |  user navigate pages, ex: /page-1/{id}/details/edit   |  |
 |      |                                                |  |
 |      v                                                |  |
 |  back button -----------------------------------------+  |
 V                                                          |
user confirms changes                                       |
        |                                                   |
        v                                                   |
router.replace(`/page-1/${id}`)                             |                   
        |                                                   |      
        v                                                   |
     back button -------------------------------------------+

This will replace last history object with new path object. Example of history objects by URL-s.

Original:

/page-1/{id} -> /page-1/{id}/overview -> /page-1/{id}/overview/edit -> /page-1/{id}

Router replace:

/page-1/{id} -> /page-1/{id}/overview -> /page-1/{id}

More info: https://router.vuejs.org/guide/essentials/navigation.html#replace-current-location

Upvotes: 1

Related Questions