Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

VueJS Components using scrollIntoView()

I'm trying to use a Jump-To-Div kind of feature using document.getElementById().scrollIntoView() in a vue component.

The feature works fine if I call the function when I'm in the component. But if I try to call the function from the parent component using a ref, the element is not scrolled into view.

The parent component is a page and the children components are tabs in the page.

This is the child Vue Component in the parent component :-

<el-tab-pane label="Solution Details" name="Solution Details" v-loading="loading">
                <solution-details
                    :formData="response"
                    ref="solutionDetails"
                    @done="$emit('done')">
                </solution-details>
            </el-tab-pane>

So there is a SolutionDetails.Vue child component which has a ref="solutionDetails". I am calling this method in the parent component using the ref for the child component:

handleClick(command) {
            this.activeTab = 'Solution Details';
            this.$refs.solutionDetails.showCurrent(command);
        },

There is a showCurrent function in the child component which should get executed for a argument "command". This is that function in the child component.

methods: {
        showCurrent(index) {
            document.getElementById(index).scrollIntoView();
        },

As you can see, showCurrent should get the element in the page and should scroll into view. If SolutionDetails.vue is the active tab, then the corresponding element is being scrolled into view perfectly fine. But I'm executing the parent function from some other tab, then the this.activeTab = 'Solution Details'; is executing, ie. the active tab is changing to SolutionDetails.vue but the requested element is not scrolled into view.

What should I do to scroll to a element when some other tab is the activeTab?

like image 342
benedemon Avatar asked Jun 17 '17 16:06

benedemon


3 Answers

The problem is that scrollIntoView is called before the tab is rendered on the page because renders are asynchronous. Essentially, when you call

this.activeTab = 'Solution Details';

Vue does not immediately render the page, it just queues a render. However immediately after that you tell Vue to look for the rendered element and scroll to it. It's not there yet.

I think my first stab at solving this would be to use $nextTick.

this.$nextTick(() => this.$refs.solutionDetails.showCurrent(command))

That should wait for the render that needs to happen to occur before you attempt to scroll into view.

like image 86
Bert Avatar answered Nov 19 '22 02:11

Bert


Actually you have to reference the element in the component. Something like this for example:

this.$refs.[ref name here].$el.scrollIntoView({ behavior: 'smooth' });
like image 27
Steven Benjamin Avatar answered Nov 19 '22 04:11

Steven Benjamin


1: Give the element you want a ref name. Inside the function on the parent element , it's better to try to console.log(this.$refs.[ref_name]) to check which part will have the effect. It is not always the parent element. Really depends on your CSS structure. When submit the form and get error message, then the view go to the part you want.

if(this.errorMessage) {
    this.$refs.[ref_name].scrollIntoView();
}

2: For Vue.JS Multi Steps Form It is normal to use step for process like signup. What we have now is the view will stay the same as the first step. For example, if step one form is quite long with scrolling then go to step two the view will stay at the bottom. What we can do here to keep the view on the top: Give the top element a ref name like ref="top". In all the steps submit functions, just add this to keep the next page on the top:

this.$refs.top.scrollIntoView();
like image 3
Daisy Avatar answered Nov 19 '22 02:11

Daisy