I work in the project with vuejs and bootsrapt-vue and I want to upload any type of file(picture, pdf ..etc) by axios library.
When I try to upload, nothing is uploading to the backend. Can some one please look in my code and tell what I'm doing wrong?
I'm pretty new into coding.
Here is my code:
`
<template> <b-container fluid>
<h4>Images page</h4>
<!-- <b-form-file action="" v-model="image" plain></b-form-file> -->
<b-form action="" method="post" v-model="image" enctype="multipart/form-data">
<h2>Select image to upload:</h2>
<input type="file" name="fileToUpload" id="fileToUpload">
<b-button type="submit" name="submit" variant="success" v-on:click="uploadImage">Upload image</b-button>
</b-form>
</b-container>
</template>
<script>
// eslint-disable-next-line
/* eslint-disable */
export default {
name: 'imagesPage',
data() {
return {
images: [],
image: []
}
},
methods: {
uploadImage(evt) {
evt.preventDefault()
var data = new FormData();
data.append('image', document.getElementById('fileToUpload').files[0])
var token = sessionStorage.setItem('token', data, null)
window.API.post('https://192.168.56.101:8080/images/' + token, data, null)
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.log(JSON.stringify(error))
})
console.log('blabla')
// this.template.push({
// image_id: ''
// })
}
}
}
</script>
`
Related
Code
template
<template>
<div id="app">
<input type="file" #change="onChange" />
</div>
</template>
export default {
name: "App",
methods: {
async onChange(event) {
const headers = {
'Content-type': 'multipart/form-data'
},
const response = await.post('http://localhost:3030/api/new/post', event.target.files[0], headers);
console.log(response);
},
}
};
I would like to upload file as it is through api, I tested through postman it does work. How can I upload it via VueJS. can anyone suggest.
Thank You
You can use FormData to send files to the server.
<template>
<div id="app">
<input type="file" #change="onChange" />
</div>
</template>
<script>
export default {
name: "App",
methods: {
async onChange(event) {
const formData = new FormData();
formData.append("file", event.target.files[0]);
const response = await axios.post("xyzzy.com", formData);
console.log(response);
}
}
};
</script>
I am creating a simple to do list and using Json server as a mock data base. I am trying to add a delete button that will delete the goals that have already added to the Vue application.
This is my main app
<template>
<h1>To Do List </h1>
<addProject />
<div v-for="newGoal in newGoals" :key="newGoal.id" class = 'newGoal'>
<li >{{newGoal.goal}} <deleteGoalVue /> </li>
</div>
</template>
<script>
import addProject from './components/addProject.vue';
import deleteGoalVue from './components/deleteGoal.vue';
export default {
name: 'App',
components: { addProject, deleteGoalVue },
data(){
return {
newGoals: [],
}
},
mounted() {
fetch('http://localhost:3000/newGoals')
.then(res => res.json())
.then(data => this.newGoals = data)
.catch(err => console.log(err.message))
}
}
This is my add project/goal component
<template>
<form #submit.prevent="handleSubmit">
<h3><div class= instructions >Type in your goal for the day</div></h3>
<input type="text" v-model="goal" placeholder="Your goal">
<input type="submit" value="Add Goal" #click="storeGoal" >
</form>
</template>
<script>
export default {
props: ['project'],
data (){
return{
goal: "",
}
},
handleSubmit(){
let project = {
goal: this.goal,
}
fetch('http://localhost:3000/newGoals', {
method: 'POST',
headers: { 'Content-Type' : 'application/json' },
body: JSON.stringify(project)
})
}
}
And this is my Delete Goal component
<template>
<button #click ="deleteGoal" >Delete Goal</button>
</template>
<script>
export default {
methods: {
deleteGoal() {
fetch('http://localhost:3000/newGoals', { method: 'DELETE'})
}
}
}
</script>
The error that I am getting when I press the 'Delete Goal' button says
DELETE http://localhost:3000/newGoals 404 (Not Found)
Please kindly help me with this, because I'm new in vue.js.
So, I have 2 Vue files :
Greetinglist.vue, It calls data from api using axios.get
Greeting.vue, It posts data using axios.post
After submit data, how to refresh the data without reload the page ?
I'm using <script setup> tag.
(greetinglist.vue)
<div class="p-2" v-for="(message, index) in messages" :key="index">
<div>
<h3>{{ message.name }}<span>{{message.date}}</span></h3>
<p class="text-slate-300 text-lg">{{ message.greeting }}</p>
</div>
<hr/>
</div>
<script setup>
import {ref, onMounted } from 'vue'
import axios from 'axios'
let messages = ref([]);
function getMessages() {
axios.get('http://127.0.0.1:8000/api/messages')
.then((result) => {
messages.value = result.data
}).catch((err) => {
console.log(err.response.data)
})
}
onMounted(() => {
getMessages()
});
</script>
(Greeting.vue)
<form #submit.prevent="store()">
<div class="">
<input type="text" placeholder="" v-model="messages.name">
<textarea name="" id="" cols="28" rows="10" placeholder="" v-model="messages.greeting"></textarea>
</div>
<button>Submit</button>
</form>
<div>
<GreetingList/>
</div>
<script setup>
import { reactive } from 'vue'
import axios from 'axios'
import GreetingList from './GreetingList.vue'
const messages = reactive({
name: '',
greeting: '',
});
function store() {
axios.post('http://127.0.0.1:8000/api/messages', messages)
.then((result) => {
messages.name = ''
messages.greeting = ''
})
.catch((err) => {
})
}
</script>
You can move getMessages function to greeting.vue, and change greetinglist.vue to use props
greeting.vue
<form #submit.prevent="store()">
<div class="">
<input type="text" placeholder="" v-model="messages.name">
<textarea name="" id="" cols="28" rows="10" placeholder="" v-model="messages.greeting"></textarea>
</div>
<button>Submit</button>
</form>
<div>
<GreetingList :messages="messageList" />
</div>
<script setup>
import { reactive } from 'vue'
import axios from 'axios'
import GreetingList from './GreetingList.vue'
const messages = reactive({
name: '',
greeting: '',
});
let messageList = ref([])
function store() {
axios.post('http://127.0.0.1:8000/api/messages', messages)
.then((result) => {
messages.name = ''
messages.greeting = ''
getMessages()
})
.catch((err) => {
})
}
function getMessages() {
axios.get('http://127.0.0.1:8000/api/messages')
.then((result) => {
messageList.value = result.data
}).catch((err) => {
console.log(err.response.data)
})
}
onMounted(() => {
getMessages()
});
</script>
greetinglist.vue
<script setup>
defineProps(['messages'])
</script>
If I understood your requirement correctly, I am assuming you have both the components in a single page and you want to get the details of newly added greeting from Greeting.vue in the GreetingList.vue reactively (without refreshing the route). If Yes, You can achieve that by calling a getMessages() method on successfully promise of axios.post and then pass the results in the GreetingList.vue.
Demo (I just created it using Vue 2, You can change it accordingly as per Vue 3) :
Vue.component('child', {
// declare the props
props: ['msglist'],
// just like data, the prop can be used inside templates
// and is also made available in the vm as this.message
template: `<div>
<div v-for="(message, index) in msglist" :key="index">
<h3>{{ message.name }}</h3>
<p>{{ message.greeting }}</p>
<hr/>
</div>
</div>`
});
var app = new Vue({
el: '#app',
data: {
messages: {
name: null,
greeting: null
},
// For demo, I am just mock data for initial greeting listing.
messageList: [{
name: 'Alpha',
greeting: 'Hi !'
}, {
name: 'Beta',
greeting: 'Hello !'
}]
},
methods: {
store() {
// Post API call will happen here.
// on success, make a call to get list of greetings.
if (this.messages.name && this.messages.greeting) {
this.getMessages();
}
},
getMessages() {
// Get API call will happen here. For demo, I am just using the mock data and pushing the newly submitted greeting in a exisiting messageList.
this.messageList.push({
name: this.messages.name,
greeting: this.messages.greeting
})
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input type="text" placeholder="Name" v-model="messages.name"/>
<textarea cols="28" rows="10" placeholder="Greeting" v-model="messages.greeting"></textarea>
<button #click="store">Submit</button>
<child :msglist="messageList">
</child>
</div>
<template>
<div>
<h1>Post component</h1>
<form #submit="submitData" method="post">
<input type="text" placeholder="Enter Title" name="tilte" v-model="userdata.title" /><br />
<br />
<input type="text" placeholder="Enter Author" name="author" v-model="userdata.author" /><br /><br />
<button type="submit">Submit Data</button>
</form>
</div>
</template>
<script>
import axios from "axios";
export default {
name: "postcomponent",
data() {
return {
userdata: {
title: null,
author: null,
},
};
},
methods: {
submitData(e) {
axios.post(
"http://localhost:3000/posts",
this.userdata
).then((result) => {
console.warn(result)
});
e.preventDefault();
},
},
};
</script>
I'm fairly new to Vue & Vuex and am unsure on how to set up my form correctly.
<template>
<div>
<div v-if="error">{{error.message}}</div>
<form #submit.prevent>
<h1>Register</h1>
<input type="email" name="" id="" :value.sync="email" placeholder="Email">
<input type="password" :value.sync="password" placeholder="Password">
<button #click="signup">Submit</button>
Sign in
</form>
</div>
</template>
<script>
import {fireAuth} from '~/plugins/firebase.js'
export default {
data: () => ({
email: '',
password: '',
error: ''
}),
methods: {
signup() {
fireAuth.createUserWithEmailAndPassword(this.email, this.password).then(res => {
if (res) {
this.$store.commit('setCurrentUser', res.user)
this.$router.push('/')
}
}).catch(err => {
this.error = err
console.log(err)
})
}
}
}
</script>
At first I tried v-model to bind the form, it was throwing and error as I was mutating the store but I'm not storing email and password so I'm unsure how this is mutating the store? If I use :value or :value.sync then the email and password fields remain an empty string, so I'm not sure how to set up these correctly or how they differ from v-model
Edit: Adding my code from the store as requested
export const state = () => ({
currentUser: {}
})
export const mutations = {
setCurrentUser (state, obj) {
state.currentUser = obj
}
}
Vue.config.devtools = false
Vue.config.productionTip = false
const vm = new Vue({
el: "#app",
data() {
return {
email: '',
password: ''
}
},
methods: {
signup() {
console.log(this.email) // email value
console.log(this.password) // password value
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div id="app">
<div>
<form #submit.prevent="signup">
<h1>Register</h1>
<input type="email" v-model="email" placeholder="Email">
<input type="password" v-model="password" placeholder="Password">
<input type="submit">
</form>
</div>
</div>
</body>
</html>
I think I have found the solution, it was the way in which I was trying to use firebase. I have used v-model, but am using a firebase method onAuthStateChanged, only if that is called will I change the store. So in my firebase.js I added
const fireAuth = firebase.auth()
const fireDb = firebase.database()
export { fireAuth, fireDb }
export default async ({ store }) => {
await asyncOnAuthStateChanged(store)
}
function asyncOnAuthStateChanged (store) {
return new Promise(resolve => {
fireAuth.onAuthStateChanged(user => {
resolve(user)
store.commit('setCurrentUser', JSON.parse(JSON.stringify(user)))
})
})
}
I am trying to send a form along with an image. Note: I don't want to save the image in a database, I want to save it in a folder which I created on the server and just add a link of the image to the database.
From the server side I know how to handle this, but I don't know how to do this from font-end. With other words, how can I send the image using axios to the server.
<template>
<input type="text" class="form-control" id="specdesc" v-model="product.specdesc" name="specdesc" placeholder="Enter your name">
<input type="file" name="image" id="image" accept="image/*" >
<button type="submit" class="btn btn-sm btn-primary"#click.prevent="Submit()"> Submit</button>
</template>
<script>
export default {
name: 'Addproduct',
data(){
return{
image: '',
product:{
specdesc:'',
},
}
},
methods:{
Submit(){
var _this=this
// console.log(this.image)
console.log(this.selectedCategory.category_name)
var product = {
specification:this.product.specdesc,
imagename:this.image
}
this.$http.post('http://localhost:3000/api/companyproducts',product)
.then(function (response) {
console.log(response.data);
})
.catch(function (error) {
console.log("error.response");
});
}
},
}
</script>
Now my question is how can I upload a image as well as the input name using axios. Moreover I want to use the same method i.e var product to send.
A standard (mostly) approach will be to split the logic in two, if you want to save the image path on your product, you firstly need to upload the photo to the server and return their path.
pseudo example:
component's data
{
imagePath: '',
productSpect: ''
}
``
``html
<input type="text" v-model="productSpect" />
<input type="file" #change="uploadImage" name="image" id="image" accept="image/*" >
<button type="submit" #click.prevent="submit"> Submit</button>`
``
**uploadImage method**
uploadImage (e) {
let img = e.target.files[0]
let fd= new FormData()
fd.append('image', img)
axios.post('/upload-image', fd)
.then(resp => {
this.imagePath = resp.data.path
})
}
**submit method**
submit () {
let data = {
imagePath: this.imagePath,
productSpect: this.productSpect
}
axios.post('/path/to/save', data)
}
**edited method to handle just only 1 image on the server**
Change the input `#change` to just save the img on a property under data():
<input type="file" #change="image = e.target.file[0]" name="image" id="image" accept="image/*" >
submit() {
let fd= new FormData()
fd.append('image', this.image)
axios.post('/upload-image', fd)
.then(resp => {
this.imagePath = resp.data.path
let data = {
imagePath: this.imagePath,
productSpect: this.productSpect
}
axios.post('/path/to/save', data)
})
}
There is nothing specific to Vue in this question. To send a POST request with axios, the easiest thing to do is to grab the formData of the html form and pass it as the data argument to Axios. To do this in Vue, just give your form tag a ref, then create a formData from the form.
<form ref="myForm">
// then in your method...
var myFormData = new FormData(this.$refs.myForm)
axios({
method: 'post',
url: 'myurl',
data: myFormData,
config: { headers: {'Content-Type': 'multipart/form-data' }}
})
for upload file I've used vuetify https://vuetifyjs.com/en/components/file-inputs/
<v-file-input
accept="image/png, image/jpeg, image/bmp"
placeholder="Pick an avatar"
prepend-icon="mdi-camera"
v-model="imageData"
></v-file-input>
<v-btn color="primary" #click="onUpload">Upload</v-btn>
in my vue method I have
onUpload() {
let formData = new FormData();
formData.append('file', this.imageData);
axios.post(
"/images/v1/upload"
,formData
,{headers: {"Content-Type": "multipart/form-data"}}
)
.then(response => {
//...
})
.catch(e => {
//...
})
}
Best regards!