function not defined upon requesting via axios in vue - vue.js

I am trying to make an axios call and it works fine but when I call the function from the scope it returns me
loadData is undefined.
import vSelect from 'vue-select';
export default {
props : [],
data : () => {
return {
assets : [],
folders : [],
parent_id : 0,
moveParentId : null,
selectedAsset: {},
parentStack : [],
searchTerm : '',
};
},
components: {
vSelect,
},
created() {
this.loadData(this.parent_id);
this.createFolder();
},
methods : {
loadData(parentId) {
axios
.get(
'/api/assets',
{
params: {
parent_id: parentId,
},
},
)
.then((response) => {
this.parentStack.push(parentId);
this.assets = response.data;
})
.catch((error) => {
if (error.response.status === vue.$options.HTTP_STATUS.UNPROCESSABLE_ENTITY) {
}
});
},
createFolder() {
$('#create-folder-button').on('click', function (e) {
let form = $('#create-folder').find('form'),
namefield = form.find('input#name'),
name = namefield.val(),
action = '/assets',
errorelem = form.find('#create-error');
axios
.post(action, {
name: name,
type: 1,
})
.then(() => {
$('#create-folder').modal('hide');
loadData(this.parent_id); //ERROR OCCURS HERE.
}, function (error) {
if (error.response != null) {
if (error.response.status == vue.$options.HTTP_STATUS.UNPROCESSABLE_ENTITY) {
errorelem.html(error.response.status).show();
}
}
});
});
}
this is my code.

Related

global store plugin error with vue 3 condition

With vue 3, I have state actions in different files globally, but they do not perform the necessary checks in the vue connector. I don't understand where I am doing wrong. I will be happy if you help.
I am waiting for your help to see the mistakes I have made. I am open to any comments.
app.js
require('./bootstrap');
import {createApp} from 'vue';
import App from './App.vue'
import WebsiteRouter from './Website/router';
import AdminRouter from './Admin/router';
import ApplicationRouter from './Application/router';
import store from './store';
axios.defaults.withCredentials = true;
store.dispatch('getUser').then(() => {
createApp(App)
.use(chanceRoute())
.use(store)
.use(DashboardPlugin)
.mount("#app");
})
import { createStore } from 'vuex'
import app from './app'
import appConfig from './app-config'
export default new createStore({
modules: {
app,
appConfig,
}
})
app\index.js
import axios from 'axios';
import sharedMutations from 'vuex-shared-mutations';
export default {
state: {
user: null
},
getters: {
user(state) {
return state.user;
},
verified(state) {
if (state.user) return state.user.email_verified_at
return null
},
id(state) {
if (state.user) return state.user.id
return null
}
},
mutations: {
setUser(state, payload) {
state.user = payload;
}
},
actions: {
async login({dispatch}, payload) {
try {
await axios.get('/sanctum/csrf-cookie');
await axios.post('/api/login', payload).then((res) => {
return dispatch('getUser');
}).catch((err) => {
throw err.response
});
} catch (e) {
throw e
}
},
async register({dispatch}, payload) {
try {
await axios.post('/api/register', payload).then((res) => {
return dispatch('login', {'email': payload.email, 'password': payload.password})
}).catch((err) => {
throw(err.response)
})
} catch (e) {
throw (e)
}
},
async logout({commit}) {
await axios.post('/api/logout').then((res) => {
commit('setUser', null);
}).catch((err) => {
})
},
async getUser({commit}) {
await axios.get('/api/user').then((res) => {
commit('setUser', res.data);
}).catch((err) => {
})
},
async profile({commit}, payload) {
await axios.patch('/api/profile', payload).then((res) => {
commit('setUser', res.data.user);
}).catch((err) => {
throw err.response
})
},
async password({commit}, payload) {
await axios.patch('/api/password', payload).then((res) => {
}).catch((err) => {
throw err.response
})
},
async verifyResend({dispatch}, payload) {
let res = await axios.post('/api/verify-resend', payload)
if (res.status != 200) throw res
return res
},
async verifyEmail({dispatch}, payload) {
let res = await axios.post('/api/verify-email/' + payload.id + '/' + payload.hash)
if (res.status != 200) throw res
dispatch('getUser')
return res
},
},
plugins: [sharedMutations({predicate: ['setUser']})],
}
app-config\index.js
import { $themeConfig } from '../../themeConfig'
export default {
namespaced: true,
state: {
layout: {
isRTL: $themeConfig.layout.isRTL,
skin: localStorage.getItem('skin') || $themeConfig.layout.skin,
routerTransition: $themeConfig.layout.routerTransition,
type: $themeConfig.layout.type,
contentWidth: $themeConfig.layout.contentWidth,
menu: {
hidden: $themeConfig.layout.menu.hidden,
},
navbar: {
type: $themeConfig.layout.navbar.type,
backgroundColor: $themeConfig.layout.navbar.backgroundColor,
},
footer: {
type: $themeConfig.layout.footer.type,
},
},
},
getters: {},
mutations: {
TOGGLE_RTL(state) {
state.layout.isRTL = !state.layout.isRTL
document.documentElement.setAttribute('dir', state.layout.isRTL ? 'rtl' : 'ltr')
},
UPDATE_SKIN(state, skin) {
state.layout.skin = skin
// Update value in localStorage
localStorage.setItem('skin', skin)
// Update DOM for dark-layout
if (skin === 'dark') document.body.classList.add('dark-layout')
else if (document.body.className.match('dark-layout')) document.body.classList.remove('dark-layout')
},
UPDATE_ROUTER_TRANSITION(state, val) {
state.layout.routerTransition = val
},
UPDATE_LAYOUT_TYPE(state, val) {
state.layout.type = val
},
UPDATE_CONTENT_WIDTH(state, val) {
state.layout.contentWidth = val
},
UPDATE_NAV_MENU_HIDDEN(state, val) {
state.layout.menu.hidden = val
},
UPDATE_NAVBAR_CONFIG(state, obj) {
Object.assign(state.layout.navbar, obj)
},
UPDATE_FOOTER_CONFIG(state, obj) {
Object.assign(state.layout.footer, obj)
},
},
actions: {},
}

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
})
}
},
}

Unable to call v-show and #click on same button with vue.js

I'm trying to display text on button based on data variable and call a function for vue.js axios method. I'm able to show text on button based on data variable but unable to call axios post method .I'm getting below error. When I click the button, url "http://localhost:8085/#/applicationtab/3" changes to http://localhost:8085/?#/applicationtab/3.
<span v-if="user.user_role_id ==results.desk_user_role_id">
<button small color="primary" style="width:400px;" #click="forward" v-show="forwardTo">{{ forwardTo }}</button><br>
<button small color="primary" style="width:400px;" #click="revert" v-show="revertTo">{{ revertTo }}</button>
</span>
data() {
return {
user: [],
roles: {
2: { name: 'Registration', next: 4, previous: 0 },
4: { name: 'Technical', next: 6, previous: 2 },
6: { name: 'Executive', next: 0, previous: 4 },
},
};
},
mounted() {
const currentuserUrl = 'api/profile';
VueAxios.get(currentuserUrl, {
headers: {
'X-Requested-With': 'XMLHttpRequest',
Authorization: `Bearer ${localStorage.getItem('token')}`,
},
}, {
timeout: 100000,
})
.then((response) => {
// debugger;
this.user = response.data;
// console.log(response.data);
// debugger;
});
computed: {
forwardTo() {
const { next } = this.roles[this.user.user_role_id];
return next ? `Forward to ${this.roles[next].name}` : false;
},
revertTo() {
const { previous } = this.roles[this.user.user_role_id];
return previous ? `Revert to ${this.roles[previous].name}` : false;
},
},
methods: {
forward() {
this.$refs.form.forward();
const url = `/api/registration/${this.$route.params.id}/forward`;
VueAxios.post(url, this.forward_message, {
headers: {
'X-Requested-With': 'XMLHttpRequest',
Authorization: `Bearer ${window.localStorage.getItem('token')}`,
},
}, {
timeout: 10000,
})
.then((response) => {
if (response.status === 200) {
// this.successmessage = 'Forwarded successfully.';
this.message = 'Forwarded successfully.';
}
})
.catch((error) => {
console.log(error);
});
},
revert() {
const url = `/api/registration/${this.$route.params.id}/revert`;
VueAxios.post(url, this.forward_message, {
headers: {
'X-Requested-With': 'XMLHttpRequest',
Authorization: `Bearer ${window.localStorage.getItem('token')}`,
},
}, {
timeout: 10000,
})
.then((response) => {
if (response.status === 200) {
// this.successmessage = 'Forwarded successfully.';
this.message = 'Reverted successfully.';
}
})
.catch((error) => {
console.log(error);
});
},
computed: {
forwardTo() {
const { next } = this.roles[this.user.user_role_id];
return next ? `Forward to ${this.roles[next].name}` : false;
},
Error is ocurring because of this part I think. this.roles[next]
I can't find roles property on your properties(data and computed)
Is this a prop from parent component?
You need to check if the roles property or props and its child property next exist.
this.user is an array or object? If it is an array containing an single object then, you must try this.user[0].user_role_id, or if it is an object so there may be a user id which is not present as a key in the roles object.
For that you can use this in your computed property.
forwardTo() {
const tempObj = this.roles[this.user.user_role_id];
return tempObj ? `Forward to ${this.roles[tempObj.next].name}` : false;
}

Computed property "main_image" was assigned to but it has no setter

How can I fix this error "Computed property "main_image" was assigned to but it has no setter"?
I'm trying to switch main_image every 5s (random). This is my code, check created method and setInterval.
<template>
<div class="main-image">
<img v-bind:src="main_image">
</div>
<div class="image-list>
<div v-for="img in images" class="item"><img src="img.image"></div>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'Item',
data () {
return {
item: [],
images: [],
}
},
methods: {
fetchImages() {
axios.get(`/api/item/${this.$route.params.id}/${this.$route.params.attribute}/images/`)
.then(response => {
this.images = response.data
})
.catch(e => {
this.images = []
this.errors.push(e)
})
},
},
computed: {
main_image() {
if (typeof this.item[this.$route.params.attribute] !== 'undefined') {
return this.item[this.$route.params.attribute].image_url
}
},
},
watch: {
'$route' (to, from) {
this.fetchImages()
}
},
created () {
axios.get(`/api/item/${this.$route.params.id}/`)
.then(response => {
this.item = response.data
})
.catch(e => {
this.errors.push(e)
})
this.fetchImages();
self = this
setInterval(function(){
self.main_image = self.images[Math.floor(Math.random()*self.images.length)].image;
}, 5000);
},
}
</script>
Looks like you want the following to happen...
main_image is initially null / undefined
After the request to /api/item/${this.$route.params.id}/ completes, it should be this.item[this.$route.params.attribute].image_url (if it exists)
After the request to /api/item/${this.$route.params.id}/${this.$route.params.attribute}/images/ completes, it should randomly pick one of the response images every 5 seconds.
I'd forget about using a computed property as that is clearly not what you want. Instead, try this
data() {
return {
item: [],
images: [],
main_image: '',
intervalId: null
}
},
methods: {
fetchImages() {
return axios.get(...)...
}
},
created () {
axios.get(`/api/item/${this.$route.params.id}/`).then(res => {
this.item = res.data
this.main_image = this.item[this.$route.params.attribute] && this.item[this.$route.params.attribute].image_url
this.fetchImages().then(() => {
this.intervalId = setInterval(() => {
this.main_image = this.images[Math.floor(Math.random()*this.images.length)].image;
})
})
}).catch(...)
},
beforeDestroy () {
clearInterval(this.intervalId) // very important
}
You have to add setter and getter for your computed proterty.
computed: {
main_image: {
get() {
return typeof this.item[this.$route.params.attribute] !== 'undefined' && this.item[this.$route.params.attribute].image_url
},
set(newValue) {
return newValue;
},
},
},

pass computed property as method parameter?

So I have a store with values:
export const store = new Vuex.Store({
state: {
selectedGradeId: null,
},
getters:{
selectedGradeId: state => {
return state.selectedGradeId
},
},
mutations:{
SET_SELECTED_GRADE_ID(state, gradeid){
state.selectedGradeId = gradeid
},
CLEAR_SELECTED_GRADE_ID(state){
state.selectedGradeId = null
},
},
actions:{
loadStudentsForGrade (gradeId) {
return new Promise((resolve, reject) => {
axios.get('/students/'+gradeId)
.then((response)=>{
... do stuff
resolve(response)
}, response => {
reject(response)
})
})
},
}
})
and inside my component i basically have a select that loads the student list for the particular grade:
<select id="grades" name="grades" v-model="selectedGradeId" #change="loadStudentsForGrade(selectedGradeId)"
methods: {
loadStudentsForGrade(gradeId) {
this.$store.dispatch('loadStudentsForGrade', {gradeId})
.then(response => {
}, error => {
})
},
},
computed: {
selectedGradeId: {
get: function () {
return this.$store.getters.selectedGradeId;
},
set: function (gradeId) {
this.$store.commit('SET_SELECTED_GRADE_ID', gradeId);
}
},
}
when the 'loadStudentsForGrade' method is called in my component, it takes 'selectedGradeId' as a parameter, which is a computed property.
Now the problem I have is that inside my store, the action 'loadStudentsForGrade' gets an object( i guess computed?) instead of just the gradeid
object i get is printed to console:
{dispatch: ƒ, commit: ƒ, getters: {…}, state: {…}, rootGetters: {…}, …}
The first parameter of your action is the store, and the second the payload.
so you should do :
actions:{
// here: loadStudentsForGrade (store, payload) {
loadStudentsForGrade ({ commit }, { gradeId }) {
return new Promise((resolve, reject) => {
axios.get('/students/'+gradeId)
.then((response)=>{
//... do stuff
//... commit('', response);
resolve(response)
}, response => {
//... commit('', response);
reject(response)
})
})
},
}
Related page in the docs :
https://vuex.vuejs.org/en/actions.html#dispatching-actions