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

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.

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

VueJS - function in import js file not getting triggered

We are building a web application using Vue JS and PHP, we are new to Vue JS. The server-side execution is fine, the API is able to fetch data as JSON. While trying out a static array display before making the API call, we find that the function in imported "app.js" is not getting called and the table displayed is empty. Please let us know what we might be doing wrong. Appreciate your help.
import Vue from 'vue';
export const MY_CONST = 'Vue.js';
export let memberList = new Vue({
el: '#members',
data: {
members: []
},
mounted: function () {
this.getAllMembers();
},
methods: {
getAllMembers: function () {
/*
axios.get("https://xxxxxx.com/services/api.php")
.then(function (response) {
memberList.members = response.data.members;
});
*/
memberList.members = [{ "empname": "Dinesh Dassss" },
{ "empname": "Kapil Koranne" }];
}
}
});
This is the Vue component. The members object is empty.
<script>
import * as mykey from './app.js'
export default {
name: 'Home',
props: {
msg: String
},
data() {
return {
message: `Hello ${mykey.MY_CONST}!`,
members: mykey.memberList.members
}
}
};
</script>
You can also use this reference for current instance reference:
getAllMembers: function () {
var me = this;
/*
axios.get("https://xxxxxx.com/services/api.php")
.then(function (response) {
// direct this not works here but we have
//saved this in another variable and scope of a var is there
me.members = response.data.members;
});
*/
// this reference works fine here.
this.members = [{ "empname": "Dinesh Dassss" },
{ "empname": "Kapil Koranne" }];
}

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.

update data in component from Vue.directive

I have a directive that needs to update data in a Vue.component. How do I set the value? Here is my code:
Vue.directive('loggedin', function(value) {
console.log('loggedin = ' + value);
vm.$set('loggedIn', value);
});
vm.$set('loggedIn', value) does not work. I get the following error:
Uncaught TypeError: Cannot read property '$set' of undefined
var ck = Vue.component('checkout', {
template: '#checkout-template',
props: ['list'],
data: function() {
return {
loggedIn: '',
billingAddr: [],
shippingAddr: [],
}
},
});
The value being passed is 'true' or 'false'.
EDIT
I need to bind <div v-loggedin="true"></div> to my data value in the component and set that to 'true'. I do not need two-way binding.
Maybe I'm going about this the wrong way. Basically, I get a value for loggedin from the server and need to set my loggedIn value to true or false in the data on the component.
I'm not sure how you are using your directive, so I'm just going to make an assumption. Please correct me if I'm wrong.
Have a look at the twoWay property (you would probably need to use the object syntax though):
Vue.directive('loggedin', {
twoWay: true, // Setup the two way binding
bind: function () {
},
update: function (newValue) {
console.log('loggedin = ' + value);
this.set(newValue); // Set the new value for the instance here
},
unbind: function () {
}
});
Then you can use the directive like this (loggedIn is the property you want to write to afterwards, and which serves as the initial value as well):
<yourelement v-loggedin="loggedIn">...</yourelement>
Regarding your edit
Since you only want to pass data from your server to the component, you're much better of just using props:
var ck = Vue.component('checkout', {
template: '#checkout-template',
props: ['list', 'loggedIn'],
data: function() {
return {
billingAddr: [],
shippingAddr: [],
}
},
});
And then when using your component, pass it:
<checkout :loggedIn="true">
...
</checkout>
I have decided to go another route. There had to be a simpler way of doing this. So, here is what I did.
I am checking if a user is logged in by doing an ajax request through the 'created' function on the vm. I then update the auth variable in the vm with true or false.
var vm = new Vue({
el: 'body',
data: {
auth: false,
},
methods: {
getData: function() {
this.$http.get('{!! url('api/check-for-auth') !!}').then(function(response) {
this.auth = response.data;
}.bind(this));
},
},
created: function() {
this.getData();
},
});
In the component I created a props item called 'auth' and bound it to the auth data on the vm.
var ck = Vue.component('checkout', {
template: '#checkout-template',
props: ['list', 'auth'],
data: function() {
return {
user: [],
billingAddr: [],
shippingAddr: [],
}
},
});
And my component
<checkout :list.sync="cartItems" :auth.sync="auth"></checkout>
Thanks everyone for your help.