Search code examples
javascriptvue.jseventsscrollalpine.js

scroll to top button not working. Cannot read properties of undefined (reading 'scrollTo')


I'm trying to do a scroll to top button with $refs.topScroll.scrollTo. When displaying the search list and scrolling to the bottom, cllicking to top button the view isn't moved to top of the block, saying Cannot read properties of undefined (reading 'scrollTo') error. I'm trying to do it with Alpinejs, but I think the same works for Vuejs.

https://codesandbox.io/s/html-template-forked-z453xs?file=/index.html

<!-- <!DOCTYPE html> -->
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="normalize.css" />
    <link rel="stylesheet" href="styles.css" />
    <script
      defer
      src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js"
    ></script>
    <!-- <script type="”module”" src="./script.js"></script> -->
    <title>Vesna</title>
  </head>

  <body>
    <section class="content">
      <div class="container">
        <div
          class="content__top"
          x-data="{
          search: ''
        }"
        >
          <input
          />
          <button
            class="input__btn font--m1"
            @click="$store.products.getAllProducts(search)"
          >
            Search
          </button>
        </div>
        <div
          x-ref="topScroll"
        >
          <div x-data>
            <template x-for="item in $store.products.people" :key="item.id">
              <div class="content__mid">
                <p class="content__mid-item" x-text="item.name"></p>
                <p class="content__mid-item" x-text="item.email"></p>
              </div>
            </template>
          </div>
        </div>
        <div class="content__bottom">
          <div class="content__bottom-left">
            <div
              class="btn--content"
              x-data
              @click="$refs.topScroll.scrollTo({top: 0, behavior: 'smooth'})"
            >
              <span class="font--m1 text-underline">to top</span>
            </div>
           
        </div>
      </div>
    </section>

    <script>
      document.addEventListener("alpine:init", () => {
        Alpine.store("products", {
          people: [],
          showTableHeader: false,
          index: 0,
          step: 5,

          getAllProducts(searchInput) {
            fetch("https://jsonplaceholder.typicode.com/users")
              .then((response) => response.json())
              .then((res) => {
                this.people = res;
                this.showTableHeader = true;
                console.log(this.showTableHeader);
              });
          }
        });
      });
    </script>
  </body>
</html>


Solution

  • You've used $refs.topScroll but window.scrollTo is better option.

    <div class="btn--content" x-data @click="window.scrollTo({top: 0, behavior: 'smooth'})">
       <span class="font--m1 text-underline">to top</span>
    </div>Ï