How to use vue-resource whit jsonp? - javascript

I'm trying to get data from this url,
http://opendata.euskadi.eus/contenidos/ds_recursos_turisticos/albergues_de_euskadi/opendata/alojamientos.json
which returns a jsonp, but I can not get them with vue-resource (with pure javascript, JQuery, and some other libary like fetch-jsonp, I get them).
Could someone please post an example?
this is my code
new Vue({
el: '.App',
mounted: function () {
this.cojerDatos()
},
data: {
losDatos: {}
},
methods: {
cojerDatos() {
const url = "http://opendata.euskadi.eus/contenidos/ds_recursos_turisticos/albergues_de_euskadi/opendata/alojamientos.json";
this.$http.jsonp(url,{params: {jsonCallback: 'jsonCallback'}})
.then(response => console.log(response.json()))
},
}
})
I note, moreover, that the url adds the parameters of a call to the random callback.
Thank you very much.

Related

VueJS, Vuex, Getter is showing as an empty array, but console.log shows it's an object with all the values

This is the method I'm using, pretty simple.
DailyCountTest: function (){
this.$store.dispatch("DailyCountAction")
let NewPatientTest = this.$store.getters.NewPatientCountGET
console.log(NewPatientTest)
}
The getter gets that data from a simple action that calls a django backend API.
I'm attempting to do some charting with the data so I need to assign them to variables. The only problem is I can't access the variables.
This is what the console looks like
And this is what it looks like expanded.
You can see the contents, but I also see empty brackets. Would anyone know how I could access those values? I've tried a bunch of map.(Object) examples and couldn't get any success with them.
Would anyone have any recommendation on how I can manipulate this array to get the contents?
Thanks!
Here is the Vuex path for the API data
Action:
DailyCountAction ({ commit }) {
axios({
method: "get",
url: "http://127.0.0.1:8000/MonthlyCountByDay/",
auth: {
username: "test",
password: "test"
}
}).then(response => {
commit('DailyCountMutation', response.data)
})
},
Mutation:
DailyCountMutation(state, DailyCount) {
const NewPatientMap = new Map(Object.entries(DailyCount));
NewPatientMap.forEach((value, key) => {
var NewPatientCycle = value['Current_Cycle_Date']
state.DailyCount.push(NewPatientCycle)
});
}
Getter:
NewPatientCountGET : state => {
return state.DailyCount
}
State:
DailyCount: []
This particular description of your problem caught my eye:
The getter gets that data from a simple action that calls a django backend API
That, to me, implies an asynchronous action and you might be getting a race condition. Would you be able to post a sample of your getter function to confirm my suspicion?
If that getter does indeed rely on an action to populate its contents, perhaps something to the effect of the following might do?
DailyCountTest: async () => {
await this.$store.dispatch('DailyCountAction')
await this.$store.dispatch('ActionThatPopulatesNewPatientCount')
let NewPatientTest = this.$store.getters.NewPatientCountGET
// ... do whatever with resulting array
}
You can also try with a computer property. You can import mapGetters
import { mapGetters } from 'vuex'
and later in computed properties:
computed: {
...mapGetters(['NewPatientCountGET'])
}
then you can use your NewPatientCountGET and it will update whenever the value changes in the store. (for example when the api returns a new value)
Hope that makes sense

How to initiate a function using data(){} but not mounted(){} while using vue-resource

This works, but I need to use mounted(){} to initiate the function which I think can be avoided but not sure how.
<script>
export default {
data () {
return {
domains: [],
}
},
methods: {
fetchDomains() {
let _this = this;
api._get({url: 'api/domains'})
.then(function (response) {
_this.domains = response.data;
})
}
},
mounted() {
this.fetchDomains()
}
}
</script>
This code doesn't work, but I like to do something like this. Initiating the function in data(){} itself.
<script>
export default {
data () {
return {
domains: this.fetchDomains(),
}
},
methods: {
fetchDomains() {
let data = [];
api._get({url: 'api/domains'})
.then(function (response) {
data = response.data;
})
return data
}
}
}
</script>
Thanks in advance.
Your first code snippet is the correct way to do it.
You can't initialize domains with the data from the API response because it is an async operation which may or may not be resolved successfully at some point in the future, well after the component is mounted. You might also want to do other things like keeping track of the async operation with a loading property which you set to true for the duration of the request.
Your component will initially be in a loading state which does not yet have any domains data, and you need to account for this. Show a loading spinner or something during this time.
I agree with Decade Moon that your first approach is the better way to do it (though you could use created instead of mounted).
The reason your second approach doesn't work is that you return an array and then replace the local variable's value with a different array. What you need to do is populate the array you returned.
new Vue({
el: '#app',
data() {
return {item: this.getItem()}
},
methods: {
getItem() {
let val = [];
setTimeout(() => {
const result = ['first','second','third'];
val.push(...result);
}, 800);
return val;
}
}
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<div id="app">{{item}}</div>
I might be deviating slightly from the question (since it explicitly mentions the data property), but I think this might be helpful. Personally, if I want to provide some data with more complex logic I use the computed property. This is great in my opinion and you can read more about it in the docs. The problem in this case is that it doesn't work entirely as expected with asynchronous operations...
However, there is a lovely little module called vue-async-computed which can be found here. It solves this specific problem by providing an asyncComputed property and keeps the code really clean!

Using Fetch API with Rails application?

I am trying to use the Fetch API with my Rails application. I can pass parameters to the controller as part of a query string, but still can't figure out how to pass JSON data or where to find it in the controller. A sample call looks like the below. Where can I access my test data on in the controller? Happy Sunday :)
export const fetchControllerData = () => {
return fetch('api/users',), {
body: { "test": "test" }
})
.then(res => res.json());
};
I'm in the process of working out my own issues with fetch and Rails. But I'll take a stab at this.
I expect that fetch is using GET as the default method - which won't use the body at all. You will likely need to set the method to be POST to get the body through. Further to that you might need to set the Content-Type header (to application/json) in order to send the data through as JSON.
May be u need to send params in this way for get request and use this link for https://github.com/axios/axios
export const fetchControllerData = () => {
params = { body: { "test": "test" } }
return HTTP.get('api/users', params)
.then((response) => {
if (response.success) {
// do something here
} else {
// handle error condtion here
}
});
}

Vue not loading data

I have a vue/coffeescript app that looks like this:
There are no errors in the console, and it says it's making a successful external request for the JSON, however When I say {{book.name}}, it only returns as Test instead of coming from the JSON.
new Vue({
el: '#app',
data: {
showModal: false,
book: {
name: "Test",
description: "",
photo: ""
}
}
ready: () ->
this.getBookData()
console.log (this.book)
methods: {
getBookData: () ->
self = $(this)
$.getJSON 'GGPK4A.json', (data) ->
self.book = data
}
})
I don't know how to do it in coffeescript, but I think the issue is that this doesn't refer to Vue within the callback function, so setting this.book isn't working. Normally you can fix this using .bind(this) on the function, or setting var vm = this before the ajax call and setting vm.book in the callback.

React Component JSON Callback Scope

I'm using generator-react-webpack to create a React web app. This web app relies on JSON feeds - one of which is hosted on a CDN that does not support JSONP and the CDN url is a subdomain of the webapp. Is there any way to return the JSON data from within the React Component?
Basic React Component:
var AppComponent = React.createClass({
loadData: function() {
jQuery.getJSON(jsonFile.json?callback=?)
.done(function(data) {
console.log(data);
}.bind(this));
},
render: function(){
return ( ... );
}
});
I've tried a few solutions, and have come to the conclusion that I need to define my own callback on the JSON file like so:
JSON:
handleData({
"data": "hello World"
})
Is there a way for the handleData callback to be defined in the react component, or the response accessed from the react component? Any thoughts as to how I can get this to work are much appreciated. Thanks!
This looks like an odd way to do things, especially the part where you're using jQuery. That's a client-side utility to overcome not knowing where everything is and not having direct access to your elements. It makes no sense to use it when you're using React weith Webpack for bundling: React already knows where everything is (using refs) and Webpack means you can just use regular universal Node modules for everything that you need to do.
I'd recommend using something like, using request or a similar universal fetch API:
// loadData.js
var request = require('request');
var loadData = function(urlYouNeed, handler) {
request(urlYouNeed, function(error, response, body) {
if (error) {
return handler(error, false);
}
// do anything processing you need on the body,
var data = process(body);
handler(false, data);
};
So: just a module you can require in any component you define with require('./loadData'). And then in your actual component you do this:
var loadData = require('./loadData');
var AppComponent = React.createClass({
getDefaultProps: function() {
return {
jsonURL: "cdn://whateverjson.json"
};
},
getInitialState: function() {
loadData(this.props.jsonURL, this.updateData);
return {
data: []
}
},
updateData: function(err, data) {
if (err) {
return console.error(err);
}
data = secondaryEnsureRightFormat(data);
this.setState({ data: data });
},
render: function(){
var actualThings = this.state.data.map((entry, pos) => {
return <Whatever content={entry} key={entry.dontUseThePosVariableUpThere}/>
});
return (
<div>
...
{actualThings}
...
</div>
);
}
});
Much cleaner.
If I understand correctly the question, you only have to change your loadData this way :
loadData: function() {
var c = this
jQuery.getJSON(jsonFile.json?callback=?)
.done(function(data) {
c.handleData(data)
});
},
handleData: function(data) {
/* Implement here the function to handle the data */
},

Categories