Execute code after view update in vue.js - vue.js

I want to perform a task (scrolling to bottom, since new elements where added) after a view has been updated by vue.
Here is my code:
export default {
mounted() {
this.connect();
},
connection: null,
methods: {
connect: function () {
...
},
onMessage: function (msg) {
this.messages.push(msg);
this.scrollDown();
return true;
},
scrollDown: function () {
$("html, body").animate({
'scrollTop': $(this).offset().top
}, 100);
}
As you can see, the this.scrollDown(); is invoked after this.messages.push(msg);, so since the view is not updated immediately the scroll is not well performed.
How is it supposed to be made?

Try waiting for the DOM to be updated using:
this.$nextTick(function () {
this.scrollDown();
});

Related

Redo the api call everytime I change the data value on VueJs

I'm trying to update a request of an axios.get
I have a method that adds 1 to the param data (the default value is 1), but even thought I'm updating the param value, the page won't change the content because it's not updating the get requisition
I know there something similar in react with componentDidUpdate method
Here's my code
Api request
async created() {
const {
data: {
data: { items, pagination },
},
} = await this.$axios.get(`/faq?page=${this.param}`)
},
Method:
methods: {
next() {
this.param = this.param + 1
},
},
So is it possible to redo the create() everytime i use the method next?
created() hook is called only once during a lifecycle, you can use watcher instead in order to listen to variable changes
watch: {
param: {
immediate: true,
handler(newVal, oldVal) {
if (newVal !== oldVal) {
await this.$axios.get(`/faq?page=${newVal}`)
}
}
}
}
For more info, please take a look at: https://v2.vuejs.org/v2/guide/computed.html#Computed-vs-Watched-Property

How to format fetched data in Vue.js and update the vue instance

I am trying to fetch a json from an api and then format it for later use in google-charts.
I fetch the json-file using vue-resource and it works normally, the problem happens when I try to format the received data (update other arrays in data() with the fetched data), the vue component is not updated (the function is in created() ).
When I use a v-on:click the formating is done correctly but when I call the function from created it doesn't work.
I tried Vue.set and the splice method, both didn't work.
Goal
Getting the formatData() method to run and update the idArray.
export default {
name: 'app',
components: {
FirstCharts
},
data() {
return {
apiData: undefined,
idArray: []
}
},
created() {
this.loadApi();
},
methods: {
loadApi: function () {
this.$http.get('https://api.myjson.com/######').then(this.successCallback, this.errorCallback);
},
successCallback: function (response) {
this.apiData = response.data;
},
errorCallback: function (response) {
this.apiData = response.data;
this.formatData();
this.$forceUpdate();
},
formatData: function () {
for (var i = 0; i < this.apiData.resourcePlan.length; i++) {
this.idArray.splice(i, 1, parseInt(this.apiData.resourcePlan[i].resourceID));
Vue.set(this.idArray, i, parseInt(this.apiData.resourcePlan[i].resourceID));
}
}
it looks like you are calling formatData in the error callback, not the success callback. see if moving it into success works.

Vuejs 'beforeunload' event not triggered as expected

I have registered 'beforeunload' event on created hook of the component used by routes of vue router.
I want to call this event handler in order to remove user on browser tab close or browser tab refresh or browser close.
On ComponentA
created (){
window.addEventListener('beforeunload', () => {
this.removeUser()
return null
})
}
Smilarly on ComponentB
created (){
window.addEventListener('beforeunload', () => {
this.removeUser()
return null
})
}
And my router.js
{
path: '/staff/call/:session_key',
name: 'Staff Call',
component: ComponentA,
meta: {auth: true}
},
{
path: '/consumer/call/:session_key',
name: 'Consumer Call',
component: ComponentB
},
Here 'beforeunload' event handler is triggered randomly. That is sometimes it get triggered and sometimes not. I count find any pattern when it is triggered and when it is not.
What am I missing here?
Edit
I'd guess the most likely culprit then is exactly what #PatrickSteele said. From MDN:
Note: To combat unwanted pop-ups, some browsers don't display prompts
created in beforeunload event handlers unless the page has been
interacted with; some don't display them at all. For a list of
specific browsers, see the Browser_compatibility section.
I'd say it's likely you're seeing inconsistent behavior because you are sometimes not interacting with the page.
This may be a syntax error. created should be a method
created () {
window.addEventListener('beforeunload', this.removeUser)
},
methods: {
removeUser () {
//remove user here
}
}
A fiddle working: https://jsfiddle.net/e6m6t4kd/3/
It's work for me. while do something before reload or close in
vue.js
created() {
window.onbeforeunload = function(){
return "handle your events or msgs here";
}
}
I had to do some fiddling on the above examples, I believe this is the most robust solution:
let app1 = new Vue({
delimiters: ['[[', ']]'],
el: '#app',
data: {
dirty_form: true,
},
created () {
console.log('created')
window.addEventListener('beforeunload', this.confirm_leaving)
},
methods: {
confirm_leaving (evt) {
if (this.dirty_form) {
const unsaved_changes_warning = "You have unsaved changes. Are you sure you wish to leave?";
evt.returnValue = unsaved_changes_warning;
return unsaved_changes_warning;
};
};
},
});
If you want detect page refresh/change in Vue whenever you press F5 or Ctrl + R, You may need to use Navigation Timing API.
The PerformanceNavigation.type, will tell you how the page was accessed.
created() {
// does the browser support the Navigation Timing API?
if (window.performance) {
console.info("window.performance is supported");
}
// do something based on the navigation type...
if(performance.navigation.type === 1) {
console.info("TYPE_RELOAD");
this.removeUser();
}
}
Not sure why none of the above were fully working for me in vue 3 composition api. Abdullah's answer partially works but he left out how to remove the listener.
setup() {
const doSomething = (e) => {
// do stuff here
return true
}
onBeforeMount(() => {
window.onbeforeunload = handleLeaveWithoutSaving
})
onUnmounted(() => {
window.onbeforeunload = null
})
}

vuejs2: how can i destroy a watcher?

How can i destroy this watcher? I need it only one time in my child component, when my async data has loaded from the parent component.
export default {
...
watch: {
data: function(){
this.sortBy();
},
},
...
}
gregor ;)
If you construct a watcher dynamically by calling vm.$watch function, it returns a function that may be called at a later point in time to disable (remove) that particular watcher.
Don't put the watcher statically in the component, as in your code, but do something like:
created() {
var unwatch = this.$watch(....)
// now the watcher is watching and you can disable it
// by calling unwatch() somewhere else;
// you can store the unwatch function to a variable in the data
// or whatever suits you best
}
More thorough explanation may be found from here: https://codingexplained.com/coding/front-end/vue-js/adding-removing-watchers-dynamically
Here is an example:
<script>
export default {
data() {
return {
employee: {
teams: []
},
employeeTeamsWatcher: null,
};
},
created() {
this.employeeTeamsWatcher = this.$watch('employee.teams', (newVal, oldVal) => {
this.setActiveTeamTabName();
});
},
methods: {
setActiveTeamTabName() {
if (this.employee.teams.length) {
// once you got your desired condition satisfied then unwatch by calling:
this.employeeTeamsWatcher();
}
},
},
};
</script>
If you are using vue2 using the composition-api plugin or vue3, you can use WatchStopHandle which is returned by watch e.g.:
const x = ref(0);
setInterval(() => {
x.value++;
}, 1000);
const unwatch = watch(
() => x.value,
() => {
console.log(x.value);
x.value++;
// stop watch:
if (x.value > 3) unwatch();
}
);
For this kind of stuff, you can investigate the type declaration of the API, which is very helpful, just hover the mouse on it, and it will show you a hint about what you can do:

vuejs 2 nextTick() return

I'm trying to return some data using nextTick() in vuejs 2 as following
getProperty() {
this.$nextTick(function() {
return 'hello';
});
}
It doesn't work. Any clue?
this.$nextTick this function does not return anything; it just executes your callback after refreshing all new data.
so if you want to set some flag or data you can use modal/variable for that.
new Vue({
data: {
msg: 'hello'
},
methods: {
someTask: function () {
this.msg = 'hello next tick';
this.$nextTick(function() {
this.printVar();
});
},
printVar: function() {
// here this variable will be changed to latest value
// or call another function where this value is used
// this.anotherFunction();
console.log(this.msg);
}
},
ready: function () {
this.someTask();
}
});
or just let us know what you want to do with that so we can provide you better answer.