How to send a delete request from Vue Js to Json server? - vue.js

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)

Related

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))
}
}
}

Vue.js 2 data not displayed in the template

I'm using vue.js 2 / vue-cli with axios. I'm facing a problem with the display of my posts (in the wall). I've made my axios request, have gotten my data (in the console), I've written my template and ... nothing was displayed ... I really appreciate your help
my template :
<template>
<v-layout column>
<v-flex xs4>
<panel title="The Wall">
<p v-for="post in posts" :key="post.index">{{ post.title }} - {{ post.content }}</p>
</panel>
</v-flex>
</v-layout>
</template>
my script :
<script>
import Panel from '../components/Panel'
import PostService from "../services/PostService.js";
export default {
components: {
Panel
},
data() {
return {
posts: null
}
},
async mounted() {
this.posts = (await PostService.getAllPosts()).data;
}
}
</script>
Add a data property called cidItem for example and bind it to your props as follows
<template>
<div id="app" class="container" :cid="cidItem">
<Images :cid="cidItem" />
<Video :cid="cidItem" />
<TextType :cid="cidItem" />
<Card :cid="cidItem" />
</div>
</template>
<script>
import axios from 'axios';
import Images from "./components/Images";
import Video from "./components/Video";
import TextType from "./components/TextType";
import Card from "./components/Card";
export default {
name: 'app',
props: ["cid"],
components: {
Images,
Video,
TextType,
Card
},
mounted() {
axios({method: "GET", "url": this.contentDeliveryUrl}).then(result => {
// eslint-disable-next-line
this.content = amp.inlineContent(result.data)[0];
console.log(this.content)
}, error => {
console.error(error);
});
},
data() {
return {
contentDeliveryUrl: 'https://c1.adis.ws/cms/content/query?fullBodyObject=true&query=%7B%22sys.iri%22%3A%22http%3A%2F%2Fcontent.cms.amplience.com%2F${this.cid}%22%7D&scope=tree&store=testing',
content: [],
cidItem:'7e4301de-9c6e-4fab-9e68-3031b94d662d'
}
}
}
</script>
Since your component have the same structure i recommend to use mixins, create a file named myMixins.js and add the following code inside it :
const myMixins = {
props:['cid'],
mounted() {
axios({
method: "GET",
"url": this.contentDeliveryUrl
}).then(result => {
// eslint-disable-next-line
this.content = amp.inlineContent(result.data)[0];
console.log(this.content)
}, error => {
console.error(error);
});
},
data() {
return {
contentDeliveryUrl: 'https://c1.adis.ws/cms/content/query?fullBodyObject=true&query=%7B%22sys.iri%22%3A%22http%3A%2F%2Fcontent.cms.amplience.com%2F${this.cid}%22%7D&scope=tree&store=testing',
content: []
}
}
}
export default mixins;
and inside each component add this :
import myMixins from './myMixins'
export default{
....
mixins: [myMixin]
}

Vue js doesn't update data on the another client

I have one simple page with input and add button. Below that I have list of all items.
<template>
<div class="page-container">
<form #submit.prevent="insertRoom" class="form-container" autocomplete="off" method="post" accept-charset="utf-8">
<h3>Add room</h3>
<label class="form-input-container" for="roomName">
<input v-model="roomName" type="text" name="roomName" spellcheck="false" placeholder="Room name">
</label>
<input class="form-button" type="submit" value="Add">
</form>
<list
:list-title="'Room list'"
:list-array="rooms"
:remove-item="deleteRoom"
/>
</div>
</template>
How to refresh list of all items on the another client? For example if I open same page on two different PC, and if I add a new item (room). On the second PC this list of rooms doesn't change till I refresh page.
<script>
import { mapActions, mapState } from 'vuex'
import List from '~/components/List.vue'
export default {
components: {
List
},
data () {
return {
roomName: null
}
},
computed: {
...mapState({
rooms: state => state.rooms
})
},
methods: {
insertRoom () {
this.addRoom({
roomName: this.roomName
})
},
deleteRoom (room) {
this.removeRoom({
roomName: room
})
},
...mapActions({
addRoom: 'addRoom',
removeRoom: 'removeRoom'
})
}
}
</script>

VueJS display dynamic modal component

I have posts and replys s.t. replies belong to posts via the attribute reply.posts_id.
I am attempting to show the reply form as a modal for the user to enter a reply. However, I want to create a generic Modal component that I can use everywhere with content that is specified in another component built for a specific context.
Reply to post is the first place I woul like this to work.
Currently, the Vuex correctly returns Modal visible:true when the reply button is clicked, but the modal does not render and I get the error message showing that the Modal component is not found:
Unknown custom element: <ModalReplyForm> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
I am using vuex to manage the visibility of the modal. Here are the relevant files:
store.js:
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
...
Vue.use(Vuex)
export default new Vuex.Store({
state: {
status: '',
...
modalVisible: false,
modalComponent: null
},
mutations: {
...
showModal(state, componentName) {
console.log('showing the modal')
state.modalVisible = true;
state.modalComponent = componentName;
},
hideModal(state) {
console.log('hiding the modal')
state.modalVisible = false;
}
},
actions: {
...
}
},
getters: {
isAuthenticated: state => !!state.user,
authStatus: state => state.status,
user: state => state.user,
token: state => state.token,
posts: state => {
return state.posts;
}
...
}
})
App.vue
<template>
<div id="app">
<app-modal></app-modal>
<NavigationBar />
<div class="container mt-20">
<router-view />
</div>
<vue-snotify></vue-snotify>
</div>
</template>
<script>
import AppModal from '#/components/global/AppModal';
import NavigationBar from '#/components/layout/NavigationBar'
export default {
name: "App",
components: {
AppModal,
NavigationBar
}
};
</script>
<style>
body {
background-color: #f7f7f7;
}
.is-danger {
color: #9f3a38;
}
</style>
Post.vue (houses the button to call the reply modal):
<template>
<div class="row ui dividing header news">
<!-- Label -->
<div class="m-1 col-md-2 ui image justify-content-center align-self-center">
<img v-if="post.avatar_url" :src="post.avatar_url" class="mini rounded"/>
<v-gravatar v-else :email="post.email" class="mini thumbnail rounded image rounded-circle z-depth-1-half"/>
</div>
<!-- Excerpt -->
<div class="col-md-9 excerpt">
...
<!-- Feed footer -->
<div class="feed-footer row">
<div class="small"> {{ post.created_at | timeAgo }}</div>
<button type="button" flat color="green" #click="showModal('ModalReplyForm')">
<i class="fa fa-reply" ></i>
...
<div v-show="postOwner(post)" class="">
<button type="button" flat color="grey" #click="deletePost(post.id)">
<i class="fa fa-trash " ></i>
</button>
</div>
</div>
</div>
</div>
</template>
<script>
import { mapMutations } from 'vuex';
import PostsService from '../../services/PostsService'
import RepliesService from '../../services/RepliesService'
import Replies from '#/components/Reply/Replies'
import ReplyForm from '#/components/Reply/ReplyForm'
export default {
name: "Post",
props: {
post: {
type: Object,
required: true
}
},
components: {
Replies,
ReplyForm
},
computed: {
me() {
return this.$store.getters.user
}
},
methods: {
...mapMutations(['showModal']),
...
}
};
</script>
AppModal.vue - generic Modal component
<template>
<div class="c-appModal">
<div class="c-appModal__overlay" v-if="visible"></div>
<div class="c-appModal__content" v-if="visible" #click.self="hideModal"></div>
<div class="c-appModal__innerContent">
<component :is="component"></component>
</div>
</div>
</template>
<script>
import Vue from 'vue';
import { mapState, mapMutations } from 'vuex';
export default {
name: 'AppModal',
data() {
return {
component: null
}
},
computed: {
...mapState({
visible: 'modalVisible',
modalComponent: 'modalComponent'
}),
},
methods: {
...mapMutations(['hideModal'])
},
watch: {
modalComponent(componentName) {
if (!componentName) return;
Vue.component(componentName, () => import(`#/components/modals/${componentName}`));
this.component = componentName;
}
},
created() {
const escapeHandler = (e) => {
if (e.key === 'Escape' && this.visible) {
this.hideModal();
}
};
document.addEventListener('keydown', escapeHandler);
this.$once('hook:destroyed', () => {
document.removeEventListener('keydown', escapeHandler);
});
},
};
</script>
ModalReplyForm - specific reply modal content
<template>
<div>
<div class="c-modalReply">
<div>
<label for="reply">Your comment</label>
<div class="field">
<textarea name="reply" v-model="reply" rows="2" placeholder="Compose reply"></textarea>
</div>
</div>
<button class="c-modalReply__cancel" #click="hideModal">Cancel</button>
<button class="c-modalReply__post" :disabled="!isFormValid" #click="createReply">Reply</button>
</div>
</div>
</template>
<script>
import RepliesService from '#/services/RepliesService'
import { mapMutations } from 'vuex';
export default {
name: "ModalReplyForm",
// props: {
// post: {
// type: Object,
// required: true
// }
// },
data() {
return {
reply: ""
};
},
computed: {
isFormValid() {
return !!this.reply;
},
currentGroup() {
return this.$store.getters.currentPost;
}
},
methods: {
...mapMutations([
'hideModal'
]),
async createReply () {
let result = await RepliesService.addReply({
reply: {
body: this.reply,
postId: this.post.id
}
});
this.$emit("reply-created");
this.hideModal();
}
}
};
</script>
Unknown custom element: - did you register the
component correctly? For recursive components, make sure to provide
the "name" option.
This message says that you never imported/defined ModalReplyForm, which you have not.
In my own generic modal, I ended up having to import all the components that might appear within the modal itself.
If you add a:
import ModalReportForm from ...
and a:
components: {
ModalReplyForm
}
to AppModal.vue, the modal should then do what you expect.

Vue.js Component emit

I have some problem about component $emit
This is my child component:
<template>
<div class="input-group mb-3 input-group-sm">
<input v-model="newCoupon" type="text" class="form-control" placeholder="code">
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="button" #click="addCoupon">comfirm</button>
</div>
</div>
</template>
<script>
export default {
props: ["couponcode"],
data() {
return {
newCoupon: this.couponcode
};
},
methods: {
addCoupon() {
this.$emit("add", this.newCoupon);
}
}
};
</script>
This is parent component
<template>
<div>
<cartData :couponcode="coupon_code" #add="addCoupon"></cartData>
</div>
</template>
<script>
import cartData from "../cartData";
export default {
components: {
cartData
},
data() {
return {
coupon_code: ""
}
},
methods:{
addCoupon() {
const api = `${process.env.API_PATH}/api/${
process.env.CUSTOM_PATH
}/coupon`;
const vm = this;
const coupon = {
code: vm.coupon_code
};
this.$http.post(api, { data: coupon }).then(response => {
console.log(response.data);
});
},
}
}
</script>
When I click the 'confirm' button,the console.log display 'can't find the coupon' 。 If I don't use the component,it will work 。
What is the problem? It's about emit?
addCoupon() {
this.$emit("add", this.newCoupon); // You emitted a param
}
// then you should use it in the listener
addCoupon(coupon) { // take the param
const api = `${process.env.API_PATH}/api/${
process.env.CUSTOM_PATH
}/coupon`;
const coupon = {
code: coupon // use it
};
this.$http.post(api, { data: coupon }).then(response => {
console.log(response.data);
});
},