I have a vuejs web aplication. In there have a form to edit-user's data. The part of edit the data like 'name', 'phone', etc is working like a charm but when the user come's to the profille picture upload they simply not upload from the backend ( codeigniter4 Rest API ). In the mobile application is everything ok to the update of that. Here is the code:
<form>
<input type="file" #change="`whenSelectImage" />
<div class="button" #click.prevent="atualizarUsuario();uploadFoto()">
<slot>Atualizar informações</slot>
</div>
</form>
and the methods part:
whenSelectImage(event){
this.selectedPicture= event.target.files[0]
},
uploadFoto(){
const fd = new FormData();
fd.append('image', this.selectedPicture, this.selectedPicture.name)
apiOnline
.post(
`/usuario/dados/${window.localStorage.uuid}`, fd
).then(res => {
console.log(res.response.data)
})
.catch(error => console.log(error.response))
}
the console says:
"undefined"
and in the Network Headers they are sending Form Data with Image: ( binary )
I'm using Vuex to store the data of the user
Related
I am trying to develop a simple app with Next.js but i am having issues with learning how to create an api.
This is my component to add an event with a form and a submit method that fetchs the data from the api.
import React from 'react'
import Layout from '#/components/Layout'
import styles from '#/styles/AddEvent.module.css'
export default function AddEventPage() {
const submitHanlder = (e) => {
e.preventDefault();
const formData = {
title: e.target.title.value,
description: e.target.description.value
}
fetch('/api/events', {
method: 'POST',
body: JSON.stringify(formData)
});
console.log(formData)
}
return (
<Layout title='Add New Event'>
<h1>Add Event</h1>
<div className={styles.container}>
<form className={styles.form} action="" onSubmit={submitHanlder}>
<label className={styles.label} >Title</label>
<input type="text" name="title" />
<label className={styles.label} >Description</label>
<input type="text" name="description"/>
<label className={styles.label}htmlFor="">Date</label>
<input type="date" />
<button type='submit' >Submit</button>
</form>
</div>
</Layout>
)
}
And this is my api/events.js:
const handler = (req , res) => {
if(req.method === 'POST'){
return res.status(201).json({ message: 'evento agregado' });
}
return res.status(400).json({ error: 'no se pudo agregar el evento' });
}
export default handler;
It is a simple handler that returns a message depending on the request method, but i am always getting the status 400 with the error message.
This is my request in the browser console:
{"title":"asdasd","description":"asdasdas"}
And my response:
message "evento agregado"
So it seems that is working. But when i go to localhost:3000/api/events it shows the following:
error "no se pudo agregar el evento"
You could try to print out what req.method is when the api gets called.
Add the following statement:
console.log(req.method)`
Then have a look at what the server logs out.
When you try to open localhost:3000/api/events in your browser the browser makes a GET Request, not a POST Request, to your api. That is the default behavior when opening a 'website'.
If you want to test your api you could use Postman or an extension for Visual Studio Code. The REST Client from Visual Studio Marketplace would probably be an option.
when I execute this in created, it works:
axios
.delete('http://localhost:8000/product/10')
.then(response => {
console.log(response);
})
.catch(err => {
console.log(err);
});
however, if I make a button and on submit I call a method that executes the same code it doesn't work, in the back, I get in the console
OPTIONS /product/10 204 0.172 ms - 0
Note that when I press the button the page refreshes and if I click the button several times fast it executes
Edit: I disabled the refresh, and now it works, Is there anything I can do because I want the method to execute even if I refresh.
the template:
<b-form class="mt-5 pt-5">
<b-form-group id="productId" label="Product id " label-form="productIdInput">
<b-form-input id="productIdInput" type="text" v-model="productForm.id" placeholder="enter product id you wish to delete"> </b-form-input>
</b-form-group>
<button type="button" v-on:click="deleteProduct()">Delete</button>
</b-form>
methods:{
deleteProduct() {
// this.$store.dispatch('removeProduct',this.productForm.id);
axios
.delete('http://localhost:8000/product/10')
.then((response) => {
console.log(response);
})
.catch((err) => {
console.log(err);
})
},
}
The delete request sends options first it seems due to cross-origin and then it waits for response to send the real request, when i click a button and the page refreshes the options is sent, however (what i understood) is that the delete request no longer exists to wait for the response, so simply i added a e.preventDefault() in the method
I've got a basic client-side rendered vue app that fetches a json array from an API endpoint and renders data from each array item as a list item in an ordered list.
The data renders as expected when I'm developing locally, using parcel index.pug to spin up my local dev environment. Here's a screenshot of the expected ordered list as shown in my local dev environment at localhost:1234:
However, the data does not render as expected when I build for production (using parcel build index.pug). Here's a screenshot of the unexpected behavior in production mode (which you can see live online at https://errands.netlify.com/):
Notice that the production version knows the fetched API data is an array with a length of 6 (because it renders out 6 empty <li>s), but for some reason the production version does not know the data inside each array object.
The full source code for this app is here, https://github.com/brianzelip/groceries-vue.
The main relevant code (the axios call to the API, which updates the vuex store, then renders out the ordered list) lives in TheGroceryForm.vue, which is also included here:
<template>
<form action="/submit" method="POST">
<ol class="list-reset border rounded">
<li class="item" v-for="item in allGroceryItems" v-bind:key="item._id">
<GroceryFormItemEditLink/>
<GroceryFormItemCheckboxInput :slug="item.slug"/>
<GroceryFormItemCheckboxLabel :slug="item.slug" :name="item.name"/>
<GroceryFormItemQtySelector :slug="item.slug"/>
<GroceryFormItemStoresSelector
:stores="item.stores"
:slug="item.slug"
:defaultStore="item.defaultStore"/>
</li>
</ol>
</form>
</template>
<script>
import axios from 'axios';
import GroceryFormItemEditLink from './GroceryFormItemEditLink.vue';
import GroceryFormItemCheckboxInput from './GroceryFormItemCheckboxInput.vue';
import GroceryFormItemCheckboxLabel from './GroceryFormItemCheckboxLabel.vue';
import GroceryFormItemQtySelector from './GroceryFormItemQtySelector.vue';
import GroceryFormItemStoresSelector from './GroceryFormItemStoresSelector.vue';
export default {
data() {
return {};
},
components: {
GroceryFormItemEditLink,
GroceryFormItemCheckboxInput,
GroceryFormItemCheckboxLabel,
GroceryFormItemQtySelector,
GroceryFormItemStoresSelector
},
computed: {
allGroceryItems() {
return this.$store.state.allGroceryItems;
},
allGroceryItemsCount() {
return this.$store.getters.allGroceryItemsCount;
}
},
getters: {},
created() {
axios
.get('https://groceries-vue-api.glitch.me/get')
.then(res => {
console.log('axio.get worked! res.data =', res.data);
console.log(`typeof res.data = ${typeof res.data}`);
const groceryData = res.data;
console.log('groceryData =', groceryData);
console.log(`typeof groceryData = ${typeof groceryData}`);
const newData = res.data.map(obj => obj);
console.log('newData', newData);
return newData;
})
.then(data => {
console.log('data from second then() =', data);
return data;
})
.then(data => (this.$store.state.allGroceryItems = data))
.catch(error => {
console.log('ERROR! ->', error);
});
}
};
</script>
Why does the data change when I build my app for production? And how can I change this behavior to get the expected outcome?
You should avoid using self closing tags.
https://github.com/vuejs/vue/issues/1036
So your TheGroceryForm.vue will be
<template>
<form action="/submit" method="POST">
<ol class="list-reset border rounded">
<li class="item" v-for="item in allGroceryItems" v-bind:key="item._id">
<GroceryFormItemEditLink></GroceryFormItemEditLink>
<GroceryFormItemCheckboxInput :slug="item.slug"></GroceryFormItemCheckboxInput>
<GroceryFormItemCheckboxLabel :slug="item.slug" :name="item.name"></GroceryFormItemCheckboxLabel>
<GroceryFormItemQtySelector :slug="item.slug"></GroceryFormItemQtySelector>
<GroceryFormItemStoresSelector
:stores="item.stores"
:slug="item.slug"
:defaultStore="item.defaultStore"></GroceryFormItemStoresSelector>
</li>
</ol>
</form>
</template>
I'm new to Vue.js and I have problem with binding on vue-bootstrap modal. I have a form inside vue-bootstrap-modal, and there is a field with NIP number, and onChange watcher bound to this field. And this watcher sends a request and I would like to set response of that request to other inputs, something like this:
HTML:
<div id="app">
<h2>Todos:</h2>
<form>
<input
name="model1"
v-model="model1">
<input
name="model1"
v-model="model2">
</form>
</div>
JS:
new Vue({
el: "#app",
data: {
model1: '',
model2: ''
},
watch: {
model1: function(todo){
Vue.http.get('https://jsonplaceholder.typicode.com/posts/1').then((response) => {
console.log('response', 'response')
this.model2 = 'test'
})
}
}
})
https://jsfiddle.net/8cdsnL91/95/
Here it is working perfectly, but on inside my bootstrap modal the values are setting after I make change to this input. So I write 10digit number, method is sending a request, I receive response, and trying to set response to the models, and when I try to console.log model the values are there, but the view updates after I interact with form. In AngularJS, I would need to use something like $scope.$apply(). Any help?
I have token authentication setup with DRF and VueJS. However, I can't seem to login using the combo of VueJS, axios, and the DRF token system and I don't understand why. I have CORS installed and if I manually set the token into the VueJS code, all my requests from VueJS to the DRF backend API work fine. It's just the login and getting the initial token that isn't working.
Here's my code:
Django URLs:
from rest_framework.authtoken import views
url(r'^api/token-auth/', views.obtain_auth_token)
Django middleware
class SiteLogin:
def process_request(self, request):
url = request.path.split('/')
# Don't require password for the URL /api/token-auth/
if url[1] == 'api' and url[2] == 'token-auth':
return None
auth Service -- VueJS:
// ... other code ...
login (context, creds, redirect) {
console.log(creds)
axios.post(LOGIN_URL, creds).then((response) => {
localStorage.setItem('token', response.data.token)
this.user.authenticated = true
// If a redirect link is provided
if (redirect) {
router.push(redirect)
}
}).catch((err) => {
console.log(err)
})
},
Login Component - VueJS:
<template>
<div>
<div class='container-fluid container-fullw bg-white'>
<div class='row'>
<div class='col-md-4'>
Login<br>
<br>
<input type='text' class='form-control' placeholder="Username" v-model='credentials.username'><br>
<input type='password' class='form-control' placeholder="Password" v-model='credentials.password'><br>
<button class='btn btn-primary btn-sm' #click='submit()'>Login</button>
</div>
</div>
</div>
</div>
</template>
<script>
import auth from '../../services/auth'
export default {
name: 'login',
data () {
return {
credentials: {
username: '',
password: ''
},
error: ''
}
},
methods: {
submit () {
auth.login(this, this.credentials, '/')
}
}
}
</script>
Upon clicking "Submit" the DRF backend always returns a 401.
Edit:
Also, if I add print(request.POST) into the SiteLogin section of the Django middleware, I can see that a) the if statement returns true (it's acknowledging that it's a login URL) and b) the QueryDict is empty -- I see: <QueryDict: {}>
I solved it over here: https://stackoverflow.com/a/45850775/717682
Problem was that the TokenAuthentication was preventing my axios POST request from being called at all -- immediately returning a 401.