I am using VueJS and got an error message that I didnt have before. The incidents var is an array, so it should work I would assume?
In my HTML file I included:
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-resource/1.2.0/vue-resource.js"></script>
When I log the output of response.data I see an array:
Uncaught (in promise) TypeError: response.data.map is not a function
at Vue$3. (main.js:17)
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 on vm
var incidentsReceived = response.data.map(function (incident) {
return incident
});
Vue.set(app, 'incidents', incidentsReceived);
});
}
})
You can not map over the response. Try setting the response data to your data so do
this.$http.get('/api/v1/incidents').then((response) => {
// set data in your data object
this.incidents = response.data
// Now you can map over the incidents and return
return this.incidents.map(incident => return)
});
Related
I have a computed property that will only be used if a match for a property exists. Because of this, I'm making the call to get the data asynchronous so that it's only retrieved when needed. I'm having an issue though trying to make an async call to return data for a computed property.
Below is what I have:
new Vue({
el: "#formCompleteContainer",
data: {
form: {},
components: []
},
computed: {
employeeList: function () {
var self = this;
if (_.some(this.components, function (component) {
return component.ComponentInfo.Type === 8
})) {
var employees = [];
$.ajax({
url: "/Form/GetAllUsers",
type: "GET"
}).done(function (results) {
employees = results;
});
return employees;
} else {
return [];
}
}
}
});
I know this isn't working because I'm returning before the call is complete. I've seen how to use deferredobjects and what not but I can't seem to figure out how to implement it with Vue.
For your use case, I don't think computed property can implement the goal.
My solution:
create one data property as one 'defered' object,
then uses one watch to async call your backend to get new data, finally assign to the defered object
like below demo:
Vue.config.productionTip = false
app = new Vue({
el: "#app",
data: {
product: "Boots",
deferedProduct: ''
},
watch: {
product: function (newVal, oldVal) {
setTimeout(() => {
this.deferedProduct = 'Cats in ' + newVal + '!'
}, 1500)
}
},
methods: {
nextProduct: function () {
this.product += 'a'
}
}
})
<script src="https://unpkg.com/vue#2.5.16/dist/vue.js"></script>
<div id="app">
<button #click="nextProduct()">Click Me!</button>
<h2>{{product}}</h2>
<h2>{{deferedProduct}}</h2>
</div>
This is what vue-async-computed is meant for. It resolves the promise you returned and handles any race conditions.
new Vue({
el: "#formCompleteContainer",
data: {
form: {},
components: []
},
asyncComputed: {
employeeList: function () {
if (_.some(this.components, function (component) {
return component.ComponentInfo.Type === 8
})) {
return $.ajax({
url: "/Form/GetAllUsers",
type: "GET"
});
} else {
return Promise.resolve([]);
}
}
}
});
After doing some more research I have gone another route. I agree with Sphinx that I don't think what I am trying to achieve will work with a computed property.
Instead, this is what I am going with:
new Vue({
el: "#formCompleteContainer",
data: {
form: {},
components: [],
employees: []
},
methods: {
getEmployees: function () {
var self = this;
if (_.some(this.components, function (component) {
return component.ComponentInfo.Type === 8;
})) {
$.ajax({
url: "/Form/Form/GetAllUsers",
type: "GET"
}).done(function (results) {
self.employees = results;
});
}
}
},
created: function () {
this.form = pageModel.Form;
this.components = pageModel.Components;
},
mounted: function () {
this.getEmployees();
}
});
As pointed out already, mounted and other 3rd party solutions can work.
However, better readability and component loading will come from putting the desired Promise within a data property. And then using the Vue lifecycle hook created, we can wait for that Promise to resolve with a .then.
For example:
requestService.js:
...
async foo(){
let myRequest = someRequest.createInstance()
await myRequest.onReady()
return myRequest.getSomePromise()
}
...
And then import the service into your component, as well as declaring a data prop:
myComponent.vue
...
data: (){
myPromiseLoc: null,
}
...
created: (){
requestService.foo().then( result =>
{
this.myPromiseLoc = result
}
}
...
The Axios response.data is okay. But when I use the markers variable in rendering the markers is undefined. I am a newbie and badly need your help for our project.
I am trying to render the markers from the link described in the code, but some I placed the axios request in the created, and in the mounted is the rendering of the leaflet map.
Screenshot of the code
<script>
/** Script Vue JS **/
new Vue({
el: '#view-map',
data: {
map,
map_link:'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
markerOption: {
clickable: true,
draggable: false
},
mapOptions: {
center: [7.3087, 125.6841],
zoom:8
},
markers:[], //[{"image":"GMS-4-0112018-467_1527086274.jpg","derivation_code":"GMS-4-0112018-467","sample_description":"test 1 test is a test that test will be tested in test","latitude":"6.428152","longitude":"125.317857"},{"image":"GMS-1-0112018-963_1527134301.jpg","derivation_code":"GMS-1-0112018-963","sample_description":"nalaya lang","latitude":"7.311647","longitude":"125.636461"}],
selectedSample: [],
},
methods: {
getMarkers: function (){
axios.get('http://127.0.0.1:8000/marker').then(response => {
this.markers = response.data;
}).catch(error =>( console.log(error) ));
},
renderMarker: function(){
for ( i = 0; i < this.markers.length; i++){
console.log(this.markers[i]);
var marker = new L.Marker([this.markers[i].latitude, this.markers[i].longitude], this.markerOption);
marker.addTo(this.map);
marker.bindPopup(`
<h6 class="display-6">${this.markers[i].derivation_code}</h6>
<img src="storage/images/${this.markers[i].image}" style="height:100%;width:100%">
`);
}
},
markerClicked: function(mrkr_data){
this.selectedSample = mrkr_data.derivation_code;
console.log(this.selectedSample);
}
},
created: function(){
this.getMarkers();
},
mounted: function(){
this.map = new L.map('map', this.mapOptions);
this.map.addLayer(new L.TileLayer(this.map_link));
console.log(this.markers);
this.renderMarker();
}
});
</script>
I solved my problem. I treated the fetching of data in Axios get property as a Synchronous but it is an Asynchronous. Base in my previous code, I accessed the data when it is not updated so the value is blank.
/** Script Vue JS **/
new Vue({
el: '#view-map',
data: {
map,
map_link:'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
markerOption: {
clickable: true,
draggable: false
},
mapOptions: {
center: [7.3087, 125.6841],
zoom:8
},
markers:[], //[{"image":"GMS-4-0112018-467_1527086274.jpg","derivation_code":"GMS-4-0112018-467","sample_description":"test 1 test is a test that test will be tested in test","latitude":"6.428152","longitude":"125.317857"},{"image":"GMS-1-0112018-963_1527134301.jpg","derivation_code":"GMS-1-0112018-963","sample_description":"nalaya lang","latitude":"7.311647","longitude":"125.636461"}],
selectedSample: [],
},
created: function(){
this.getMarkers();
},
mounted: function(){
this.map = new L.map('map', this.mapOptions);
this.map.addLayer(new L.TileLayer(this.map_link));
},
watch: {
markers: function(){
this.renderMarker();
}
},
methods: {
getMarkers: function (){
axios.get('http://127.0.0.1:8000/marker').then(response => {
this.markers = response.data;
console.log(this.markers);
}).catch(error =>( console.log(error) ));
console.log(this.markers);
},
renderMarker: function(){
for ( i = 0; i < this.markers.length; i++){
console.log(this.markers[i]);
var marker = new L.Marker([this.markers[i].latitude, this.markers[i].longitude], this.markerOption);
marker.addTo(this.map);
marker.bindPopup(`
<h6 class="display-6">${this.markers[i].derivation_code}</h6>
<img src="storage/images/${this.markers[i].image}" style="height:100%;width:100%">
`);
}
},
markerClicked: function(mrkr_data){
this.selectedSample = mrkr_data.derivation_code;
console.log(this.selectedSample);
}
},
});
I've created two components to send an image in base-64 encoded format to a server. When the parent component is mounted it's supposed to set the child reference to file.
Vue.component('some-form', {
template: '#some-form',
data: function() {
return {
logoImage: '',
coverImage: ''
}
},
methods: {
onSubmit: function(event) {
var dataForm = {};
var that = this;
dataForm['logo-image'] = this.logoImage;
dataForm['cover-image'] = this.coverImage;
// AJAX REQUEST HERE with posting data
},
},
mounted: function(){
var $this = this;
// AJAX REQUEST HERE with getting data
}
});
Vue.component('upload-photo', {
template: '#upload-photo',
data: function () {
return {
image: {
body: '',
'content-type': '',
'content-length': '',
url: ''
},
imageBody: ''
}
},
props: ['logoImage', 'title', 'description'],
watch: {
'image': function() {
this.$emit('input', this.image);
}
},
created: function(){
this.image = this.logoImage;
},
mounted: function () {
var that = this;
//AJAX REQUEST HERE to get data
},
methods: {
onFileChange: function(e) {
var files = e.target.files || e.dataTransfer.files;
if (!files.length)
return;
this.createImage(files[0]);
},
createImage: function(file){
var image = new Image();
var reader = new FileReader();
var vm = this;
vm.image = {};
reader.onload = function(e) {
vm.image.body = e.target.result;
vm.imageBody = e.target.result;
};
vm.$set(vm.image, 'content-type', file.type);
vm.$set(vm.image, 'content-length', file.size);
reader.readAsDataURL(file);
},
removeImage: function (e) {
this.image = '';
}
}
});
var app = new Vue({
el: '#app',
data: function() {
},
methods: {
},
mounted: function() {
}
});
Full example https://codepen.io/anon/pen/ZvzwzO
How can it be implemented?
P.S. I have no idea how to implement it in the same component. I send data as a string with two more property, however get as a string to, however it's link.
P.S.S. need just way to search.
It is difficult to tell exactly what you are asking but it sounds like you want to pass data from the parent component to the child. If you haven't already, read about Composing components and Dynamic Props for passing properties from a parent component to a child component.
One way to do this is to make the imageBody a property of the upload-photo component instead of part of the data.
props: ['logoImage', 'title', 'description', 'imageBody'],
Then have the parent supply a value for that property:
<upload-photo v-model="logoImage" title="TITLE 1" description="description_1" v-bind:image-body="imageBody">
Take a look at this phpfiddle. When the form is mounted, it sends an AJAX call back to the server to retrieve a URL, then sets the property on that first upload-photo child element to the URL sent back from the server in the AJAX response. Note that the upload-photo template was changed to show the image if imageBody is truthy instead of image.
Basically I want to initialize my vValidNombre field on my form by comparing two values, so It would be nice to use a method, something like this:
<script type="text/javascript">
var avatar = new Vue({
el: '#validaciones',
data: {
vNombre: $('input[name=nombre]').val(),
vValidNombre: validar(),
},
methods: {
validar: function(){
if ('true' == 'true') {
return = true;
}
else {
return false;
}
}
}
})
</script>
This code doesn't work, but is it possible to do something like that?
EDIT: I'm using Vue 2
Not really. When it is initialised, vValidNombre would be undefined. However, you can do something like this with the ready method:
var avatar = new Vue({
el: '#validaciones',
data: {
vNombre: $('input[name=nombre]').val(),
vValidNombre: null,
},
ready: function() {
this.vValidNombre = this.validar();
}
methods: {
validar: function(){
// do something here
// and return it
},
bindDom: function() {
}
},
})
I need to pass an arguments in methods using ajax axios.
var app = new Vue({
el: '#app',
data: {
urlAdmission:
admissions: [
{ name : 'asdf'},
{ name : 'sd'}
]
},
mounted: function(){
this.allAdmissions()
},
methods: {
allAdmissions: _.debounce( function(){
var app = this
axios.get('http://localhost/school/api/hello')
.then( function(response ){
app.admissions = response.data.admissions
})
.catch( function(error){
console.log(error)
})
})
}
});
As you can see in mounted I call the methods this.allAdmissions() I need to pass an argument so that I can reuse the function. For example this.allAdmissions('http://localhost/school/api/hello'). Then use it in axios.get('url'). Thanks
It looks like what you're trying to do is make a function that can accept a url and bind the results of the url to a variable value in your data. Here is how you might do that.
methods: {
allAdmissions: _.debounce(function(url, value){
axios.get(url)
.then(function(response){
this[value] = response.data.admissions
}.bind(this))
.catch(function(error){
console.log(error)
})
})
}
Then, if you call that method like this,
this.allAdmissions('http://localhost/school/api/admissions', "admissions")
allAdmissions will set the admissions property on your data to the result of your call. This works if you always want to use response.data.admissions because you hardcoded that. If you wanted that to be variable as well, you might pass in a third value like so
methods: {
getSomeData: _.debounce(function(url, value, responseValue){
axios.get(url)
.then(function(response){
this[value] = response.data[responseValue]
}.bind(this))
.catch(function(error){
console.log(error)
})
})
}
In case some will need multiple ajax request. Here is an example.
var app = new Vue({
el: '#app',
data: {
value: '',
admissions: [],
schoolyear: []
},
created: function(){
this.ajaxAll()
},
methods: {
ajaxAll: _.debounce( function(){
var app = this
var admissions = 'admissions'
var schoolYear = 'schoolyear'
axios.all([this.getAllData('http://localhost/school/api/admissions', 'admissions'), this.getAllData('http://localhost/school/api/schoolyear', 'schoolyear')]);
}),
getAllData: function(url, value){
var app = this
return axios.get(url)
.then(function(response){
app[value] = response.data[value]
console.log(response.data.admissions)
})
}
}
})
Credit to #Bert Evans.