vue updating data on create() - vue.js

I am trying to update an array from my view data() inside my created hook() but my console says that the allFish is undefined. I'm not so great with vue data scoping yet and I was hoping someone could let me know if this is a diction issue, or if there's a better way to update my data on create() when receiving data from a get request and then adding it to an array inside my data.
my current app.vue
export default {
name: "App",
components: {
WebMap
},
data: () => ({
coords: {
latitude: -118,
longitude: 34,
},
date: '',
fishType: '',
allFish: []
}),
created(){
this.allFish = this.fetchFishLocations()
},
methods: {
fetchFishLocations(){
axios.get('http://localhost:3000/allFish')
.then(function (response) {
// handle success
console.log(response.data.fish);
return response.data.fish
})
.catch(function (error) {
// handle error
console.log(error);
})
},
async updateCenter() {
console.log(this.allFish) //check to see if allFish is defined
await this.getLocation();
this.addFishToDb()
},
},
};

The function which is called fetchFishLocations just returns undefined.
You'd better learn about the use of promise.
By the way, it's easier to use the arrow function
// solution 1
created(){
this.fetchFishLocations()
},
methods: {
fetchFishLocations(){
const that = this
axios.get('http://localhost:3000/allFish')
.then(function (response) {
// handle success
console.log(response.data.fish);
that.allFish = response.data.fish
})
.catch(function (error) {
// handle error
console.log(error);
})
}
}
// solution 2
created(){
const that = this
this.fetchFishLocations()
.then(function (response) {
// handle success
console.log(response.data.fish);
that.allFish = response.data.fish
})
.catch(function (error) {
// handle error
console.log(error);
})
},
methods: {
fetchFishLocations(){
return axios.get('http://localhost:3000/allFish')
}
}

You need fill allFish in axios->then method.
...
created() {
this.fetchFishLocations();
},
methods: {
fetchFishLocations(){
axios.get('http://localhost:3000/allFish')
.then(function (response) {
// handle success
console.log(response.data.fish);
this.allFish = response.data.fish;
})
.catch(function (error) {
// handle error
console.log(error);
})
},
}
...

Related

How can I update the comments without refreshing it?

First, I'm using vuex and axios.
store: commentService.js
components:
CommentBox.vue (Top components)
CommentEnter.vue (Sub components)
This is the logic of the code I wrote.
In the store called commentService.js, there are mutations called commentUpdate.
And There are actions called postComment and getComment.
At this time, In the component called CommentBox dispatches getComment with async created().
Then, in getComment, commentUpdate is commited and executed.
CommentUpdate creates an array of comments inquired by getComment and stores them in a state called commentList.
Then I'll get a commentList with "computed".
CommentEnter, a sub-component, uses the commentList registered as compounded in the CommentBox as a prop.
The code below is commentService.js.
import axios from 'axios'
export default {
namespaced: true,
state: () => ({
comment:'',
commentList: []
}),
mutations: {
commentUpdate(state, payload) {
Object.keys(payload).forEach(key => {
state[key] = payload[key]
})
}
},
actions: {
postComment(state, payload) {
const {id} = payload
axios.post(`http://??.???.???.???:????/api/books/${id}/comments`, {
comment: this.state.comment,
starRate: this.state.starRate
}, {
headers: {
Authorization: `Bearer ` + localStorage.getItem('user-token')
}
})
.then((res) => {
console.log(res)
this.state.comment = ''
this.state.starRate = ''
)
.catch((err) => {
alert('댓글은 한 책당 한 번만 작성할 수 있습니다.')
console.log(err)
this.state.comment = ''
this.state.starRate = ''
})
},
async getComment({commit}, payload) {
const {id} = payload
axios.get(`http://??.???.???.???:????/api/books/${id}/comments`)
.then((res) => {
console.log(res)
const { comment } = res.data.commentMap
commit('commentUpdate', {
commentList: comment
})
})
.catch((err) => {
console.log(err)
commit('commentUpdate', {
commentList: {}
})
})
}
}
}
The code below is CommentBox.vue
computed: {
commentList() {
return this.$store.state.commentService.commentList
}
},
methods: {
async newComment() {
if(this.$store.state.loginService.UserInfoObj.id === '') {
alert('로그인 후 이용할 수 있습니다.')
return
}
this.$store.dispatch('commentService/postComment', {
id: this.$route.params.id,
comment: this.$store.state.comment,
starRate: this.$store.state.starRate
})
}
},
async created() {
this.$store.dispatch('commentService/getComment', {
id: this.$route.params.id
})
}
The code below is CommentEnter.vue
created() {
this.userComment = this.comment
},
props: {
comment: {
type: Object,
default: () => {}
}
},
I asked for a lot of advice.
There were many comments asking for an axios get request after the axios post request was successful.
In fact, I requested an axios get within .then() of the axios post, and the network tab confirmed that the get request occurred normally after the post request.
But it's still not seen immediately when I register a new comment.
I can only see new comments when I refresh it.
How can I make a new comment appear on the screen right away when I register it?
Can't you just call getComment when postComment is finished?
methods: {
async newComment() {
if(this.$store.state.loginService.UserInfoObj.id === '') {
alert('로그인 후 이용할 수 있습니다.')
return
}
this.$store.dispatch('commentService/postComment', {
id: this.$route.params.id,
comment: this.$store.state.comment,
starRate: this.$store.state.starRate
}).then(function() {
this.$store.dispatch('commentService/getComment', {
id: this.$route.params.id
})
})
}
},
}
Or since you're using async:
methods: {
async newComment() {
if(this.$store.state.loginService.UserInfoObj.id === '') {
alert('로그인 후 이용할 수 있습니다.')
return
}
await this.$store.dispatch('commentService/postComment', {
id: this.$route.params.id,
comment: this.$store.state.comment,
starRate: this.$store.state.starRate
})
this.$store.dispatch('commentService/getComment', {
id: this.$route.params.id
})
}
},
}

Vuex update state by using store actions

I have two functions in my store, one that gets data by calling API and one that toggles change on cell "approved". Everything working fine, except that when I toggle this change it happens in database and I get the response that it is done but It doesn't update on UI.
I am confused, what should I do after toggling change to reflect change on UI, should I call my API from .then or should I call action method responsible for getting data from server.
export default {
state: {
drivers: {
allDrivers:[],
driversError:null
},
isLoading: false,
token: localStorage.getItem('token'),
driverApproved: null,
driverNotApproved: null
},
getters: {
driversAreLoading (state) {
return state.isLoading;
},
driverError (state) {
return state.drivers.driversError;
},
getAllDrivers(state){
return state.drivers.allDrivers
}
},
mutations: {
getAllDrivers (state) {
state.isLoading=true;
state.drivers.driversError=null;
},
allDriversAvailable(state,payload){
state.isLoading=false;
state.drivers.allDrivers=payload;
},
allDriversNotAvailable(state,payload){
state.isLoading=false;
state.drivers.driversError=payload;
},
toggleDriverApproval(state){
state.isLoading = true;
},
driverApprovalCompleted(state){
state.isLoading = false;
state.driverApproved = true;
},
driverApprovalError(state){
state.isLoading = false;
state.driverError = true;
}
},
actions: {
allDrivers (context) {
context.commit("getAllDrivers")
return new Promise((res,rej)=>{
http.get('/api/admin/getAllDrivers').then(
response=>{
if (response.data.success){
let data=response.data.data;
data=data.map(function (driver) {
return {
/* response */
};
});
context.commit("allDriversAvailable",data);
res();
}else {
context.commit("allDriversNotAvailable",response.data)
rej()
}
})
.catch(error=>{
context.commit("allDriversNotAvailable",error.data)
rej()
});
});
},
toggleDriverApproval (context, payload){
return new Promise((res, rej)=>{
http.post("/api/admin/toggleDriverApproval",{
driver_id: payload
})
.then( response => {
context.commit('driverApprovalCompleted');
res();
}).catch( error =>{
context.commit('driverApprovalError');
rej()
})
})
}
}
}
and here is the code on the view, I wrote the necessary code for better clarification of the problem
export default {
name: 'Drivers',
data: () => ({
data: [],
allDrivers: [],
driversErrors: []
}),
created() {
this.$store
.dispatch('allDrivers')
.then(() => {
this.data = this.$store.getters.getAllDrivers
})
.catch(() => {
this.errors = this.$store.getters.driverError
})
},
computed: {
isLoading() {
return this.$store.getters.driversAreLoading
}
},
methods: {
verify: function(row) {
console.log(row)
this.$store.dispatch('toggleDriverApproval', row.id).then(() => {
this.data = this.$store.getters.getAllDrivers
console.log('done dis')
})
},
},
}
if I understand your issue, you want the UI displaying your data to change to the updated data after making a post request.
If you are using Vuex you will want to commit a mutation, and use a getter display the data.
I am not sure how your post request is being handled on the server but if successful typically you would send a response back to your front end with the updated data, and commit a mutation with the updated data.
Example:
Make a Post request
toggleDriverApproval (context, payload){
return new Promise((res, rej)=>{
http.post("/api/admin/toggleDriverApproval",{
driver_id: payload
})
.then( response => {
context.commit('driverApprovalCompleted', response.data);
res();
}).catch( error =>{
context.commit('driverApprovalError', error.response.data);
rej()
})
})
}
If succesful commit the mutation
.then( response => {
context.commit('driverApprovalCompleted', response.data);
res();
})
response.data being your data you want to mutate the state with.
Mutation Example:
customMutation(state, data) {
state.driverApproval = data
}
Getter Example:
driver(state) {
return state.driverApproval
}
displaying the getter in a template
<template>
<div v-if="driver">{{driver}}</div>
</template>
<script>
import {mapGetters} from 'vuex'
export default {
name: Example,
computed: {
driver() {
return this.$store.getters.driver
},
// or use mapGetters
...mapGetters(['driver'])
}
}
</script>
more examples can be found at Vuex Docs

How to set a value inside a variable on data() using a function?

I'm creating a Vue.js component inside a Laravel App.
After I catch the response with an axios request, I can't put a value inside a variable on method data()
Here is the code:
app.js
require('./bootstrap')
window.Vue = require('vue')
Vue.component('card', require('./components/card.vue'))
let app = new Vue({
el: '#app'
})
card.vue
<script>
module.exports = {
props: [
'name'
],
data: function() {
return {
projects: [],
}
},
mounted() {
this.getProjects() // NOT WORK?
},
methods: {
getProjects: function() {
axios.get('/api/v1/getProjects').then(function (response) {
console.log(response.data)
this.projects = response.data // NOT WORK
}).catch(function (error) {
console.log(error)
}).then(function () {
})
},
}
}
</script>
It's because of using this in response callback. You should use an arrow function (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) or save the context in separate variable.
Try to add .bind(this) or replace function with =>:
getProjects: function() {
axios.get('/api/v1/getProjects').then((response) => {
console.log(response.data)
this.projects = response.data // NOT WORK
}).catch((error) => {
console.log(error)
}).then(function () {
})
},

aixos reponse data can not assign to Vue instance's data

In my vue.js project, i get an array data by axios, and want to assign to bookList variable, but failed, bookList still equal to [], could you tell me why?
export default {
...
data () {
return {
bookList: []
}
},
mounted: function() {
this.$nextTick(function(){
this.viewBooks();
});
},
methods: {
viewBooks: function() {
axios.get('/books.json')
.then(res=>{
this.bookList = res.data.bookList;
})
.catch(error=>{
console.log(error);
});
}
}
The callback is on a different scope...this should work
methods: {
viewBooks: function() {
let self = this;
axios.get('/books.json')
.then(res=>{
self.bookList = res.data.bookList;
})
.catch(error=>{
console.log(error);
});
}
There's also a different answer here

how to reference itself in a component in vuejs single file component

So here is my code:
export default {
data(){
return {
list: {}
}
},
components: {
listFields : ListFields
},
methods : {
submitForm(data){
let vm = this;
console.log(vm);
axios.post('/api/dashboard/lists/create', data)
.then(function (response) {
this.$router.push({path: 'show-list', params: {list_id: response.data.id}});
}).catch(function (error) {
console.log(error);
})
}
}
}
the problem is that inside the method where I am calling "this.$router.push" it throws an error, because this references to the function. But the problem is that I can't reference vm, because I am exporting the component. How can I solve this problem?
Your callback function is not aware of the outer context.
Either use .bind(this) or declare var that = this;
axios.post('/api/dashboard/lists/create', data)
.then(function (response) {
this.$router.push({path: 'show-list', params: {list_id: response.data.id}});
}.bind(this)).catch(function (error) {
console.log(error);
})
or
var that = this;
axios.post('/api/dashboard/lists/create', data)
.then(function (response) {
that.$router.push({path: 'show-list', params: {list_id: response.data.id}});
}).catch(function (error) {
console.log(error);
})
Update:
Since somehow nothing seems to work you can try the following: Declare a seperate method for the callback
methods : {
submitForm(data){
axios.post('/api/dashboard/lists/create', data)
.then(this.onSuccess)
.catch(function (error) {
console.log(error);
})
},
onSuccess(response) {
this.$router.push({path: 'show-list', params: {list_id: response.data.id}});
}
}