Scroll behaviour VueJS not working properly

I am trying to make a scrolling to anchor by means of scrollBehaviour in VueJS.

Generally, I change current router with the following way :

this.$router.push({path : 'componentName', name: 'componentName', hash: "#" + this.jumpToSearchField})

My VueRouter is defined as :

const router = new VueRouter({
  routes: routes,
  base: '/base/',
  mode: 'history',
  scrollBehavior: function(to, from, savedPosition) {
    let position = {}
    if (to.hash) {
      position = {
        selector : to.hash
      };
    } else {
      position = {x : 0 , y : 0}
    }
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve(position)
      }, 10)
    })
  }
});

My routes :

[
  {
    path: '/settings/:settingsId',
    component: Settings,
    children: [
      {
        path: '',
        name: 'general',
        components: {
          default: General,
          summary: Summary
        }
      },
      {
        path: 'tab1',
        name: 'tab1',
        components: {
          default: tab1,
          summary: Summary
        }
      },
      {
        path: 'tab2',
        name: 'tab2',
        components: {
          default: tab2,
          summary: Summary
        }
      },
      {
        path: 'tab3',
        name: 'tab3',
        components: {
          default: tab3,
          summary: Summary
        }
      }
    ]
  },
  {
    path: '/*',
    component: Invalid
  }
];

Let's say I am on tab1 component and I would like to jump to anchor 'test' on tab3 component

After router.push() I see that scrollBehavior is trigged and component switches from tab1 to tab3 as well as URL is changed (e.g. http://localhost:8080/tab1 to http://localhost:8080/tab3#test) but windows location is not placed where anchor is but just on the top of the window.

And of course, I have textarea with id="test" on tab3 component

What can be wrong ?


Solution 1:

Use {left: 0, top: 0} instead of {x: 0, y: 0} and it will work.

I think it's a mistake in Vue documentation because if you log savedPosition on the console, you'll see {left: 0, top: 0} and when you change {x: 0, y: 0} like that everything will work perfectly.

Solution 2:

I couldn't get any of the other solutions around this working, and it was really frustrating.

What ended up working for me was the below:

const router = new Router({
    mode: 'history',
    routes: [...],
    scrollBehavior() {
        document.getElementById('app').scrollIntoView();
    }
})

I mount my VueJs app to #app so i can be certain it is present its available for selection.

Solution 3:

this works for me in Vue 3 :

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes,
  scrollBehavior(to, from, SavedPosition) {
    if (to.hash) {
      const el = window.location.href.split("#")[1];
      if (el.length) {
        document.getElementById(el).scrollIntoView({ behavior: "smooth" });
      }
    } else if (SavedPosition) {
      return SavedPosition;
    } else {
      document.getElementById("app").scrollIntoView({ behavior: "smooth" });
    }
  },
});