1

When I navigate to another page by routerLink or $router.push scrollBehavior works fine. But when I try to navigate to the same page by a watcher which is triggered by changing input value of an input box situated in the center of the home page, scrollBehavior doesn't work. Rather it gets the position at bottom of the new navigated page. Even if I don't use scrollBehavior it does the same.

Now my question is how can I get to the top of the navigated 'About' page by the input value changing watcher?

HeadSearch Component:

<template>
  <div class="search">
    <input type="text" v-model="tx" />
    <p>{{ tx }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      tx: "",
    };
  },
  watch: {
    tx() {
      if (this.$route.path !== "/about") {
        this.$router.replace("/about");
      }
    },
  },
};
</script>

App.vue:

<template>
  <div id="app">
    <div id="nav">
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link>
      <br /><br />
      <head-search></head-search>
      <br /><br />
    </div>
    <router-view />
  </div>
</template>

<script>
import HeadSearch from "./components/HeadSearch.vue";
export default {
  components: {
    HeadSearch,
  },
};
</script>

Home.vue:

<template>
  <div class="home">
    <h1>This is Home page</h1>
    <br /><br /><br />
    <input class="home-input" type="text" v-model="hTx" />
  </div>
</template>

<script>
export default {
  name: "Home",
  data() {
    return {
      hTx: "",
    };
  },
  watch: {
    hTx() {
      if (this.$route.path !== "/about") {
        this.$router.push("/about");
      }
    },
  },
};
</script>

About.vue:

<template>
  <div class="about">
    <h1>This is an about page</h1>
    <br /><br /><br /><br /><br />
    <div v-for="(cont, index) in 30" :key="index">
      {{ cont }} {{ index }}
      <p>Lorem ipsum dolor sit amet.</p>
    </div>
  </div>
</template>

router.js:

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes,
  scrollBehavior(){
    return {
      x: 0,
      y: 0
    }
  }
})
Abeer
  • 155
  • 1
  • 11

2 Answers2

0

You can define a scrollTop or scrollIntoView using Javascript or jQuery in your About component methods and call the method in your About component's mounted hook.

Using Javascript or jQuery, you could define an id, class or element to scroll to when the About component is mounted.

e.g id="scrollTarget"

<template>
    <div class="about" id="scrollTarget">
        <h1>This is an about page</h1>
        <br /><br /><br /><br /><br />
        <div v-for="(cont, index) in 30" :key="index">
            {{ cont }} {{ index }}
            <p>Lorem ipsum dolor sit amet.</p>
        </div>
    </div>
</template>


<script>
export default {
    methods: {
        scrollToTop() {
            // using Javascript
            document.getElementById("scrollTo").scrollIntoView({ behavior: "smooth" })
            // OR
            // using jQuery
            $("html, body").animate({scrollTop: 600}, "slow")
        }
    },
    mounted() {
        this.scrollToTop();
    }
}
</script>
Gblend
  • 11
  • 3
0

Thanks to @Abeer in another answer, I decided to try the "delaying scroll" described here https://router.vuejs.org/guide/advanced/scroll-behavior.html#delaying-the-scroll

and it's working ! I copied it from the documentation, the code :

const router = createRouter({
  scrollBehavior(to, from, savedPosition) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve({ left: 0, top: 0, behavior: 'smooth' })
      }, 500)
    })
  },
})

Actually my problem was that when I used the syntax "return {}" it was working, but on mobile, it was not working at all. So I tried this, it works. And SMOOTH can be added !

Instead of writing 500 (ms), just write 0 if you want it to do it directly and it works fine. Finally something that works

ufa9
  • 29
  • 7