I'm trying to understand Vue and it's dependencies (newbie) just need help to understand the way axios works so it can be clear to me.
If I use code below it works to returning my data:
methods: {
load: function() {
axios.get('/api/projects')
.then(
response => {
this.projects = (response.data.projects);
}
)
.catch(function (error) {
this.errors.push(error);
console.log(error);
})
}
}
But if I use code below it doesn't return data:
methods: {
load: function() {
axios.get('/api/projects')
.then(function (response) {
this.projects = (response.data.projects);
})
.catch(function (error) {
this.errors.push(error);
console.log(error);
})
}
}
The difference is in .then part only.
this is referring to different object in both functions.
Write console.log(this) and you will see that the one in arrow function is referring to Vue instance. The other one, however, is referring to other object. probably window. In the case of function() {} you can't access Vue instance via this. You need to store it beforehand in a variable.
var vm = this;
axios.get('/api/projects')
.then(function (response) {
console.log(this); // undefined or other object
console.log(vm); // vue instance
vm.projects = (response.data.projects);
})
See another SO post for more details.
From MDN:
An arrow function does not have its own this; the this value of the enclosing execution context is used.
It's not the axios that needs to be explained. It's how this keyword behaves in different contexts. Your first method makes use of something called Arrow Function, which doesn't have this of it's own so it uses the this of the current context. But your second method does have it's own this.
So, in order for you second method to work, you would have to cache this outside of the closure, like this:
methods: {
load: function() {
var that = this;
axios.get('/api/projects')
.then(function (response) {
that.projects = (response.data.projects);
})
.catch(function (error) {
this.errors.push(error);
console.log(error);
})
}
}
And then it will work.
Related
I'm writing a plugin for Wordpress that uses VueJS. Everything works fine until I come to send the data via a Ajax POST request.
Here is an extract of what I have:
data () {
return {
form: {
items: []
}
}
}
methods: {
processOrder () {
axios({
method: 'post',
url: '/ajax.php',
data: JSON.stringify({
action: "process_order"
})
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
}
and when I examine the request in Chrome I get:
"body":"{\"action\":\"process_order\"}"
which means the action key is never found on the server. If I take out the Stringify then the server sees nothing. Any ideas on how to remove the escaping?
u can try this
npm install qs --save-dev
and use:
import Qs from qs
data:Qs.stringify({action: "process_order"})
I am using getJSON in my knockout view:
$.getJSON("/GetItems", function (data) {
self.Items(data.map(viewModelFromData));
});
I want to make it a function for reuse so next time I can reload items on page action. How to do it?
When I tried:
self.getBasketItems = $.getJSON("/umbraco/Surface/Booking/GetBasketItems",
function(data) {
self.Items(data.map(viewModelFromData));
// or return data.map(viewModelFromData);
});
I got self.getBasketItems() is undefined.
The quickest fix:
self.getBasketItems = function() {
return $.getJSON(
"/umbraco/Surface/Booking/GetBasketItems",
function(data) {
self.Items(data.map(viewModelFromData));
});
};
This returns the promise, so you can use it in a chain like so:
self.getBasketItems().then(function() { console.log(self.Items()); })
You can also make a more general utility function like:
const getTransformWrite = (url, converter, target) =>
() =>
$.getJSON(url)
.then(converter)
.then(target);
}
}
self.getBasketItems = getTransformWrite(
"/umbraco/Surface/Booking/GetBasketItems",
data => data.map(viewModelFromData),
self.Items
);
I don't really think this is an improvement, but it might suit your style.
Make sure you don't forget to handle exceptions/errors!
what #haim770 suggested was this:
self.getBasketItems = function() {
return $.getJSON(
"/umbraco/Surface/Booking/GetBasketItems",
function(data) {
self.Items(data.map(viewModelFromData));
});
};
But, from your comments, it seems you're trying to actually return the value into self.getBasketItems? In that case, you will need to do a synchronous call (getJSON is asynchronous) using the $.ajax method instead.
self.getBasketItems = function() {
var _r;
$.ajax(
dataType: "json",
async: false,
url: "/umbraco/Surface/Booking/GetBasketItems",
success: function(data) {
_r = self.Items(data.map(viewModelFromData));
});
return _r
};
Please note that this second solution is very quirky. And the browser will actually hang waiting for the response from the server. You would be better of using either callbacks or promises.
Let me know if this helps!
Cheers,
I am getting the 'cannot read property push of undefined' error: here is my vueJs code:
data:{
CoIsignedListUID:[]
}
methods:{
fetchCoISigned: function () {
this.$http.get('/cimsm/public/api/fetchCoIsigned/' + this.conflictofInterest.complaintID).then(function (response) {
var data = response.data;
this.$set('CoIsignedList', data);
data.forEach(function (detail) {
this.CoIsignedListUID.push(detail.uID);
});
});
what am i doing wrong? Thanks
this.CoIsignedListUID is not defined
probably because this is not the this you think it is
you should do
var _this = this
outside the function and then
_this.CoIsignedListUID.push(detail.uID);
Alternatively, you can use ES2015 arrow syntax.
Instead of:
.then(function (response) {}
Use:
.then((response) => {}
The 'this' is now available inside the function so no need for creating a new variable. Full details Here.
this in the forEach callback is not the vue.js this.
you can do this to solve this problem.
this.$http.get("...").then(function(response){
var data = response.data;
this.$set('CoIsignedList', data);
var that = this;
data.forEach(function (detail) {
that.CoIsignedListUID.push(detail.uID);
});
});
I've been using the following code for doing ajax calls in Angular which worked fine so far:
function getData (url) {
var deferred = $q.defer();
$http.get(url, {
cache: true
}).success(function (data) {
deferred.resolve(data); // works
});
return deferred.promise;
}
As you can see there is only a success handler. When I wanted to add an error handler, I noticed that the docs state that success and error were depracated and should not be used any more (https://docs.angularjs.org/api/ng/service/$http). Instead the .then promise should be used, so I changed my code to this:
function getData (url) {
var deferred = $q.defer();
$http.get(url, {
cache: true
}).then(function (data) {
deferred.resolve(data); // Not called :(
}, function () {
deferred.resolve(false); // Not called :(
});
return deferred.promise;
}
Now everything stopped working. .then is never called. Why? I'm on latest Angular version 1.4
Ok, I found the problem. Actually, there were two problems.
First, I had a redundant promise which I removed:
function getData (url) {
return $http.get(url, {cache: true});
}
Second, the returned data from .then seems to be a little different from .success. Instead of returning the plain result data, it returns an object with some meta data from the call. So, in order to get the data, I'd have to access data.data:
pub.getList = function () {
return getData(serviceurl + "?c=latest").then(function (result) {
var list = result.data;
precacheArticles(list);
return list;
});
};
I created an .getjson() call to work with reddit.com's API. The code is below.
$(document).ready(function() {
var SEARCH_URL = 'http://www.reddit.com/r/subreddits/search.json?jsonp=?';
var searchQueryText = 'XBox'; //getSearchQueryText();
$.getJSON(SEARCH_URL, {
q: searchQueryText,
limit: 3
})
.done(function (data) {
$.each(data.data.children, function(i,item) {
$("<h1>").attr("src", item.data.url).appendTo("#images");
});
})
.fail(function (data) {
alert("Something went wrong");
});
});//end ready
My .getJSON() function works and gets back data. However I am having trouble with my .each() function. I know it's slightly off even though my console isn't giving me an error message. I was hoping someone much smarter than me could help me rewrite it so it passes the content through #images in my body?
The JSON looks like this
http://www.reddit.com/r/subreddits/search.json?q=xbox&limit=3
If you just want to show all URLs in the #images elements, there is some problem in your code.
I test the reddit JSON data you're fetching.
The URL is a web page link not a image resource.
So why you try to add a non-exist attribute "src" to h1 element?
Try to use text() if you just want to show the URL and append them to element:
var SEARCH_URL = 'http://www.reddit.com/r/subreddits/search.json?jsonp=?';
var searchQueryText = 'XBox'; //getSearchQueryText();
$.getJSON(SEARCH_URL, {
q: searchQueryText,
limit: 3
})
.done(function (data) {
$.each(data.data.children, function(i,item) {
$("<h1>").text(item.data.url).appendTo("#images");
});
})
.fail(function (data) {
alert("Something went wrong");
});
This is jsfiddle demo
Hope this is helpful for you.