Carrierwave: upload an image from vue front to rails api - vue.js

I am not sure how to make the axios post for the image.
This is what my json object looks like.
{
"id":20,
"title":"pineapple",
"text":"pineapple",
"date":null,
"created_at":"2019-03-23T01:42:48.142Z",
"updated_at":"2019-03-23T01:42:48.142Z",
"image":{
"url":null
}
}
This is my image input from the Vue form.
<input type="file"
id="file"
ref="myFiles"
class="custom-file-input"
#change="takeFile"
multiple>
Here is me trying to make sense of it.
export default {
data() {
return {
blog: {
title: '',
content: '',
link: ''
}
}
},
methods: {
submitArticle(blog) {
console.log('blog.link', blog.link)
axios.post('http://localhost:3000/articles', {
title: blog.title,
text: blog.content,
image: {
url: blog.link
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
},
takeFile(event) {
console.log(this.$refs.myFiles.files);
this.blog.link = this.$refs.myFiles.files
}
}
}
Here is a link to the file in my repo.

First this.$refs.myFiles.files returns an array of files. Change your method like this to set the file to blog.link:
takeFile(event) {
this.blog.link = this.$refs.myFiles.files[0]
}
Now to send file in your post request, you should use FormData:
submitArticle(blog) {
let formData = new FormData()
formData.append("article[title]", blog.title)
formData.append("article[text]", blog.content)
formData.append("article[image]", blog.link)
axios.post('http://localhost:3000/articles', formData, {
headers: {
'Content-Type': 'application/json'
}
}).then(function (response) {
console.log(response)
}).catch(function (error) {
console.log(error)
})
},

Related

Request failed with status code 401', name: 'AxiosError', code: 'ERR_BAD_REQUEST'

I'm on a page that uses a vue component and one of my patch routes is saying I'm un-authenticated.
<template>
...
<button #click="editPost(attributes.attributes.post_id)"></button>
...
</template>
<script>
export default {
data() {
return {
info: null,
message: null,
postTitle: "",
postContent: ""
}
},
methods: {
editPost(id) { // not working, 401 unauthenticated
console.log('edit post clicked', id);
axios.patch('http://127.0.0.1:8000/api/posts/' + id, {
headers: {
Authorization: 'Bearer 3d58d6cd66e134a59b3a9373a2b4a233e55d00107b9251f654c5c92a2276a1c5'
}
})
.then((response) => {
this.info = response.data;
// this.message = 'Success';
console.log(this.info);
})
.catch((error) => {
console.log(error, error.response.data.message);
this.message = error.response.data.message;
})
},
deletePost(value){
console.log('delete post clicked', value);
}
},
mounted() {
axios.get('http://127.0.0.1:8000/api/posts', { // working as expected, authenticated
headers: {
Authorization: 'Bearer 3d58d6cd66e134a59b3a9373a2b4a233e55d00107b9251f654c5c92a2276a1c5'
}
})
.then((response) => {
this.info = response.data;
this.message = 'Success';
console.log(this.info);
})
.catch((error) => {
console.log(error, error.response.data.message);
this.message = error.response.data.message;
})
}
}
</script>
I dont understand how this can be since I have to authenticate to get the posts on page load and they load fine, with authentication using a Bearer token in header?
Why is the call to axios using a PATCH not working? The PATCH call works in postman fine also.

how to upload file with title and description using vuex and laravel

i have a section in my project where i can upload a post with image
i tried this but it's returning a 419 status
vue script:
<script>
export default {
data() {
return{
post: {
title: '',
description: '',
},
file: '',
name: '',
}
},
methods: {
onChange(e){
this.file = e.target.files[0];
},
createPost(e){
e.preventDefault();
const config = {
headers: {
'content-type': 'multipart/form-data'
}
}
let data = new FormData();
data.append('file', this.file);
this.$store.dispatch('createPost', this.post, data, config);
}
}
}
</script>
vuex store's actions:
createPost({}, post, data, config){
axios.post('api/createPost',{
title: post.title,
description: post.description
}, data , config ).then(res => {
console.log(res);
}).catch(err =>{
console.log(err);
})
}
i'm gettinh this error:
POST http://127.0.0.1:8000/dashboard/api/createPost 419 (unknown status)
i figured it out
the script should've been like this :
<script>
export default {
data() {
return{
post: {
title: '',
description: '',
},
file: '',
}
},
methods: {
onChange(e){
this.file = e.target.files[0];
},
createPost(e){
e.preventDefault();
const config = {
headers: {
'content-type': 'multipart/form-data'
}
}
let data = new FormData();
data.append('file', this.file);
data.append('title', this.post.title);
data.append('description', this.post.description);
this.$store.dispatch('createPost', data, config);
}
}
}
</script>
and the vuex file should've containe this :
createPost({}, data, config){
axios.post('/api/createPost', data , config ).then(res => {
console.log(res);
}).catch(err =>{
console.error(err);
})
}

How to fetch data in Vue 3?

I don't know how to fetch data with Vue 3? I created one action and with this action I am calling endpoint (https://api.openbrewerydb.org/breweries/5494). I didn't get response data.
Endpoint:
import { createStore } from 'vuex'
export default createStore({
state: {
},
mutations: {
},
actions: {
async getData() {
await fetch('https://api.openbrewerydb.org/breweries/5494', {
method: 'get',
headers: { 'Content-type': 'application/json' },
}).then((response) => {
if (!response.ok) {
throw Error(response.statusText);
}
console.log('response: ', response)
}).catch((error) => {
console.log('Looks like there was a problem: \n', error);
});
}
},
modules: {
}
})
Vue component:
<template>
<div #click="loadData">Load Data</div>
</template>
<script>
import { useStore } from 'vuex'
export default {
name: 'HelloWorld',
props: {
msg: String
},
setup () {
const store = useStore()
const loadData = () => {
store.dispatch('getData')
}
return { loadData }
}
}
</script>
As a response I didn't get anything but I should get:
{"id":5494,"name":"MadTree Brewing","brewery_type":"regional","street":"3301 Madison Rd","address_2":null,"address_3":null,"city":"Cincinnati","state":"Ohio","county_province":null,"postal_code":"45209-1132","country":"United States","longitude":"-84.4239715","latitude":"39.1563725","phone":"5138368733","website_url":"http://www.madtreebrewing.com","updated_at":"2018-08-24T15:44:22.281Z","created_at":"2018-07-24T01:34:01.620Z"}
You need to make the data to json
.then(res=>res.json())
this will do the trick for you.
const getData = () => {
fetch('https://api.openbrewerydb.org/breweries/5494', {
headers: { 'Content-type': 'application/json' },
}).then(res=>res.json()).then((response) => {
console.log({ response })
}).catch((error) => {
console.log('Looks like there was a problem: \n', error);
});
}
getData();
If the response fails, it will surely get you to catch.
This answer Should be the accepted answer.
If readers landed here while working through the introductory examples on the Vue.js website, Adarsh's code can be adapted thusly (for Vue.js 3):
<div id="beer">
{{ message }}
</div>
const Breweries = {
data() {
return {
message: ""
}},
mounted() {
fetch('https://api.openbrewerydb.org/breweries/', {
headers: { 'Content-type': 'application/json' },
}).then(res=>res.json()).then((response) => {
this.message = response;
}).catch( (error) => {
this.message = error;
});
}
}
Vue.createApp(Breweries).mount('#beer')
First you must install a package like axios
Then create an object from axios and call the API
import axios from "axios";
export default {
setup() {
function getUsers() {
axios.get("https://jsonplaceholder.typicode.com/users")
.then(function (response) {
// handle success
console.log(response.data);
})
.catch(function (error) {
// handle error
console.log(error);
});
getUsers();
}
return { getUsers };
},
};

TypeError: stripe.redirectToCheckout is not a function in nuxt.js

I am trying to integrate stripe payment gateway. I have a nuxt.js for front-end and adonis.js for backend.
From front-end I am calling an api to backend to create checkoutSession and return the sessionID. I am able to create checkoutSession and return the sessionID and in api response I am calling the
stripe.redirectToCheckout but it is not redirecting rather gives error as stripe.redirectToCheckout is not a function. How can I redirect users to checkout Page?
I have install the stripe-js file also.
import { loadStripe } from '#stripe/stripe-js'
const stripe = loadStripe(process.env.STRIPE_PK)
<button class="btn btn-primary btn-block text-center rounded" #click="checkout()">Buy</button>
import { loadStripe } from '#stripe/stripe-js'
const stripe = loadStripe(process.env.STRIPE_PK)
export default {
methods: {
checkout() {
let params = {
payment_method_types: ['card'],
line_items: [
{
name: 'Buy Now',
images: ['image.jpg'],
amount: 100 + '00',
currency: 'usd',
quantity: 1,
},
],
mode: 'payment',
success_url: `${process.env.URL}/success`,
cancel_url: window.location.href,
}
axios
.post(`${process.env.API_BASE_URL}/stripe/session`, params, {
'Content-type': 'application/json',
Accept: 'application/json',
})
.then((response) => {
this.stripeSession = response.data.data
stripe.redirectToCheckout({sessionId: this.stripeSession})
})
.catch((e) => {
console.log(e)
})
}
},
}
</script>
According to tyhe doc, loadStripe is an async function, try adding await in stripe assignement:
const stripe = await loadStripe(process.env.STRIPE_PK)
Edit:
To get rid of Module parse failed: Cannot use keyword 'await' outside an async function error you just need to add async before your function declaration :
async function myAsyncFunction() {
const test = await myPromise();
}
As I do not have the full definition of your function I cannot show it to you in your code :-(
But a weird solution (mixing 'await' and 'then') would be :
import { loadStripe } from '#stripe/stripe-js';
axios
.post(`${process.env.API_BASE_URL}/stripe/session`, params, {
'Content-type': 'application/json',
Accept: 'application/json',
})
.then(async response => {
this.stripeSession = response.data.data;
const stripe = await loadStripe(process.env.STRIPE_PK);
stripe.redirectToCheckout({ sessionId: this.stripeSession });
})
.catch(e => {
console.log(e);
});
This should work:
import { loadStripe } from '#stripe/stripe-js';
export default {
methods: {
async checkout() {
let params = {
payment_method_types: ['card'],
line_items: [
{
name: 'Buy Now',
images: ['image.jpg'],
amount: 100 + '00',
currency: 'usd',
quantity: 1,
},
],
mode: 'payment',
success_url: `${process.env.URL}/success`,
cancel_url: window.location.href,
};
try {
const { data } = await axios.post(`${process.env.API_BASE_URL}/stripe/session`, params, {
'Content-type': 'application/json',
Accept: 'application/json',
});
this.stripeSession = data.data;
const stripe = await loadStripe(process.env.STRIPE_PK);
stripe.redirectToCheckout({ sessionId: this.stripeSession });
} catch (error) {
console.error(error);
}
},
},
};

I can't post my file on the server with formData from the state

I'm not able to post a form data on my server files as formData from my store.
Checking the state before submit I can see that image and video properties have formDatas as values, but on submit the params of the request are empty object
<template>
<input type="file" #change="onImageSelected($event)" accept="image/*" >
</template>
methods: {
submit() {
this.$v.$touch()
if (this.$v.$invalid || this.tags.length > 3) {
this.submitStatus = 'ERROR'
} else {
this.submitStatus = 'PENDING'
this.$store.dispatch('exercises/storeExercise')
}
},
onImageSelected(event) {
this.image = event.target.files[0]
if (this.image.size < 8000000) {
const formDataImage = new FormData()
formDataImage.append('image', this.image)
this.$store.dispatch('exercises/commitImageSelected', formDataImage)
}
},
}
const state = {
exercises: [],
tags: [],
selectedExercise: null,
selectedComponent: BeforeSelect
}
const mutations = {
setImageSelected(state, image) {
Vue.set(state.selectedExercise, 'image', image)
},
setVideoSelected(state, video) {
Vue.set(state.selectedExercise, 'video', video)
}
}
const actions = {
commitImageSelected({commit}, image){
commit('setImageSelected', image)
},
commitVideoSelected({commit}, video){
commit('setVideoSelected', video)
},
storeExercise({commit, state}) {
axios.post('exercises', state.selectedExercise)
.then(({data}) => {
commit('setExercises', data)
})
.catch(err => console.log(err))
},
}
Try this axios post in storeExcerise method.
axios.post('exercises',state.selectedExercise,{
headers: { 'Content-Type': undefined},
}).then(function (response) {
if (response.data.ok) {
}
}.bind(this));
This is working fine for me while uploading file to server.