Cannot access $refs inside mounted function VUE - vue.js

In my template I have:
<apex-chart v-if="followers_options" ref="chart1" height="160" type="area" :options="followers_options"
:series="followers_series"></apex-chart>
I'm calling this function on mounted:
export default {
components: {
app: appLayout,
auth: authLayout,
},
mounted: function () {
this.uChart()
},
methods: {
uChart: function() {
const store = useStore();
let weight_series = [];
store
.dispatch("getWeights")
.then((data) => {
for (var j = 0; j < data.table.length; j++){
weight_series.push(data.table[j].weight);
}
console.log(this.$refs.chart1);
this.$refs.chart1.updateSeries([{ name: 'Weight', data: weight_series }]);
})
.catch((error) => {
console.log(error);
});
}
}
};
Yet when I look at the console I get undefined on the $refs log and couldn't find updateSeries on the other line.
I've also tried with a plain input tag with a ref but had no luck.
I'm new to vue so any help would be greatly appreciated.
cheers
To see the $ref yet it was undefined.

Related

How to check if JSON data is loaded

I use axios to fetch my JSON file en vuex for using the fetched data over multiple components.
The thing is that my page renders before all data is loaded.
The following works because I delayed the rendering by 2 seconds, without this timeout it would result in an error.
I would like to do this the proper way but am not sure how to do it.
STORE.JS
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
poss: null
},
getters: {
NAME: state => {
return state.name
},
POSS: state => {
return state.poss
}
},
mutations: {
SET_POSS : (state,payload) => {
state.poss = payload
},
ADD_POSS : (state,payload) => {
state.poss.push(payload)
},
},
actions:{
GET_POSS : async (context,payload) => {
let { data } = await axios.get("json/poss.json")
context.commit('SET_POSS',data)
},
SAVE_POSS : async (context,payload) => {
let { data } = await axios.post("json/poss.json")
context.commit('ADD_POSS',payload)
}
}
});
COMPONENT.VUE
module.exports = {
mounted:function(){
var self = this;
setTimeout(function () {
self.mkPageload()
}, 2000);
},
methods: {
mkPageload: function(){
let positions = this.$store.getters.POSS.pos
Object.keys(positions).forEach(key => {
// rendering
}
}
}
}
The desired result is that the page is only rendered after all data from the JSON file has been loaded.
There are several ways to solve this.
You could use wait / async in your component.
async mounted () {
await userStore.getAll()
// access getter and render
},
Your could watch vuex variable like (could be done without async but I like to add them)
async mounted () {
await userStore.getAll()
},
computed: {
...mapGetters('users')
},
watch: {
users(newValue, oldValue) {
....
// render
}
}
dont'forget to import the mapGetters: https://vuex.vuejs.org/guide/getters.html

How to set a value inside a variable on data() using a function?

I'm creating a Vue.js component inside a Laravel App.
After I catch the response with an axios request, I can't put a value inside a variable on method data()
Here is the code:
app.js
require('./bootstrap')
window.Vue = require('vue')
Vue.component('card', require('./components/card.vue'))
let app = new Vue({
el: '#app'
})
card.vue
<script>
module.exports = {
props: [
'name'
],
data: function() {
return {
projects: [],
}
},
mounted() {
this.getProjects() // NOT WORK?
},
methods: {
getProjects: function() {
axios.get('/api/v1/getProjects').then(function (response) {
console.log(response.data)
this.projects = response.data // NOT WORK
}).catch(function (error) {
console.log(error)
}).then(function () {
})
},
}
}
</script>
It's because of using this in response callback. You should use an arrow function (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) or save the context in separate variable.
Try to add .bind(this) or replace function with =>:
getProjects: function() {
axios.get('/api/v1/getProjects').then((response) => {
console.log(response.data)
this.projects = response.data // NOT WORK
}).catch((error) => {
console.log(error)
}).then(function () {
})
},

aixos reponse data can not assign to Vue instance's data

In my vue.js project, i get an array data by axios, and want to assign to bookList variable, but failed, bookList still equal to [], could you tell me why?
export default {
...
data () {
return {
bookList: []
}
},
mounted: function() {
this.$nextTick(function(){
this.viewBooks();
});
},
methods: {
viewBooks: function() {
axios.get('/books.json')
.then(res=>{
this.bookList = res.data.bookList;
})
.catch(error=>{
console.log(error);
});
}
}
The callback is on a different scope...this should work
methods: {
viewBooks: function() {
let self = this;
axios.get('/books.json')
.then(res=>{
self.bookList = res.data.bookList;
})
.catch(error=>{
console.log(error);
});
}
There's also a different answer here

this.$http.get is not working inside methods vue js

I am working with Laravel + spark + vue js.
Blade file
<draggable class="col-md-12" :list="emergencies" :element="draggableOuterContainer" #end="onEnd">
Js file
import draggable from 'vuedraggable'
module.exports = {
data() {
return {
emergencies:[]
};
},
components: {
draggable,
},
created() {
this.getEmergencies();
},
methods: {
getEmergencies() {
this.$http.get('/ajax-call-url')
.then(response => {
this.emergencies = response.data;
});
},
onEnd: function(evt){
var counter = 1;
this.emergencies.forEach(function(user, index) {
this.$http.get('/ajax-call-url/')
.then(response => {
});
counter++;
});
}
}
};
Here I have drag and Drop, On Drop, I call "onEnd" function and getting following error.
TypeError: this is undefined
Here this.emergencies.forEach is working but it is giving error on this.$http.get
Any suggestions, what can be the solutions?
Instead of using function syntax, use arrow functions, as scope of this changes inside function:
onEnd: function(evt){
var counter = 1;
this.emergencies.forEach((user, index) => {
this.$http.get('/ajax-call-url/')
.then(response => {
});
counter++;
});
}
Check this for explanation.

VueJS: Setting data initially based on http response

So I have a template .vue file:
<template>
<div id="app">
<textarea v-model="input" :value="input" #input="update"></textarea>
<div v-html="compiledMarkdown"></div>
</div>
</template>
<script>
var markdown = require('markdown').markdown;
export default {
name: 'app',
data() {
return {
input: '# Some default data'
}
},
mounted: function () {
this.$nextTick(function () {
this.$http.get(window.location.pathname + '/data').then((response) => {
this.input = response.body.markdown;
}) })
},
computed: {
compiledMarkdown: function() {
this.$http.post(window.location.pathname, {
"html": markdown.toHTML(this.input)}).then(function() {
},function() {
});
return markdown.toHTML(this.input);
}
},
methods: {
update: function(e) {
this.input = e.target.value
}
}
}
</script>
In the mounted function I am trying to set input equal to the response of an HTTP request, but when you view this file this.input is still the same as it was initially declared. How can I change this.input inside the compiledMarkdown function to be this.input in the mounted function. What other approaches might I take?
You can not call a async method from a computed property, you can use method or watcher to run asynchronous code, from docs
This is most useful when you want to perform asynchronous or expensive operations in response to changing data.
You have to ran that relevant code when input changes, like following:
var app = new Vue({
el: '#app',
data: {
input: '# Some default data',
markdown : ''
},
methods: {
fetchSchoolData: function (schoolId) {
var url = this.buildApiUrl('/api/school-detail?schoolId=' + schoolId);
this.$http.get(url).then(response => {
this.schoolsListData = response.data;
}).catch(function (error) {
console.log(error);
});
},
},
mounted: function () {
this.$nextTick(function () {
this.$http.get(window.location.pathname + '/data').then((response) => {
this.input = response.body.markdown;
})
})
},
watch: {
// whenever input changes, this function will run
input: function (newInput) {
this.$http.post(window.location.pathname, {
"html": markdown.toHTML(this.input)}).then(function() {
},function() {
this.markdown = markdown.toHTML(this.input);
});
}
},
Have a look at my similar answer here.