3

I want to create a button that once clicked, it should scroll to the specific div.

Here is my code:

  <form @submit.prevent="onSubmit">
  <div class="form-group">
    <div class="col-md-6 employee_name">
      <label for="name">Name</label>
      <input
        type="text"
        name="name"
        class="name_input"
        placeholder="Enter your name"
        v-model="name"
        required
      />
    </div>
  </div>
  <div class="form-group">
    <div class="col-md-6 employee_email">
      <label for="email">Email</label>
      <input
        type="email"
        name="email"
        class="email_input"
        placeholder="Enter your email"
        required
      />
    </div>
  </div>
  <div class="form-group">
    <div class="col-md-6 employee_title">
      <label for="title">Title</label>
      <input
        type="text"
        name="title"
        class="title_input"
        placeholder="Enter your title"
        v-model="title"
        required
      />
    </div>
  </div>
  <div class="form-group">
    <button class="btn btn-light submit" type="submit" @submit="onSubmit>Submit</button>
  </div>
</form>

   <div id="main" class="container" v-if="infoComplete">
  <div class="col-md-12 primary_option">
    <h4 class="primary_lead">Please copy & paste signature inside the box below</h4>
    <div class="container desktop_container">
      <h5 class="email_style">Desktop</h5>
      <div class="col-md-7 desktop">
        <EmailSignature :name="name" :title="title" />
      </div>
    </div>
    <div class="container mobile_container">
      <h5 class="email_style">Mobile</h5>
      <div class="col-md-4 mobile">
        <MobileEmailSignature :name="name" :title="title" />
      </div>
    </div>
    <div class="col-md-6 secondary_option">
      <h2 class="secondary_lead">OR...</h2>
      <button class="btn btn-outline-light download_button" @click="onDownload">Download</button>
    </div>
  </div>
</div>

Here is my onClick function :

onClick() {
  let elmnt = document.getElementById("main");
  elmnt.scrollIntoView({ behavior: "smooth" });
}

And my onSubmit function:

 onSubmit() {
  console.log("Submitted");
  this.infoComplete = true;
},

Although it works, its not performing in the right sequence. So upon submit, the div will show. But if I click on the submit button again, it will scroll to that div. I need it so scroll immediately once the div is shown on display. Is there a better way of doing this? I can't pinpoint what I'm doing wrong.

2
  • where is your onSubmit in the template code? Commented Mar 9, 2020 at 14:48
  • @HankX just added it. Commented Mar 9, 2020 at 14:54

2 Answers 2

1

I've made something in the past, which can be done by creating an Directive.

const scroll = {
    bind(el, binding) {
        const handler = () => {
            setTimeout(function () {
                let element = el;

                if (typeof binding.value.el !== 'undefined') {
                    element = document.getElementById(binding.value.el)
                }

                let bodyRect = document.body.getBoundingClientRect(),
                    elementRect = element.getBoundingClientRect(),
                    offset = (elementRect.top - bodyRect.top) + (binding.value.offset || 0),
                    startingY = window.pageYOffset,
                    elementY = offset,
                    targetY,
                    diff,
                    easeInOutCubic,
                    start,
                    duration = (binding.value.speed || 500);

                // if element is close to page's bottom then window will scroll only to some position above the element...
                targetY = document.body.scrollHeight - elementY < window.innerHeight ? document.body.scrollHeight - window.innerHeight : elementY;
                diff = targetY - startingY;

                easeInOutCubic = function (t) {
                    return t < .5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1
                };

                if (!diff) return;

                // bootstrap our animation,
                //  it will get called right before next frame shall be rendered...
                window.requestAnimationFrame(function step(timestamp) {
                    if (!start) start = timestamp;

                    let time = timestamp - start, // elapsed milliseconds since start of scrolling...
                        percent = Math.min(time / duration, 1); // get percent of completion in range [0, 1]

                    // apply the easing, it can cause bad-looking
                    //  slow frames in browser performance tool, so be careful...
                    percent = easeInOutCubic(percent);

                    window.scrollTo(0, startingY + diff * percent);

                    // proceed with animation as long as we wanted it to.
                    if (time < duration) {
                        window.requestAnimationFrame(step)
                    }
                });
            }, 400);
        };

        let scrollOn = binding.value.scrollOn || null;

        if (scrollOn && scrollOn === 'init') {
            handler();
        } else {
            el.addEventListener('click', handler);
            el.$destroy = () => el.removeEventListener('click', handler);
        }
    },
    unbind: function (el) {
        if (typeof el.$destroy !== 'function') return;

        el.$destroy()
    }
};


new Vue({
  el: "#app",
  directives: {scroll: scroll}
})

Please see this jsFiddle

Sign up to request clarification or add additional context in comments.

Comments

0

you can do this by simply put the scroll code in the onSubmit function, add a setTimeout to wait for the page rendering the id="main" block

onSubmit() {
        console.log("Submitted");
        this.infoComplete = true;
        setTimeout(()=>{
          let elmnt = document.getElementById("main");
          elmnt.scrollIntoView({behavior: "smooth"});
        }, 100)
      },

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.