I have a simple file upload component FileUpload.vue
<template>
<div>
<input type="file" name="file" id="file" v-on:change="handleFileUpload()" ref="file">
<button class="btn shadow-lg first" #click="addFiles()">SELECT FILE</button>
<button class="btn shadow-lg" v-on:click="handleSubmit()">UPLOAD</button>
<p> {{uploadPercentage}} </p>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'FileUpload',
data() {
return {
file: '',
uploadPercentage: 0
}
},
methods: {
handleFileUpload: () => {
this.file = document.getElementById('file').files[0];
},
addFiles: () => {
document.getElementById('file').click();
},
handleSubmit: () => {
let formData = new FormData();
formData.append('file', this.file);
axios.post('/file/create',
formData,
{
headers: {
'Content-Type': 'multipart/form-data'
},
onUploadProgress: (progressEvent) => {
console.log(this.uploadPercentage);
this.uploadPercentage = parseInt(Math.round(progressEvent.loaded * 100 / progressEvent.total));
}
}
)
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.log(error);
})
}
}
}
</script>
The data uploadPercentage is initialized to 0. As the file upload starts, the uploadPercentage value changes in the onUploadProgress method.
If I console log uploadPercentage, it shows the changes in the value. It goes from 0 to 100.
console.log(this.uploadPercentage)
But in my view, uploadPercentage never changes. It always shows the initial value 0.
<p> {{uploadPercentage}} </p>
What am I doing wrong?
Thanks in advance.
Related
I'm a newbie in VueX. I face a problem which is after I updated the profile information and save it successfully, the database has shown the latest updated info but the user interfaces cannot retrieve the latest data. The state seems no updated.
My profile UI
https://i.stack.imgur.com/8QtI9.png
but after updated, all the info disappear and didn't show the latest info
https://i.stack.imgur.com/ul1ob.png
UserProfile.vue
<template>
<div class="container" style="padding-top:25px">
<div class="main-font">My Profile</div>
<div class="d-flex row">
<div class="col-6">
<ValidationObserver v-slot="{ handleSubmit }">
<form #submit.prevent="handleSubmit(updateProfile)">
<div class="d-flex py-4">
<div>
<img class="profile" src="/img/default.png" alt=""
</div>
<div class="my-auto ml-5">
<button type="submit" class="btn upload text"><i class="fas fa-upload fa-sm pr-2"></i>Upload new picture</button>
</div>
</div>
<div class="form-group col-10 p-0 m-0">
<ValidationProvider name="Name" rules="required|alpha" v-slot="{ errors }">
<label class="text">Name</label>
<input type="text" id="name" class="form-control form-text" placeholder="Enter your username" v-model="userForm.name">
<span class="error-messsage">{{ errors[0] }}</span>
</ValidationProvider>
<!-- <small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone else.</small> -->
</div>
<div class="form-group col-10 p-0 m-0 mt-4">
<ValidationProvider name="E-mail" rules="required|email" v-slot="{ errors }">
<label class="text">Email</label>
<input type="email" id="email" class="form-control form-text" placeholder="Enter email" v-model="userForm.email">
<span class="error-messsage">{{ errors[0] }}</span>
</ValidationProvider>
</div>
<button type="submit" class="btn col-10 p-o save-but">SAVE CHANGES</button>
</form>
</ValidationObserver>
</div>
<div class="w-50">
<img class="bg-img" src="/img/profile-bg.png" alt="">
</div>
</div>
</div>
script
<script>
import { ValidationProvider, ValidationObserver, extend } from 'vee-validate/dist/vee-validate.full';
export default {
components: {
ValidationProvider,
ValidationObserver,
},
data() {
return {
userForm: {
name: '',
email: '',
},
error: null,
}
},
created () {
this.userForm = JSON.parse(JSON.stringify(this.$store.getters.currentUser));
},
computed: {
currentUser(){
return this.$store.getters.currentUser;
},
},
methods: {
getUser (){
const token = this.$store.getters.currentUser.token
axios.get('/api/auth/userprofile',{
headers: {
Authorization: `Bearer ${token}`
}
})
.then(response => {
this.userForm= response.data.user;
})
},
updateProfile () {
const token = this.$store.getters.currentUser.token
// console.log(this.$store.getters.currentUser.token)
axios.put('/api/auth/update-profile',
{
name: this.userForm.name,
email: this.userForm.email,
},
{
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json" // add content-type
}
})
.then(response => {
this.userForm.name = response.data.name;
this.userForm.email = response.data.email;
swal({
icon: "success",
text: "Update Succesfully!",
});
// this.$store.commit('update');
})
}
}
}
</script>
store.js
import {getLoggedinUser} from './auth';
import {getUser} from './auth';
const user = getLoggedinUser();
const updateUser = getUser();
export default {
state: {
currentUser: user,
isLoggedin: !!user,
loading: false,
auth_error: null,
reg_error:null,
registeredUser: null,
update: null,
},
getters: {
isLoading(state){
return state.loading;
},
isLoggedin(state){
return state.isLoggedin;
},
currentUser(state){
return state.currentUser;
},
authError(state){
return state.auth_error;
},
regError(state){
return state.reg_error;
},
registeredUser(state){
return state.registeredUser;
},
update(state){
return state.update;
}
},
mutations: {
login(state){
state.loading = true;
state.auth_error = null;
},
loginSuccess(state, payload){
state.auth_error = null;
state.isLoggedin = true;
state.loading = false;
state.currentUser = Object.assign({}, payload.user , {token: payload.access_token});
localStorage.setItem("user", JSON.stringify(state.currentUser));
},
loginFailed(state, payload){
state.loading = false;
state.auth_error = payload.error;
},
logout(state){
localStorage.removeItem("user");
state.isLoggedin = false;
state.currentUser = null;
},
registerSuccess(state, payload){
state.reg_error = null;
state.registeredUser = payload.user;
},
registerFailed(state, payload){
state.reg_error = payload.error;
},
update(state, payload) {
state.currentUser = payload.data;
}
},
actions: {
login(context){
context.commit("login");
},
// update(context){
// // state.currentUser.update(context);
// }
}
};
auth.js
export function registerUser(credentials){
return new Promise((res,rej)=>{
axios.post('/api/auth/register', credentials)
.then(response => {
res(response.data);
})
.catch(err => {
rej('An error occured.. try again later.')
})
})
}
export function login(credentials){
return new Promise((res,rej)=>{
axios.post('/api/auth/login', credentials)
.then(response => {
setAuthorization(response.data.access_token);
res(response.data);
})
.catch(err => {
rej('Wrong Email/Password combination.')
})
})
}
export function getLoggedinUser(){
const userStr = localStorage.getItem('user');
if(!userStr){
return null
}
return JSON.parse(userStr);
}
export function getUser(credentials){
return new Promise((res,rej)=>{
axios.get('/api/auth/userprofile', credentials)
.then(response => {
// setAuthorization(response.data.access_token);
res(response.data);
})
.catch(err => {
rej('No User')
})
})
}
Please help me if you have any ideas or solution.
You're not running any dispatches of your store.
You have defined update mutation, but commented it.
Uncomment this
// this.$store.commit('update')
and modify it like so:
this.$store.commit('update', { data: response.data })
Next do the same for your login request.
When the client clicks on the button, I want him to block another client, so I want my id to be dynamic: http://example/user/:id.
My template:
<template>
<div class>
<div v-for="post in posts" :key="post.id">
<div>
<div>{{ post.name }}</div>
<div>{{ post.id }}</div>
<button #click='BlockUser'>Block</button>
</div>
</div>
</div>
</template>
And my script:
<script>
const axios = require('axios');
export default {
name: 'User',
data() {
return {
posts: [],
errors: [],
id: {
id: ""
},
}
},
methods: {
getData() {
axios.get(`http://example/user`)
.then(result => {
this.posts = result.data
console.log(result)
})
},
BlockUser() {
axios.get('http://example/user/blacklist/:id' + encodeURIComponent(this.id.id))
.then(response => {
console.log(response)
})
},
},
}
</script>
Initially, I set a value for the id in data id a number and it worked. But now that I put an empty string.
it returns an undefined
If your posts have user_id field inside, you can pass it to BlockUser method, and use it in the request url.
<button #click='BlockUser(post.user_id)'>Block</button>
BlockUser(user_id) {
axios.get(`http://example/user/blacklist/${user_id}`)
.then(response => {
console.log(response)
})
},
<template>
<div class="comment">
<div v-for="(comment, index) in comments" :key="index">
{{ getUser(comment.student_idx) }}
</div>
</div>
</template>
<script>
import axios from 'axios'
import server from '#/models/server'
export default {
data() {
return {
url: server,
comments: {}
}
},
props: ['idx'],
created() {
axios.get(`${this.url}/bamboo/reply?post=${this.idx}`)
.then(response => {
if (response.data.status === 200) {
this.comments = response.data.data.replies
}
})
},
methods: {
getUser (idx) {
axios.get(`${this.url}/member/student/${idx}`)
.then(response => {
if (response.data.status === 200) {
return response.data.data.member.name
}
})
}
}
}
</script>
I would like to load the comments at created and print them out using v-for.
In v-for, I would like to load the member.name from each comment
But {{ getUser(comment.student_idx) }} is undefined.
I don't know how to return data from axios
Help me please!!
Your method should not be async for stable run code. My recomendation is next code:
<template>
<div class="comment">
<div v-for="(comment, index) in comments" :key="index">
{{ comments['user'] }}
</div>
</div>
</template>
<script>
import axios from 'axios'
import server from '#/models/server'
export default {
data() {
return {
url: server,
comments: []
}
},
props: ['idx'],
created() {
axios.get(`${this.url}/bamboo/reply?post=${this.idx}`)
.then(response => {
if (response.data.status === 200) {
this.comments = response.data.data.replies;
if(this.comments)
for(let comment of this.comments){
this.getUser(comment, comment.student_idx);
}
}
})
},
methods: {
getUser (comment, idx) {
axios.get(`${this.url}/member/student/${idx}`)
.then(response => {
if (response.data.status === 200) {
this.$set(comment, 'user', response.data.data.member.name);
}
})
}
}
}
</script>
I have a parent component:
<template>
<div class="w-full">
<div class="card-body">
<city-edit-form :form="form" :resource="resource" #save_resource="func">
</city-edit-form>
</div>
</div>
</template>
<script>
export default {
methods: {
func() {
console.log("test");
}
}
};
</script>
And child component:
<template>
<div>
<form action="#" method="POST" #submit.prevent="submit" v-else>
<button type="submit" class="btn-green">Save</button>
</form>
</div>
</template>
<script>
import { UPDATE_RESOURCE } from "../../../Stores/action-types";
export default {
props: {
form: { required: true },
resource: { required: true }
},
methods: {
submit() {
this.$store
.dispatch(`city/${UPDATE_RESOURCE}`, this.form)
.then(() => this.$emit("save_resource"));
}
}
};
</script>
And action is:
[UPDATE_RESOURCE]({ commit, state }, form) {
commit(SET_LOADING, true);
return ResourceService.update(state.resource.id, form)
.then(({ data }) => {
commit(SET_RESOURCE, data);
})
.catch(errors => {
commit(SET_ERRORS, errors.response.data);
})
.finally(() => commit(SET_LOADING, false));
});
},
When I submit form, action has been dispatched, but nothing emitted.
Nothing logged in console. Where I make mistake?
update
When I check Vue toolbar's Event tab, I see this:
I think event has been emmitted, but console.log logs nothing in console! So wired!
Use return keyword while resolve or reject is triggered
[UPDATE_RESOURCE]({ commit, state }, form) {
commit(SET_LOADING, true);
return new Promise((resolve, reject) => {
ResourceService.update(state.resource.id, form)
.then(({ data }) => {
commit(SET_RESOURCE, data);
return resolve();
})
.catch(errors => {
commit(SET_ERRORS, errors.response.data);
return reject();
})
.finally(() => commit(SET_LOADING, false));
});
},
instead of emitting events (nothing wrong with that) you could use mapGetters
<template>
<div class="w-full">
<div class="card-body">
<city-edit-form :form="form" :resource="myResource">
</city-edit-form>
</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters({
myResource: 'Stores/action-types/SET_RESOURCE', <---- needs to be modified
}),
}
};
</script>
this is assuming you have made any getters
I have vue SPA and I trying to upload some images and text. I try using postman to test my server code and it's work, but my client-side still error.
I think I'm still mistaken for handle req.file.
addImage.vue
<template>
<div>
<b-form-group label-cols-sm="3" description="image title" label="Title">
<b-form-input v-model="newImage.title"></b-form-input>
</b-form-group>
<b-form-group label="my Image" label-for="file" label-cols-sm="2">
<b-form-file id="file" v-model="newImage.image"></b-form-file>
</b-form-group>
<b-button variant="primary" class="pl-5 pr-5" #click.prevent="addImage">Save</b-button>
</div>
</template>
<script>
export default {
data() {
return {
newImage: {
title: '',
image: null,
},
};
},
methods: {
addImage() {
this.$store.dispatch('addProduct', this.newProduct);
}
},
};
store.js
actions: {
addImage(context, newImage) {
const config = {
headers: {
token: localStorage.getItem('token'),
},
};
Axios
.post(`${baseUrl}/product`, newImage, config)
.then(({ newImage }) => {
context.commit('ADD_IMAGE', newImage);
})
.catch((err) => {
console.log(err.message);
});
}
}
When you want to upload an image you have to set the content type and create FormData, like this:
let data = new FormData();
for (var i = 0; i < files.length; i++) {
let file = files.item(i);
data.append('images[' + i + ']', file, file.name);
}
const config = {
headers: { 'content-type': 'multipart/form-data' }
}
return axios.post('/api/images', data, config)