Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
129
rated 0 times [  130] [ 1]  / answers: 1 / hits: 47485  / 7 Years ago, tue, may 30, 2017, 12:00:00

I am trying to create a chat style form. So a user inputs their data and then uses the button within my template with the class of continue-btn.



As you can see when the continue-btn is pressed it uses the nextStep method which adds 1 to the counter data property.



Within my template I then use v-if=counter >= 1 to display the next section of the chat dialog and input field.



I am then trying to use scrollTop to automatically scroll the page to the new section with the id of #conversation__tram-1. I originally tried running this block of code just after the counter had been given a value of 1:



const container = this.$el.querySelector(#conversation__tram- + this.counter);
container.scrollTop = container.scrollHeight;


This didn't work though because I'm guessing the #conversation__tram-1 element hadn't been added to the DOM yet.



So for the sake of testing I tried wrapping it in a timeout function:



  setTimeout(function(){
const container = this.$el.querySelector(#conversation__tram- + this.counter);
container.scrollTop = container.scrollHeight;
}, 3000);


However I am left with this error when trying this:



Uncaught TypeError: Cannot read property 'querySelector' of undefined


Here is my whole single vue file:



<template>

<div id=conversation-app>
<!-- <div v-for=item in items>
{{ item.text }}
</div> -->
<div class=conversation__track>
<div id=conversation__tram-0>
<div class=conversation__item agent>
<img src=/assets/cdn.annuityadvicecentre.dev/images/theme-f/michael-chat-agent.jpg class=conversation__item-prof-img alt=Michael Chat Agent />
<div class=conversation__item-content>
<p>
Hello my name is {{ agent }}, we'll compare the whole annuity market to bring you back the best annuity rates from the top providers for you. Let's get started, what's your name?
</p>
</div>
</div>
<div class=conversation__item customer id=title-fullname>
<div class=conversation__item-content>
<p>
Hi {{ agent }}, my name is...
</p>
<div class=row>
<div class=col-4>
<select id=title class=field-title name=payload[title]><option value=mr>Mr</option><option value=mrs>Mrs</option><option value=miss>Miss</option><option value=ms>Ms</option></select>
</div>
<div class=col-8>
<input v-model=customerName id=full_name class=field-full_name name=payload[full_name] type=text>
</div>
</div>
</div>
</div>
</div>
<transition name=fade>
<div id=conversation__tram-1 v-if=counter >= 1>
<div class=conversation__item agent>
<img src=/assets/cdn.annuityadvicecentre.dev/images/theme-f/michael-chat-agent.jpg class=conversation__item-prof-img alt=Michael Chat Agent />
<div class=conversation__item-content>
<p>
Thanks {{ firstName }}, nice to meet you. To process your instant quote please can I have your Pension Value?
</p>
</div>
</div>
<div class=conversation__item customer>
<div class=conversation__item-content>
<p>
Sure, my pension value is...
</p>
<input id=pension_value class=field-pension_value placeholder=£ pattern=d* name=payload[pension_value] type=number>
<div class=error-wrap error_pension_value is-hidden data-format=<div class=&quot;error-text&quot;>:message</div>></div>
</div>
</div>
</div>
</transition>
<div id=conversation__buttons>
<button type=button class=continue-btn
v-on:click=nextStep
>Continue&nbsp;<i class=fa fa-chevron-right aria-hidden=true></i></button>
</div>
</div>
</div>
</template>

<script>
export default {
name: 'conversation-app',
data () {
return {
agent: 'Brick',
counter: 0,
customerName: '',
}
},
methods: {
nextStep: function() {
this.counter += 1;
setTimeout(function(){
const container = this.$el.querySelector(#conversation__tram- + this.counter);
container.scrollTop = container.scrollHeight;
}, 3000);

},
},
computed: {
firstName() {
return this.customerName.split(' ')[0];
}
}
}
</script>


Any idea why this isn't working? Thanks.


More From » vue.js

 Answers
20

This is a good time to use arrow functions, as they preserve the context of this.



nextStep: function() {
this.counter += 1;
setTimeout(() => {
const container = this.$el.querySelector(#conversation__tram- + this.counter);
container.scrollTop = container.scrollHeight;
}, 3000);


Altenatively, instead of the timeout you can use Vue.nextTick which is a more technically-correct way of doing this.



nextStep: function () {
this.counter += 1
this.$nextTick(() => { ... })

[#57624] Friday, May 26, 2017, 7 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
mckinleykeyshawnb

Total Points: 281
Total Questions: 99
Total Answers: 111

Location: Saudi Arabia
Member since Sat, Aug 20, 2022
2 Years ago
;