Reputation: 4387
I'm building a simple chatbot app with meteor. When the user sends a text message, the text is forwarded to my chatbot api. When I get the response back from the request I want to scroll to the bottom of my chat.
I found this answer on stackoverflow: How do I scroll to the bottom of a div as data is added in Meteor?
When the user sends a message the scrolling works, but as soon as I get the response back from my chatbot the scrollbar isn't at the bottom anymore. Do i have to wait till the insertion of the response is completed?
What am I missing?
User adds a new message:
Template.chat.events({
'submit .new-message'(event) {
// Prevent default browser form submit
event.preventDefault();
// Get value from form element
const target = event.target;
const text = target.text.value;
const chatId = FlowRouter.getParam("chatId");
// Insert a task into the collection
const callback = function () {
let messages = document.getElementById('messages');
setTimeout(() => {
messages.scrollTop = messages.scrollHeight;
}, 300);
}
Meteor.call('messages.insert', text, chatId,callback);
// Clear form
target.text.value = '';
}
});
And here is the part where i call my chatbot api to process the user input and respond accordingly (insert response to collection, scroll to bottom):
Meteor.methods({
'messages.insert'(text, chatId, callback) {
check(text, String);
Messages.insert({
text,
chatId,
user: true,
createdAt: new Date()
});
let options = {
sessionId: chatId
};
let request = app.textRequest(text, options);
request.on('response', Meteor.bindEnvironment(function (response, errror) {
text = response.result.fulfillment.speech + '<br><br><button class="js-yes">Ja</button><button class="js-no">Nein</nein>';
Messages.insert({
text,
chatId,
user: false,
createdAt: new Date()
});
callback();
}, function (error) {
console.log(error);
}));
request.end();
}
});
and here the html:
<template name="chat">
<ul id="messages">
{{#each messages}}
{{> message}}
{{/each}}
</ul>
<form class="new-message">
<input type="text" name="text" autocomplete="off" placeholder="Write a new message" />
</form>
</template>
with its css part:
#messages {
height: 500px;
overflow-y: scroll;
}
Upvotes: 0
Views: 1281
Reputation: 7777
I think if you move your callback function:
const callback = function () {
let messages = document.getElementById('messages');
setTimeout(() => {
messages.scrollTop = messages.scrollHeight;
}, 300);
}
To be called by the helper method that runs when the collection is updated, and then you can dispense with the call you make after the insert, because it will run whoever updates the collection. You might want to give it a better name than "callback" while you are doing it
Upvotes: 1