Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow router.replace without triggering scrollBehavior #2072

Closed
Dadibom opened this issue Feb 22, 2018 · 11 comments
Closed

Allow router.replace without triggering scrollBehavior #2072

Dadibom opened this issue Feb 22, 2018 · 11 comments

Comments

@Dadibom
Copy link

Dadibom commented Feb 22, 2018

What problem does this feature solve?

Using router.replace to update query parameters. However this triggers scrollBehavior and scrolls to the top. As far as I know, there is no way to distinguish between a push and a replace event.

What does the proposed API look like?

Here are some options:

Could be a simple boolean passed to the scrollBehavior function

scrollBehavior (toRoute, fromRoute, savedPosition, isPush) {

It could be put in the route object to be consistent with this suggestion: #1620

scrollBehavior (toRoute, fromRoute, savedPosition) {
    const isPush = toRoute.navigationType === 'push';

I could also work with the replace function accepting an additional parameter, or having a new signature, that simply updates the url and router.$route without going through guards, scrollbehavior etc. I originally just updated the state manually to circumvent this (using history.replaceState), however that caused some other sneaky bugs since vue-router didn't know about these changes.

router.replace(route, true)
// OR
router.replace(route, { noEvents/silent: true })
// OR
router.silentReplace(route)
@posva
Copy link
Member

posva commented Feb 22, 2018

I'd rather keep it in #1620
To skip guards, I prefer using meta fields, they're there for that kind of stuff
I already have some helpers in mind and docs we should provide to help advanced use cases to combine them

@posva posva closed this as completed Feb 22, 2018
@Dadibom
Copy link
Author

Dadibom commented Feb 22, 2018

hm, can i just add meta to the route and read from that?

@posva
Copy link
Member

posva commented Feb 22, 2018

yep, but it will be linked to the route, not the navigation. I don't see why you would need to skip navigation guards in a navigation, it could make things fail easily 🤔

@Dadibom
Copy link
Author

Dadibom commented Feb 22, 2018

Hm, it appears i have to define meta for every route... this feature spans multiple routes. This is what I'm attempting:

router.setQuery = function (query) {
	const route = {
		name: app.$route.name,
		params: app.$route.params,
		query,
		meta: {
			isQueryUpdate: true,
		},
	};
	router.replace(route);
};

Any ideas?

@Dadibom
Copy link
Author

Dadibom commented Feb 22, 2018

I only use the query parameters for saving data that you might want when you share a link or reload the page. For example where you are in a list

@posva
Copy link
Member

posva commented Feb 22, 2018

You can add the meta in the route definition as well so it is always applied, but yeah, you have to define where to use it 🙂

@Dadibom
Copy link
Author

Dadibom commented Feb 22, 2018

Yeah but I can't have it always apply, what I need is to be able to see the difference between a query parameter update and a navigation (push) to the page. It appears meta is only per route, and never per route object (ie per entry in router.routes, not per router.route object)

@posva
Copy link
Member

posva commented Feb 22, 2018

that's beforeRouteUpdate
Let's stop the discussion here, it's turning into a forum thread 😄

@Dadibom
Copy link
Author

Dadibom commented Feb 22, 2018

It's not the same because going from /product/1 to /product/2 through a push will still go through beforeRouteUpdate, while I want to prevent some behaviour when going from /product/1 to /product/1?image=2
Anyway thanks for the help. I'll add a +1 to the other issue and just fork in the meantime.

@Dadibom
Copy link
Author

Dadibom commented Feb 22, 2018

If anyone has similar problems and finds this issue, I solved it by not scrolling if the only thing that changed was the query/hash:

scrollBehavior (to, frm, savedPosition) {
		if (frm && to.name === frm.name && _.isEqual(to.params, frm.params)) {
			return;
		}
               // Handle scroll
}

isEqual is a lodash function that makes a deep comparison of the two objects

@peterthomassen
Copy link

Similar, but without requiring lodash:

scrollBehavior (to, from) {
    // Skip if destination full path has query parameters and differs in no other way from previous
    if (from && Object.keys(to.query).length) {
        if (to.fullPath.split('?')[0] == from.fullPath.split('?')[0]) return;
    }
    // Handle scroll
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants