Sending PUT request in Nuxt3 with oh my fetch - vue.js

I try send put request in public api. When I send, my data doesn't update.
my code:
<template>
<div class="mt-20 mb-32 px-20 mx-aute gap-20" data-scroll-section>
<div class="mt-20 mb-20">
<form>
<label>Enter Title</label>
<input type="text" v-model="title"/>
<button class="ng-bt-pri" #click="update">Send Message</button>
</form>
{{title}}
</div>
{{data}}
</div>
</template>
<script setup lang="ts">
import { $fetch } from 'ohmyfetch'
import { ref, onMounted } from "vue";
var title = ref("");
const update = async() => await $fetch( "https://api.escuelajs.co/api/v1/products/1", {
headers: {
"Content-Type": "application/json",
},
method: "put",
body: {
'title': title
}
} );
const {data} = await useFetch('https://api.escuelajs.co/api/v1/products/1')
</script>
and api documentation:
https://fakeapi.platzi.com/doc/products#update-a-product

If you want to access the value of a ref in the script section, you have to use the value property.
I.e. instead of
body: {
'title': title
}
use
body: {
'title': title.value
}

Related

Why doesn't the post method work in my Vue.js Project?

I have a page in my Vue.ja project where you add products to the database in JSON Server.
Howevwe, when I fill up the form, the data does not change. Below is the code:
<template>
<form action="" #submit.prevent="submit">
<input type="text" placeholder="Product Name" name="name" v-model="name">
<input type="number" name="" id="" placeholder="Price in USD" v-model="price">
<input type="button" value="Add Product">
</form>
</template>
<script>
import { ref } from "vue";
import { useRouter } from "vue-router";
export default {
name: "ProductCreate",
setup() {
const name = ref("");
const price = ref("");
const router = useRouter();
const submit = async () => {
await fetch("http://localhost:3000/products", {
method: "POST",
headers: { "Content-type": "application/json" },
body: JSON.stringify({ id: (Math.random() * 10000000000000000n), name: name.value, price: price.value })
});
await router.push("admin/products");
};
return { name, price, submit };
}
};
</script>
Why doesn't it work?
The add button should of type submit
<input type="submit" value="Add Product">
👆

how to upload complete excel file into server using vuejs

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>

Get newest data after submit data without page reload using vue script setup + axios

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>

Losing my data when i refresh page in vuejs

I'm creating a social network for project in my formation, i have a like system and it work.
i have a components cardArticle with all info and i try to do a like count. It work but when i refresh the page or going on other page, i lost all my data likes (my data is not saved)
components/CardArticle.vue
<template>
<div id="card">
<div>
<a class="cardLink">
<img class="card-img" v-if="post.imageUrl !== undefined" :src="post.imageUrl" />
<h2 class="cardTitle"> {{ post.title }}</h2>
<p class="cardDescription"> {{ post.description }}</p>
</a>
</div>
<div class="buttonIcon">
<div>
<button type="button" class="buttonDelete" id="buttonDelete" #click="deletePost"
v-if="this.post.userId === this.user.userId || this.user.isAdmin === true">Supprimer</button>
<button type="button" class="buttonEdit" id="buttonEdit" #click="modifyPost"
v-if="this.post.userId === this.user.userId || this.user.isAdmin === true">
Editer
</button>
</div>
<div class="divIconLike">
<div class="iconLike">
<a #click="sendLike">
<i class="fa-regular fa-thumbs-up"></i>
</a>
</div>
<div class="countLike">
<p> {{ likes }} </p>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from "axios";
import router from "../router/index.js";
export default {
name: 'CardArticle',
data () {
return {
likes: 0
}
},
props: {
post: {
type: Object
}
},
computed: {
user() {
return this.$store.getters.user;
}
},
methods: {
sendLike() {
axios.post("http://localhost:3000/api/articles/" + this.post._id + "/like", {
userId: this.user.userId
}, {
headers: {
Authorization: "Bearer " + this.user.token
}
})
.then(response => this.likes = response.data.article.likes)
.catch(error => console.log(error))
}
}
}
</script>
views/home.vue
<template>
<div class="home" v-if="this.user.token !== null">
<CardArticle v-for="post in allPosts" v-bind:key="post.id" :post="post" />
</div>
</template>
<script>
import CardArticle from "../components/CardArticle.vue"
import axios from "axios";
export default {
name: 'HomeArticle',
data () {
return {
post: {
title: "",
description: "",
imageUrl: ""
},
allPosts: [],
}
},
computed: {
user() {
return this.$store.getters.user;
}
},
components: {
CardArticle,
},
mounted() {
axios.get("http://localhost:3000/api/articles", {
headers: {
Authorization: "Bearer " + this.user.token
}
})
.then(response => {
this.allPosts = response.data;
})
.catch(error => {
return error;
})
}
}
</script>
What i should do for not losing my data ?
I would not use vuex or localstorage for that if possible, you have idea ?
Thanks for your help
If you loading data from server, then refresh page, you always will be lose data, because browser loading page again from server, and application will load data again.
If you don't want use vuex (but why not?), you can write data to cookies (by setting cookie value), then load it on app startup (when page is loaded). But it's not best practice at all. You can use vue3-cookies lib (link).
By the way, better learn to use stores, most progressive, I think, is Pinia.
Check: https://pinia.vuejs.org/
i lost all my data likes (my data is not saved)
likes is belong to each articles and It should have been saved to your db and call API to retrieve it again on component mounting:
export default {
name: 'CardArticle',
data () {
return {
likes: 0 // It's not managed by component state
}
},
methods: {
sendLike() {
axios.post("http://localhost:3000/api/articles/" + this.post._id + "/like", {
userId: this.user.userId
}, {
headers: {
Authorization: "Bearer " + this.user.token
}
})
.then(
// invalidates, update allPosts props (emit to parent)
)
.catch(error => console.log(error))
}
}
}

get value from child component Vuejs

This is my LoggedUser component which return the name of the logged user and its scope. the name will be displayed in the side bar and the scope will be used to display countries whom under the user's scope
<template>
{{ message }}
</template>
<script lang="ts">
import { onMounted, ref } from 'vue';
export default {
name: "LoggedUser",
setup() {
const message = ref('You are not logged in!');
const scope = ref ('');
onMounted(async () => {
let token = '??';
const response = await fetch('https://localhost:44391/api/Auth/User', {
headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' +
token },
credentials: 'include'
});
const content = await response.json();
message.value = `Hi ${content.name}`;
scope.value = `${content.scope}`;
});
return {
message,
scope
}
}
}
{{message}}is used in the sideBar component but i need scope in my Home.vue to use it in a test.
Here is my Home.vue component
<template>
<div class="container w-75" v-show="showGrid">
<search-bar v-show="searchbar"></search-bar>
<div class="row" style="width:900px; height:900px; padding-left:200px">
<div class="col-md-4" v-for="country of countries" v-bind:key="country">
<div class="card p-3" style="cursor:pointer">
<router-link :to="{ path: '/FetchData', query: { query: country.countryName }}">
<div class="d-flex flex-row mb-3">
<div class="d-flex flex-column ml-2"><span>{{country.countryId}}</span></div>
</div>
<h6 style="text-align:left">{{country.countryName}}</h6>
</router-link>
<div class="d-flex justify-content-between install mt-3">
</div>
</div>
<br /><span v-if="!countries"><img src="../assets/loader.gif" /></span><br />
</div>
this is the vue part. I want to test user scope == country scope
<script>
import axios from 'axios'
import SearchBar from './SearchBar.vue'
import SideBar from './SideBar.vue'
import LoggedUser from './LoggedUser.vue'
import swal from 'sweetalert';
import '#trevoreyre/autocomplete-vue/dist/style.css'
export default {
name: "Home",
components: {
SearchBar,
SideBar,
LoggedUser
},
data() {
return {
countries: [],
showGrid: true,
}
},
methods: {
getCountries() {
let country = this.$route.query.query
if (!country) {
axios.get("https://localhost:44391/api/Pho/GetCountries")
.then(res => this.countries = res.data)
} else {
axios.get("https://localhost:44391/api/Pho/GetCountries?country=" + this.$route.query.query)
.then(res => this.countries = res.data);
this.searchbar = false;
}
},
I need to get scope value in Home.vue from LoggedUser.vue. How could i do it?
you have multiple options, one to put the api call to home, second option would be to use composition api and share a common state between these components and the third option would be to use a store management tool such as pinia or vuex.
Composition api would probably be the simplest solution. You basically just need to set a variable outside of the function that will be used in setup, short code example:
const cart = ref({})
function useCart () {
// super complicated cart logic
return {
cart: computed(() => cart.value)
}
}
you still need to adjust this snippet to your needs it was just to show you a way
you can watch this talk by Vanessa Otto to hear more about how it works: https://www.youtube.com/watch?v=MgtQ9t74mhw