Start watcher after created() is done - vue.js

My goal is to initially set up a data property when component is created and then set up a watcher on this property. The issue I am struggling with is the watcher catches initial property change in created method but this is not what I want. I would rather to watch data property only after initial change is made in created().
export default {
name: 'testComponent',
data() {
return {
testValue: 1;
}
},
watch: {
testValue() {
console.log('watcher catches!');
},
created() {
console.log(this.testValue);
this.testValue = 2;
console.log(this.testValue);
}
}
// CONSOLE OUTPUT: 1 -> watcher catches! -> 2
Can you tell me how to achieve behaviour like that?

No idea why you'd want that but you could simply do it like this:
export default {
name: 'testComponent',
data() {
return {
ready: false,
testValue: 1
}
},
watch: {
testValue() {
if (!this.ready) return;
console.log('watcher catches!');
},
created() {
this.testValue = 2;
this.ready = true;
}
}

Related

Vue3-My provide is not updated after changing the data using mounted

I tried to provide my data from a parent element like below.
data(){
return{
allData:null,
ingCollection:null,
selectedDish:[]
}
},
mounted(){
Promise.all([
d3.json('data.json'),
d3.json('ingredientsonly.json')
]).then((data)=>{
this.allData=data[0];
this.ingCollection=data[1];
})
},
components:{sidePanel,centerPiece},
methods: {
// receiveIngredients(selected){
// let selections = this.allData.filter(d=>{
// d.ingredients.includes(selected)
// });
// }
},
provide() {
return{
allData:this.allData,
ingCollection:this.ingCollection,
selectedDish:this.selectedDish,
receiveIngredients:this.receiveIngredients
}
}
However, after mounted lifecycle hook was run,
data is updated while provide elements were not updated.
Why is it?
Thank you
provide() is only called once at initialization, and not when there's a change to the references within.
Instead, you can provide an object (e.g., named root), and then update a property of that object in mounted():
export default {
provide() {
return {
root: {
allData: null,
ingCollection: null,
}
}
},
mounted() {
Promise.all([
d3.json('data.json'),
d3.json('ingredientsonly.json')
]).then((data)=>{
this.root.allData = data[0];
this.root.ingCollection = data[1];
})
}
}

Setting intial local data from Vuex store giving "do not mutate" error

I thought I understood the correct way to load inital state data from Vuex into the local data of a component, but why is this giving me “[vuex] do not mutate vuex store state outside mutation handlers.” errors! I am using a mutation handler!
I want my component data to start empty, unless coming back from a certain page (then it should pull some values from Vuex).
The component is using v-model=“selected” on a bunch of checkboxes. Then I have the following:
// Template
<grid-leaders
v-if="selected.regions.length"
v-model="selected"
/>
// Script
export default {
data() {
return {
selectedProxy: {
regions: [],
parties: [],
},
}
},
computed: {
selected: {
get() {
return this.selectedProxy
},
set(newVal) {
this.selectedProxy = newVal
// If I remove this next line, it works fine.
this.$store.commit("SET_LEADER_REGIONS", newVal)
},
},
},
mounted() {
// Restore saved selections if coming back from a specific page
if (this.$store.state.referrer.name == "leaders-detail") {
this.selectedProxy = {...this.$store.state.leaderRegions }
}
}
}
// Store mutation
SET_LEADER_REGIONS(state, object) {
state.leaderRegions = object
}
OK I figured it out! The checkbox component (which I didn't write) was doing this:
updateRegion(region) {
const index = this.value.regions.indexOf(region)
if (index == -1) {
this.value.regions.push(region)
} else {
this.value.regions.splice(index, 1)
}
this.$emit("input", this.value)
},
The line this.value.regions.push(region) is the problem. You can't edit the this.value prop directly. I made it this:
updateRegion(region) {
const index = this.value.regions.indexOf(region)
let regions = [...this.value.regions]
if (index == -1) {
regions.push(region)
} else {
regions.splice(index, 1)
}
this.$emit("input", {
...this.value,
regions,
})
},
And then I needed this for my computed selected:
selected: {
get() {
return this.selectedProxy
},
set(newVal) {
// Important to spread here to avoid Vuex mutation errors
this.selectedProxy = { ...newVal }
this.$store.commit("SET_LEADER_REGIONS", { ...newVal })
},
},
And it works great now!
I think the issue is that you can't edit a v-model value directly, and also you also have to be aware of passing references to objects, and so the object spread operator is a real help.

local storage data not being bound to data

i have a component, which calls a footer component. inside the footer component, i have a modal that shows on click. i want the title of that modal to be a data variable, and i want to set that data variable with data from local storage. for some reason, its not appearing.
I know that the data is in local storage. Any idea's?
export default {
name: "FooterComponent",
data: () => {
return {
privacy_modal: false,
privacy_title: '',
privacy_content: ''
};
},
methods: {
beforeMount() {
this.privacy_title = localStorage.getItem("privacy_title");
}
}
};
beforeMount is a lifecycle hook, not a method. It must be defined directly within options, not inside methods:
export default {
name: "FooterComponent",
data() {
return {
privacy_modal: false,
privacy_title: '',
privacy_content: ''
};
},
beforeMount() {
this.privacy_title = localStorage.getItem("privacy_title"); // || "some default value"
},
methods: {
// custom methods
}
};
Also, don't forget to update local storage, as demanded by your app logic.

VueJS How to access Mounted() variables in Methods

I'm new in Vue and would like assistance on how to access and use variables created in Mounted() in my methods.
I have this code
Template
<select class="controls" #change="getCatval()">
Script
mounted() {
var allcards = this.$refs.allcards;
var mixer = mixitup(allcards);
},
methods: {
getCatval() {
var category = event.target.value;
// I want to access mixer here;
}
}
I can't find a solution anywhere besides this example where I could call a method x from mounted() and pass mixer to it then use it inside my getCatval()
Is there an easier way to access those variables?
I will first suggest you to stop using var, and use the latest, let and const to declare variable
You have to first declare a variable in data():
data(){
return {
allcards: "",
mixer: ""
}
}
and then in your mounted():
mounted() {
this.allcards = this.$refs.allcards;
this.mixer = mixitup(this.allcards);
},
methods: {
getCatval() {
let category = event.target.value;
this.mixer
}
}
like Ninth Autumn said : object returned by the data function and props of your components are defined as attributes of the component, like your methods defined in the method attribute of a component, it's in this so you can use it everywhere in your component !
Here an example:
data() {
return {
yourVar: 'hello',
};
},
mounted() { this.sayHello(); },
method: {
sayHello() { console.log(this.yourVar); },
},
Update
you cannot pass any value outside if it's in block scope - Either you need to get it from a common place or set any common value
As I can see, var mixer = mixitup(allcards); is in the end acting as a function which does some operation with allcards passed to it and then returns a value.
1 - Place it to different helper file if mixitup is totally independent and not using any vue props used by your component
In your helper.js
const mixitup = cards => {
// Do some operation with cards
let modifiedCards = 'Hey I get returned by your function'
return modifiedCards
}
export default {
mixitup
}
And then in your vue file just import it and use it is as a method.
In yourVue.vue
import Helpers from '...path../helpers'
const mixitup = Helpers.mixitup
export default {
name: 'YourVue',
data: ...,
computed: ...,
mounted() {
const mixer = mixitup(allcards)
},
methods: {
mixitup, // this will make it as `vue` method and accessible through
this
getCatval() {
var category = event.target.value;
this.mixitup(allcards)
}
}
}
2- Use it as mixins if your mixitup dependent to your vue and have access to vue properties
In your yourVueMixins.js:
export default {
methods: {
mixitup(cards) {
// Do some operation with cards
let modifiedCards = 'Hey I get returned by your function'
return modifiedCards
}
}
}
And import it in your vue file:
import YourVueMixins from '...mixins../YourVueMixins'
const mixitup = Helpers.mixitup
export default {
name: 'YourVue',
mixins: [YourVueMixins] // this will have that function as vue property
data: ...,
computed: ...,
mounted() {
const mixer = this.mixitup(allcards)
},
methods: {
getCatval() {
var category = event.target.value;
this.mixitup(allcards)
}
}
}

New property to "export default"

Is it possible or recommended to add a custom property to a component like in the below example? In that case how can I call this property from a method?
export default {
data() {
return {
test = ""
};
},
methods: {
someMethod() {
//
},
},
customLoggingData {
title : "main",
}
};
I have seen some plugins that have their own property like the customLoggingData and I was just curious to know if that was possible.
If not I'll just have it as a method.
The recommendation from the vuejs team is this:
{
data: ...,
created: function () {
this.customLoggingData = {
...
}
}
}
See this github thread for more info.