How to use Axios Delete in VueJs? - node.js

Why my delete function is not working in VueJS?
I have a table that displays the data from NodeJS and renders to VueJS
<tr v-for="result in filteredPeople" :key="result.id">
<td>{{result.Memb_ID}}</td>
//other data
<div class="btn">
<button class="btn btn-success">Edit Details</button>
<b-button class="btn btn-danger" #click="deleteData(result.Memb_ID)">Delete</b-button>
</div>
and my delete data is shown below.
deleteData(result, Memb_ID) {
axios
.delete("localhost:9000/api/delete/user/" + result.Memb_ID)
.then(response => {
this.result.splice(Memb_ID, 1);
console.log(this.result);
});
},
On my server console
DELETE /api/delete/user/undefined 404 167 - 0.184 ms
This is my image of backend
I never posted all the code but if you want I'll post it. Thanks for the help!
EDIT
I added image of my backend.
EDIT 2
I updated the server image.

It is because you are passing your memId via req.params but in your backend you are using req.query.memId
you can adjust it by:
update your axios to use localhost:9000/api/delete/user?Memb_ID=${Memb_ID}
or update your backend route to router.delete('/delete/user/:Memb_ID')

Your deleteData function parameter is only one. Could you try this.
deleteData(memId) {
axios
.delete("localhost:9000/api/delete/user/" + memId)
.then(response => {
this.result.splice(memId, 1);
console.log(this.result);
});
},

Related

Angular suscribed observable don't showing information on the view

image of the detail view with console to see the console.log()
I'm having troubles making the Tour Of Heroes Angular tutorial work, i'm in the 6 step of the tutorial, getting the data from a server but instead of getting the data from a simulated data server i have a api with nodejs express and mysql.
The problem cames when i try to show the detail of the hero (fetching one by id), all seems to work but the information don't show on the view.
template:
<div *ngIf="hero">
<h2>{{ hero.name }} Details</h2>
<div>id: {{hero.id}}</div>
<div>
<label for="name">Hero name: </label>
<input id="name" [(ngModel)]="hero.name" placeholder="name">
</div>
<button type="button" (click)="goBack()">go back</button>
</div>
component:
ngOnInit(): void {
this.getHero();
}
getHero(){
const id = Number(this.route.snapshot.paramMap.get("id"));
this.heroService.getHero(id).subscribe(hero => {
this.hero = hero;
console.log("hero", hero)
})
}
service:
private heroesUrl = 'http://localhost:3300/api/';
constructor(private MessageService: MessageService, private http: HttpClient) {
}
private log(message: string) {
this.MessageService.add(`HeroService: ${message}`);
}
getHeroes(): Observable<Hero[]>{
this.log('HeroService: fetched heroes');
return this.http.get<Hero[]>(this.heroesUrl);
}
getHero(id: number): Observable<Hero> {
const url = `${this.heroesUrl}${id}`;
return this.http.get<Hero>(url);
}
I don't know what's the problem, im learning angular but the observable is well suscribed, in the attached image you can see in the console that at least the api is working.
you received an array with an unique element, see the [``] in console. So
Or in subscribe your write hero[0]
this.heroService.getHero(id).subscribe(hero => {
this.hero = hero[0];
})
Or in your service return the first element of the array. For this use rxjs/operator map
getHero(id: number): Observable<Hero> {
const url = `${this.heroesUrl}${id}`;
return this.http.get<Hero[]>(url).pipe(
map((res:Hero[])=>res[0])
);
}
See that although you say to Angular that getHero return an Observable<Hero> really you got an Observable<Hero[]>. Yes, when we indicate the return of a function this not make "magically" we get the result, only help us to write the code and the editor advise us about it

Is there any method to fetch the data from back-end MongoDB and show at front-end react JS?

I am trying to show my backend data from mongoDB into front-end and calculate the balance of a particular member
Here is the code:
export default function BuySellInfo() {
const[xnaLogData,setXnaLogData]=useState([]);
const [balance,setBalance]=useState(0);
const calBal =()=>{
var sum = xnaLogData.reduce(function(prev, current) {
return prev + +current.balance
}, 0);
setBalance(sum);
}
useEffect(() => {
async function fetchXna () {
const response = await fetch('/xnaloginforoute');
const json = await response.json();
setXnaLogData(json.xnacomp);
console.log(json.xnacomp)
console.log(xnaLogData);
}
fetchXna();
calBal();
},[]);
return (
<div>
<table className="table" style={{width:"30%",marginLeft:"3%"}}>
<tbody>
<h2 style={{textAlign:'center'}}> Buy & Sell </h2>
<tr>
<td>Member No</td>
<td>{xnaLogData[0].memberno}</td>
</tr>
<tr>
<td>XNA Balance</td>
<td>{balance}</td>
</tr>
</tbody>
The above component will fetch the data from the back-end route. Although the route is working fine with postman whenever i send the request but its showing error in the front-end . And the error is sometimes removed (which means data fetched perfectly) but on the first attempt the data is not fetched, after commenting or uncommenting the line of code : {/* <td>{xnaLogData[0].memberno}</td> */}
from above component the fetch api work. I am unable to sort out this issue.
The back-end route is :
router.get('/xnaloginforoute', async (req, res) => {
const xnacomp=await xnaLog.find({})
res.json({xnacomp});
});
What i had figured about this issue that response is not fetched in first attempt in front-end but through Postman it is working correctly. But i am unable to solve this issue.
And how to get the data or fetch is that:
First click on BuySell button to open this component
It will show error of TypeError: Cannot read properties of undefined (reading 'memberno') as i had not comment out the line { <td>{xnaLogData[0].memberno}</td> }
But then i comment the line {/* <td>{xnaLogData[0].memberno}</td> */} and the table will appear with no values as the line of code is comment out
Then i uncomment the line { <td>{xnaLogData[0].memberno}</td> } the data will be fetched perfectly and stored in usestate
I couldnt understand the things in this code.
Put this line under your useEffect and above your return:
if (!xnaLogData.length) {
return null;
}
You're fetching data for your table that's not going to be available at initial render of the component so xnaLogData[0] is undefined

Connecting Node.js with React

I am new to react and am working on my first project, I have a question on how to connect react with node.js.I have a post page where you can post data and I want to get that data in node.js so that I can connect it with MongoDB.
Here's my code
Post component
import React from "react";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import { faPlus } from "#fortawesome/free-solid-svg-icons";
import "./componentStyles/postStyles.css";
const element = <FontAwesomeIcon icon={faPlus} />;
function Post() {
return (
<div>
<h2>Post your data here</h2>
<form className="post-form">
<input className="inputTitle" name="title" placeholder="Title" />
<textarea
className="inputContent"
name="content"
placeholder="Content"
rows="3"
/>
<input
className="inputTitle"
name="contact"
placeholder="contact details"
/>
<br />
<br />
<label className="inputTitle" for="CompanyType">
Company Type:{" "}
</label>
<select>
<option value="AI">AI</option>
<option value="Stocks">Stocks</option>
<option value="Finance">Finance</option>
<option value="Medical">Medical</option>
<option value="Engineering">Engineering</option>
<option value="Construction">Construction</option>
</select>
<button className="submitBtn">{element}</button>
</form>
</div>
);
}
export default Post;
Post page
import React from "react";
import Post from "../components/Post";
const Contact = () => {
return (
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
height: "90vh",
}}
>
<Post />
</div>
);
};
export default Contact;
Thanks in advance for Answers
There's not one "standard" way of doing this. There are several ways to do it, such as:
using redux and redux middlewares like redux-saga and redux-thunk
with hooks (react-query is worth looking at)
with a simple abstract API manager
directly inside the component (not recommended)
Anyway, React is JavaScript at the end of the day, so you need a client to make HTTP requests to the API. Many use axios.
A pseudo code example:
// APIManager.js
export const getPosts = () => {
return axios.get(`${baseUrl}/posts`).then(resp => resp.data);
};
// Post.jsx
const Post = () => {
const [posts, setPosts] = useState([]);
useEffect(() => {
APIManager.getPosts().then(res => setPosts(res));
}, []);
};
Also, there are many other client libraries that you can use for this purpose.
You need to set up a nodejs environment.
Add Express or Koa to handle requests.
Add Mongodb -> use mongo atlas and add the end point to the backend. Make sure to configure your Mongodb Atlas environment to handle requests.
Add the routes that you want to your backend to handle the data exchanges.
Use Fetch or Axios on the front end to get, post, put, delete data.
There are courses and articles that cover this more in detail. I suggest checking them out, because you will need to understand some of nuances that are specific for your use case, such as working with mongodb. This post could be turned into a book, but I just wanted to help guide you in the right direction.

VueJS getting the page to accept UID & token

I'm trying to get an activation link from an email to successfully pass it's UID and token to a vue page where it'll get authenticated.
I have my folder structure set up currently like .../registration/activate/_uid/_token.vue, but that causes the registration link to bring up a 404 page.
I've tried setting up to /_uid/_token/_token.vue with the extra token to see what'll happen, and it lets token.vue render, but I don't think the params are being passed. I'm also getting a "Duplicate param keys in route with path: "/registration/activate/:uid?/:token?/:token?" error in console.
<template>
<v-container>
<v-card v-if="status === 'pending'" class="pa-8 text-center">
<p class="title">Please wait</p>
<p class="body-1">Checking registration status...</p>
</v-card>
<v-card v-if="status === 'success'" class="pa-8 text-center">
<p class="title primary--text">Activation successful</p>
<p class="body-1">You may now log in.</p>
<v-btn color="primary" text #click="navigateToLogin">Log In</v-btn>
</v-card>
<v-card v-if="status === 'error'" class="pa-8 text-center">
<p class="title error--text">Invalid activation token</p>
<p class="body-1">This token is invalid. Please try again.</p>
</v-card>
</v-container>
</template>
<script>
export default {
auth: false,
data: () => ({
status: 'pending'
}),
mounted() {
this.$axios
.post('/auth/users/activation/', this.$route.params)
.then((response) => {
this.status = 'success'
})
.catch(() => {
this.status = 'error'
})
},
methods: {
navigateToLogin() {
this.$router.push('/login')
}
}
}
</script>
Here's an example of a registration link.
http://localhost:3000/activate/MTg/5j2-d0af1770a53f1db2a851
Another part of issue that I can't quite solve, is since I'm using python for my backend should I use a python template to submit the UID and token or figure out a way to send the email where the root is localhost:3000 (my frontend) vs :8000 (my backend).
Currently my settings.py looks like this for the registration link:
'ACTIVATION_URL': 'registration/activate/{uid}/{token}',
the root is localhost:8000 for the whole API. So if I can't figure out how to manually set it to 3000 for just this link, I guess I'll need to use a template right? Any suggestions are welcome!
the problem is your path declaration. In Vue you should declare a param in path like this:
path: "/registration/activate/:uid/:token"
after this if you enter http://localhost:3000/activate/MTg/5j2-d0af1770a53f1db2a851 your this.$route.params should look like this:
{"uid":"MTg","token":"5j2-d0af1770a53f1db2a851"}
and you axios request is fine.
and because yout are sending a JSON to server if your using django you can use this code to get the body of a request:
def avtivate(request):
if request.is_ajax():
if request.method == 'POST':
print 'Raw Data: "%s"' % request.body
return HttpResponse("OK")

Cannot delete mongodb entry with node and handlebars

I tried various ways to delete a entry but no luck. I know I'm close. I did use "post" instead of "delete" with no luck. I did the action request on the html, no luck. Im in a pickle :(
My routers:
router.delete('/:id',function(req, res){
Docket.findById(req.params.id, function(err, docket){
docket.remove(function(err){
res.redirect('/dockets');
});
});
});
Handlebars:
<form name="create-docket-form" id="create-docket-form" method="post">
<div class="form-submit">
<input type="submit" name="delete" value="Delete my docket" />
</div>
</form>
In your form, you are using method method="post", but your route is listening for DELETE requests: router.delete('/:id',function(req, res){ So this router is never triggered because the app can't found the route.
I wonder, how do you send your requests, but in if you are using no JavaScript code, you can work around this by applying approach from this answer.
I did solve this problem, first, you have to change the "delete" to "get" in the "router.get()", after that, you go to HandleBars file and put a tag 'button' inside the tag '', put the 'href: '/adress/{{variable to delete}}', go to your node.js and prepare the route, now I'll show you my code:
NODE.EXPRESS / .JS:
app.get(`/del-comander/:comand`,express.json() ,(req,res)=>{
let comanderDel = req.params.comand
Comander.deleteOne({comander: comanderDel}).then(()=>{
console.log(`deleted: ${comanderDel}`)
res.redirect('back')
}).catch((err)=>{
res.send(err)
})
}),
HANDLEBARS:
{{#each comanders}}
<strong> comander: </strong>{{comander}} <br>
<strong> skill: </strong>{{skill}} <br>
<strong>season: </strong>{{season}} <br>
<a href='/del-comander/{{comander}}'><button>delete</button></a>
<br>
<hr>
{{/each}}
OBS: the args inside '{{}}' was connected with the DataBase, I also did more than just delete the data and printed it to the screen, so each data could be deleted separately, I do not know if my answer was good, but somebody else could have this same problem if you want more code just ask.

Resources