VueJS Watch not working - vuejs2

I am trying to watch a particular property of a component. The property is an array which gets's updated every time a checkbox is selected.
https://github.com/ratiw/vuetable-2/wiki/Special-Fields#-__checkbox
This is the code that I am trying with is like this
watch: {
selectedTo: function(val){
console.log(val);
}
},
Neither did the below code work
watch : {
selectedTo: {
handler(val, oldVal)
{
console.log('Item Changed');
},
deep: true
}
},
Vue console: http://prntscr.com/gb1gew

You can watch $refs.<name>.<data> but not $refs.<name> itself.
Reference on this: https://jsfiddle.net/kenberkeley/9pn1uqam/
Still, though I don't know much about how your code works, try
this.$watch(() => this.$refs.vuetable.selectedTo, (val) => {...})

Related

Vue component replacement on load and scroll - how to make it work?

I inherited app written in VUE and mostly I found my way through the app to make designed changes, but I have problem with the below code.
What I want to achieve is: on scrolling the new tiles are being loaded and they have elements which should be replaced as in vueComponent function.
It works as designed on document load, but new elements are not being replaced. I haven't copied all the code, but you can get an idea. Please see my comments below to know what is working and what is not.
$(document, context).once('vue__comparison_toggle_add').each(() => {
Drupal.behaviors.vue__comparison_toggle.vueComponent(); //this works perfectly
});
$(window).on("scroll", function() {
Drupal.behaviors.vue__comparison_toggle.vueComponent(); //this doesn't although the function is entered
});
},
vueComponent: function () {
Vue.component('comparison-training-toggle', {
template: this.template,
props: ['trainingId', 'icon', 'init-comparison'],
data() {
return {
inComparison: false,
}
},
computed: {
toggleText() {
return this.inComparison ? Drupal.t('Usuń z porównania') : Drupal.t('Dodaj do porównania')
}
},
methods: {
toggle() {
...

Im watching vuetify width change but reload is not keeping the width

hello. I have one question, my app is watching for the this.$vuetify.breakpoint.width property and updating a value that is used in a submenu.
Computed:
computed: {
width() {
return this.$vuetify.breakpoint.width
},
},
Watch:
watch: {
width() {
this.setSubMenuWidth()
},
},
setSubMenuWidth() {
this.subMenuWidth = this.$vuetify.breakpoint.width
this.$refs.submenu.style.width = this.subMenuWidth + 'px'
}
Resizing works but after reloading the changes are lost.
It seems to be all ok.
All you have to do is use mounted to run the method after the page is loaded or reloaded.
mounted() {
this.setSubMenuWidth()
},
Edit:
I recommend you to check this: https://v2.vuejs.org/v2/guide/instance.html#Lifecycle-Diagram
Vue has a life cycle, check it out.

Vue-router param not updating with back button

I am using a param, and when I push the param using this.$router.push() it works.
routes: {
path: ':stepId?',
name: 'stepper'
}
BUT, I am also watching $route inside a component in order to catch the value of the param changing (As described in the docs):
watch: {
$route: {
handler: function(to, from) {
const newStepId = (to.params && to.params.stepId) || this.steps[0].id;
const initial = !from;
if (initial || newStepId !== from.params.stepId) {
this.goToStep(newStepId, initial);
}
},
immediate: true
}
}
However when I use the back button, either the to section of the route inside the watch: $route doesn't have any param, just the path OR the watch doesn't even run.
I had the same issue, what worked for me was adding the $watch in the created() method.
created() {
this.$watch("$route",() => {
// this.$route.query is watched now as expected
},
{ immediate: true });
}
Still a bit unclear to me though why putting it in mounted or like what you did doesn't work

Undefined data when using vuex and vue-router

I'm having an issue with the initial state of data in my application. I'm using vuex and vue-router, and I think the async stuff is tripping me up, but I'm not sure how to fix it.
In my view.vue component:
beforeRouteEnter(to, from, next) {
store.dispatch('assignments/getAssignment', {
id: to.params.id
}).then(res => next());
},
In my module:
getAssignment({commit, state}, {id}) {
return axios.get('/assignments/' + id)
.then(response => {
if(response.data.data.type == 'goal_plan') {
const normalizedEntity = normalize(response.data.data, assignment_schema);
commit('goals/setGoals', {goals: normalizedEntity.entities.goals}, {root: true});
commit('goals/setGoalStrategicPriorities', {goal_priorities: normalizedEntity.entities.strategicPriorities}, {root: true});
commit('goals/setObjectives', {objectives: normalizedEntity.entities.objectives}, {root: true});
commit('goals/setStrategies', {strategies: normalizedEntity.entities.strategies}, {root: true});
}
commit('setAssignment', {assignment: response.data.data});
}).catch(error => {
console.log(error);
EventBus.$emit('error-thrown', error);
});
},
A couple of subcomponents down, I want to access state.goals.goals, but it is initially undefined. I can handle some of the issues from that, but not all.
For example, I have a child component of view.vue that includes
computed: {
originalGoal() {
return this.$store.getters['goals/goalById'](this.goalId);
},
},
data() {
return {
form: {
id: this.originalGoal.id,
description: this.originalGoal.description,
progress_type: this.originalGoal.progress_type,
progress_values: {
to_reach: this.originalGoal.progress_values.to_reach,
achieved: this.originalGoal.progress_values.achieved,
},
due_at: moment(this.originalGoal.due_at).toDate(),
status: this.originalGoal.status,
},
In the heady days before I started using vuex, I was passing in the original goal as a prop, so it wasn't an issue. Since it's now pulled from the state, I get a bunch of errors that it can't find the various properties of undefined. Eventually originalGoal resolves in the display, but it's never going to show up in the form this way.
I tried "watch"ing the computed prop, but I never saw when it changed, and I'm pretty sure that's not the right way to do it anyway.
So, is there a way to get the data set initially? If not, how should I go about setting the form values once the data IS set? (Any other suggestions welcome, as I'm pretty new to vuex and vue-router.)
So if I set the form values in "mounted," I'm able to get this to work. Still learning about the vue life-cycle I guess. :)

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: