Reputation: 379
I'm a new VueJS user, currently struggling with updating image src on the fly. This is what I've got:
Template:
<div v-for="place in places">
<img
v-bind:src="isPlacePrivate(place.data.place_is_private)"
v-on:click="setPlaceAsPrivate(place.data.place_is_private, place.data.place_id)"
>
</div>
<script>
export default {
data: function () {
return {
places: null,
}
},
mounted () {
this.username = this.$route.params.username;
axios.get('/api/' + this.username + '/places')
.then(response => {
this.places = response.data.data;
})
.catch(error => {
// show error
});
},
methods: {
isPlacePrivate: function (value) {
// If Place is private
if (value == 1) {
var src = '/icons/padlock-color.png'
} else {
var src = '/icons/padlock.png'
}
return src;
},
setPlaceAsPrivate: function (value, placeId) {
let data = {
isPrivate: value
};
axios.put('/api/' + this.username + '/places/' + placeId + '/edit', data)
.then(response => {
let newValue = response.data.data.private;
this.isPlacePrivate(newValue);
})
.catch(error => {
// show error
});
},
},
}
</script>
On a page load -> if a particular place is private it will show colored padlock icon or uncolored padlock if a place is public!
A user will be able to press on the padlock icon and change the value from public->private or private->public.
Everything is working fine but the padlock image is not updating on the fly when a user is clicking on it, I need to refresh a page to see changes! How to make it work?
Upvotes: 1
Views: 1855
Reputation: 1114
I would suggest using a computed property so that it is reactive
Also according to your updates you are looping through an array of places so when you get your response from your axios call instead of just updating the icon I would try replacing the object in the array so I created the method called updatePlace()
and I pass in the response object.
And change your places in the v-for to a computed property as well so that it is also reactive
Template:
<div v-for="place in placesArray" :key="index" v-if="places">
<img
v-bind:src="imgSrc"
v-on:click="setPlaceAsPrivate(place.data.place_is_private, place.data.place_id)"
v-if="imgSrc"
>
</div>
Script:
<script>
export default {
data() {
return {
src: '',
places: null
}
},
computed: {
imgSrc() {
return this.src
},
placesArray() {
return this.places
}
},
Methods: {
isPlacePrivate: function (value) {
// If Place is private
if (value == 1) {
this.src = '/icons/padlock-color.png'
} else {
this.src = '/icons/padlock.png'
}
},
setPlaceAsPrivate: function (value, placeId) {
let data = {
isPrivate: value
};
axios.put('/api/' + this.username + '/places/' + placeId + '/edit', data)
.then(response => {
console.log(response);
let newValue = response.data.data;
this.updatePlace(newValue);
})
.catch(error => {
console.log(error);
});
},
},
updatePlace(newPlace) {
const index = this.places.findIndex(place => place.id === newPlace.id)
this.places.splice(index, 1, place)
},
created() {
this.username = this.$route.params.username;
axios.get('/api/' + this.username + '/places')
.then(response => {
this.places = response.data.data;
})
.catch(error => {
// show error
});
}
}
</script>
Also make sure to move your mounted
method to a created()
method so that it is called before anything else is trying to render.
Upvotes: 1
Reputation: 201
Apparently the problem is that you are calling the function and printing its return on the <img v-bind:src>
, the isPlacePrivate
function returns a value, so when you use this function within the setPlaceAsPrivate
it returns the value only in scope of setPlaceAsPrivate
.
The isPlacePrivate
function does not modify any data
value of the component, so the image always remains the same. You just need to set a data
and manipulate its value in the isPlacePrivate
function.
Template
<img
v-bind:src="bindSrc"
v-on:click="setPlaceAsPrivate(place.data.place_is_private, place.data.place_id)"
>
Script
<script>
export default {
data() {
return {
bindSrc: '/icons/padlock-color.png', // default img src value
... // your other values
}
},
Methods: {
isPlacePrivate: function (value) {
// If Place is private
if (value == 1) {
this.bindSrc = '/icons/padlock-color.png'
} else {
this.bindSrc = '/icons/padlock.png'
}
},
setPlaceAsPrivate: function (value, placeId) {
let data = {
isPrivate: value
};
axios.put('/api/' + this.username + '/places/' + placeId + '/edit', data)
.then(response => {
console.log(response);
let newValue = response.data.data.private;
this.isPlacePrivate(newValue);
})
.catch(error => {
console.log(error);
});
},
}
}
</script>
Upvotes: 1