Load new JSON data and replace the old one in VueJS - javascript

I'm using a v-for loop with data fetched from JSON file. Is there a way to re-render the DOM and whole v-for loop after loading a new JSON file and replacing the old one?
What I'm trying to achieve is load different sets of products on click and update DOM.
Vue.use(VueResource);
var productsList = new Vue({
el: '#vue',
data: function () {
return {
products: []
};
},
ready: function () {
this.$http.get('data/data.json').then(function (response) {
this.products = response.data;
});
},
methods: {
loadProducts: function (url) {
this.$http.get(url).then(function (response) {
this.products = response.data;
});
}
}
});

The code above should be sufficient for updating your DOM automatically. There are 2 errors however and 1 thing you should consider.
Anonymous functions have different scopes in javascript. This means that when you have an anonymous function function(response) then you lose the scope of the vue instance this. In order to deal with such situations you have to either use arrow functions if you have support for them in your project or save this into another variable before entering the anonymous function.
Vue.use(VueResource);
var productsList = new Vue({
el: '#vue',
data: function () {
return {
products: []
};
},
ready: function () {
var self=this;
this.$http.get('data/data.json').then(function (response) {
self.products = response.data;
});
},
methods: {
loadProducts: function (url) {
var self=this;
this.$http.get(url).then(function (response) {
self.products = response.data;
});
}
}
});
Also if you have this exact code, you should've received an error in browser with products being undefined.

Once you update the products data it will automatically change the DOM as par the latest data, as vue data is reactive. One error I see in your code is, you may have wrong this inside the this.$http block. instead of using function() syntax, use arrow function, which does not bind it's own this, arguments, super, or new.target, like following:
Vue.use(VueResource);
var productsList = new Vue({
el: '#vue',
data: function () {
return {
products: []
};
},
ready: function () {
this.$http.get('data/data.json').then((response) => {
this.products = response.data;
});
},
methods: {
loadProducts: function (url) {
this.$http.get(url).then( (response) => {
this.products = response.data;
});
}
}
});

Related

Vuejs ajax call not mapping changes to underlying html table

I am making simple ajax call with vuejs and axios:
var app1 = new Vue({
el: '#app1',
data: {
test: []
},
methods: {
setAJAX: function () {
axios.get('/Departments/GetDepartments/').then(response => this.test = response.data.listBACAET);
}
}
});
Why is this working:
setAJAX: function () {
axios.get('/Departments/GetDepartments/').then(response => this.test = response.data.listBACAET);
}
But this is not working, changes are not mapped into table (this.test is undefined):
setAJAX: function () {
axios.get('/Departments/GetDepartments/').then(function(response){this.test = response.data.listBACAET});
}
This is because of the way arrow functions work: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#No_separate_this
When using an arrow function, this is implicitly bound to this of the enclosing scope, which is, in your case, the vue instance on which the method is called.
So you're setting the data of your view model, which works.
When using a std. function, there is no this in the scope, hence the error. To use a std. function, you need to define a closure for your view model like this:
setAJAX: function () {
let vm = this
axios.get('...').then( function(response) {
vm.test = response.data.listBACAET
});
}

How can I assign data from received data in VueJS?

How can I assign data from received data?
my code is below. axios is working well. I can get response.data from server . and I tried to assign the data to imglists variable. but It doesn't assign. What's wrong with me? Is There something wrong?
please help me out.
var app = new Vue({
el: '#app',
data: {
imglists: [],
},
created(){
axios.post('https://test.com/hello-lambda')
.then(function (response) {
this.imglists = response.data;
}).catch(function (error) {
console.log(error);
});
}})
In the example code above this is bound to the created function. To bind this to the object context, you'll need a function that doesn't bind this. Use ES6(ES2015) to solve the binding issue.
Use the ES6 syntax:
var app = new Vue({
el: '#app',
data: {
imglists: [],
},
created(){
axios.post('https://test.com/hello-lambda')
.then(response => this.imglists = response.data)
.catch(error =>console.log(error));
}
})
Your reference to this is scoped to the function it is inside of so you need to create an external reference.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
Also data should be a returned object to create a reactive object to trigger re-renders (nextTick) when the data is changed in imagelists due to this usage case being an asynchronous call.
https://v2.vuejs.org/v2/guide/reactivity.html#Async-Update-Queue
var app = new Vue({
el: '#app',
data: () => ({
imglists: []
}),
created(){
let self = this;
axios.post('https://test.com/hello-lambda').then(response => {
self.imglists = response.data;
}).catch(error => {
console.log(error);
});
}})
The var self and function then() plus its own content is scoped to function created() allowing child functions access to vars declared at the top level (parent function or script file) but be mindful if 'strict mode' is enforced as this will change the behavior of scoping / inheritance.

How to use data from one hook to other hook in Vue.js?

In my vue.js application I send request by axios package in created() hook. I add response to array called coordinates. I want to use that array outside of created() hook. For example in mounted() hook or in functions which we can set in methods.
Right now when I tried to use self.coordinates outside created() hook it return undefined. When I use this.coordinates it return just [__ob__: Observer].
Whats wrong I did?
export default {
name: "Map",
data() {
return {
coordinates: [],
}
},
created() {
let self = this;
axios.get('URL').then(function (response) {
let coordinates = [];
for (let i = 0; i < response.data.length; i++) {
coordinates.push([response.data[i]["LATITUDE"], response.data[i]["LONGITUDE"]]);
}
self.coordinates = coordinates;
});
},
mounted() {
console.log(self.coordinates); // undefined
consol.log(this.coordinates); // [__ob__: Observer]
},
}
I would prefer "mounted" and move the logic into methods for reusability. The method can be kicked from anywhere afterwards. In the example below, I prefered kicking the method direcly. Watchers is another option.
Here is the fiddle https://jsfiddle.net/dj79ux5t/2/
new Vue({
el: '#app',
data() {
return {
coordinates: []
}
},
mounted() {
let self = this;
axios.get('https://api.weather.gov/').then(function (response) {
self.coordinates = response.data;
self.greet();
});
},
methods: {
greet: function () {
console.warn(this.coordinates.status);
}
}
})
I think instead of mounted , you should use watch . You call some link so it will take time to load that data , watch method will trigger when your data is updated ...
watch: {
coordinates: {
handler: function (updateVal, oldVal) {
console.log(updateVal)
},
deep: true
}
},

Vue plugin, adding global component which takes data

I am using Vue plugins so that user can access a global component once registering the global component and configuring it inside Vue.use. For this I need to pass some data from Vue.use() to Component.vue.
Take a look at the following code:
Vue.use(MyPlugin, { data: true });
the code of MyPlugin is
import Plugin from './plugin';
const IconPlugin = {
install(Vue, options) {
console.log(options); // Here I can see {data: true}
Vue.component('GlobalComponent', Icon);
},
};
Now I need to pass this options variable to the component. So that a user whenever use
<GlobalComponent />
{data: true} should always be there.
Basically, that is a configuration which user is passing and the further component computation will be dependent on this.
You can use Vue.extend to extend components
var Icon = Vue.extend({
data: function() {
return {
foo: 'fooooo',
bar: 'barr'
}
},
template: '<div><button #click="doFooStuff">{{foo}}</button><button #click="doBarStuff">{{bar}}</button></div>',
methods: {
doBarStuff: function() {
console.log(this.foo, this.bar)
},
doFooStuff: function() {
console.log(this.foo)
}
}
})
const IconPlugin = {
install(Vue, options) {
// console.log(options);
// normalize data (select only props you want)
var data = Object.assign({}, options);
var NewIcon = Icon.extend({
data: function() {
return data;
}
})
Vue.component('GlobalComponent', NewIcon);
},
};
Vue.use(IconPlugin, {
foo: 'FOOO'
});
new Vue({
el: '#app',
components: {
Icon
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id="app">
<icon></icon>
<global-component></global-component>
</div>
it sounds like you want to take a look at the component guide. It would seem that you want to merge the data with where you are passing Icon.

VueJS2 property not defined

I wrote the following code and Vue complains:
[Vue warn]: Property or method "incidents" is not defined on the
instance but referenced during render. Make sure to declare reactive
data properties in the data option.
I don't see why incidents cannot be accessed?
var app = new Vue({
el: '#app',
data: {
responders: [],
incidents: []
},
mounted: function () {
this.getIncidents();
},
methods: {
getIncidents: function() {
console.log('getIncidents');
var app = this;
this.$http.get('/api/v1/incidents').then(function(response) {
// set data
var incidentsReceived = response.data.map(function (incident) {
return incident;
});
Vue.set(app, 'incidents', incidentsReceived);
})
},
getResponders: function() {
console.log('fetchResponders');
var app = this;
this.$http.get('/api/v1/responders').then(function(response) {
// set data on vm
var respondersReceived = response.data.map(function (responder) {
return responder
});
Vue.set(app, 'responders', respondersReceived);
});
}
}
})
EDIT: Didn't read the code very well for the first time. Verify that you have data inside the response and if not don't set it the incidents array.
data is meant for internal component data modeling, while props, which can be assigned externally, are defined using the props key for your component.
In other words, try:
var app = new Vue({
...,
props: {
incidents: {
type: Array,
required: false //change this as you see fit.
}
},
...
});
For full documentation on component properties, please refer to the official guide.

Categories

Resources