This is a React Js project that is using Axios, Cors, Express, and Node JS connecting to an SQL database.
I am trying to get the data from an SQL table and have it show on the screen either in a div or p tag each row on its own line. At this time I am able to get it to console.log inside my VS Code terminal from my server.js side as well as console log the data inside my browser console from my frontend of ProductList.js. I do not get any errors in any of my consoles just the data that I would like displayed on the screen.
The below is my server.js
const bodyParser = require('body-parser');
const express = require('express');
cors = require('cors');
const app = express();
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }))
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/collectors', function (req, res) {
var sql = require("mssql");
const config = {
user: 'XXXXXXX',
password: 'XXXXXXX',
server: 'XXXXXXX',
database: 'XXXXXXX',
options: {
trustServerCertificate: true,
trustedConnection: false,
enableArithAbort: true
},
}
sql.connect(config).then(pool => {
return pool.request()
.query('select * from CollectorAssignment.tCollectors ').then(result => {
console.dir(result)
res.send(result)
})
}).catch(err => {
console.log("error at line24: ", err)
})
sql.on('error', err => {
console.log("error at line28: ", err)
})
});
app.listen(5000, () => {
console.log('listening on port 5000')
});
The below is my ProductList.js
import React from "react";
import axios from 'axios';
class ProductList extends React.Component {
state = {
loading: true,
error: "",
data: []
};
componentDidMount() {
this.getCollectorList();
}
getCollectorList = () => {
this.setState({ loading: true });
return axios
.get(
'http://localhost:5000/collectors'
)
.then(result => {
console.log(result);
this.setState({
CollectorList: result.data.items,
loading: false,
error: false
});
})
.catch(error => {
console.error("error: ", error);
this.setState({
error: `${error}`,
loading: false
});
});
};
render() {
const { loading, error, data } = this.state;
if (loading) {
return <p className="productList">Loading ...</p>;
}
if (error) {
return (
<p className="productList">
There was an error loading the collectors.{" "}
<button onClick={this.loadData}>Try again</button>
</p>
);
}
return (
<div className="productList">
<h1>Collector List</h1>
{data.map(result => <p className="productList">{result.CollectorList}</p>)}
</div>
);
}
}
export default ProductList;
Screenshot of my VS Code console data I get the same info in my browser console which is a total of 16 rows of data that I need displayed on the screen
I have gotten this to start working for me here are the changes I have made to the two files I provided. I was calling a few areas improperly and found that I was looking at some ways for SQL and I am using SQL so some connections to the DB were different which caused some issues small syntax things mainly.
Server.js
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const config = require('./src/dbfiles/dbConfig')
const app = express();
app.use(cors());
app.use(bodyParser.json({ extended: true }));
var sql = require("mssql");
app.get('/getCollectors', (req, res) => {
sql.connect(config).then(pool => {
return pool.request()
.query('SELECT * FROM CollectorAssignment.tCollectorsTest').then(result => {
res.send(result.recordset)
})
})
})
app.post('/addCollector', function (req, res) {
sql.connect(config).then(pool => {
return pool.request()
.query(`INSERT INTO CollectorAssignment.tCollectorsTest
(
Active,
FirstName,
MiddleInitial,
LastName,
CollectorCode,
CreationDate,
CollectionTeamID
) VALUES (
${req.body.Active},
'${req.body.FirstName}',
'${req.body.MiddleInitial}',
'${req.body.LastName}',
'${req.body.CollectorCode}',
'${req.body.CreationDate}',
1
)`)
.then(result => {
res.send(result)
})
})
});
app.post('/updateCollector', function (req, res) {
sql.connect(config).then(pool => {
return pool.request()
.query(`UPDATE CollectorAssignment.tCollectorsTest
SET ${req.body} = ${req.body}
WHERE ${req.body} = ${req.body}
`)
.then(result => {
res.send(result)
})
})
});
app.delete('/deleteCollector/:CollectorID', (req, res) => {
sql.connect(config).then(pool => {
return pool.request()
.query(`DELETE FROM CollectorAssignment.tCollectorsTest WHERE CollectorID = ${req.params.CollectorID}`).then(result => {
res.send(result.recordset)
})
})
})
app.listen(5000, () => {
console.log('running on port 5000');
})
ProductList.js
import "./userList.css";
import React from "react";
import axios from 'axios';
import { Link } from "react-router-dom";
import { DeleteOutline, Edit } from "#material-ui/icons";
class UserList extends React.Component {
state = {
Collectors: '',
collectorList: []
}
componentDidMount() {
this.getCollectors()
}
getCollectors = () => {
axios.get('http://localhost:5000/getCollectors')
.then((result) => result.data)
.then((result) => {
this.setState({collectorList: result});
});
};
render() {
return (
<div className="userList">
<h3>Collectors</h3>
<table className="blueTableHeaders">
<thead>
<tr>
<th>Active</th>
<td>Collectors</td>
<td>Aging Bucket</td>
<td>Program Code</td>
<td>Finance Company</td>
<td></td>
</tr>
</thead>
</table>
{this.state.collectorList.map((Collectors) => (
<div>
<table className="blueTableData">
<thead>
<tr>
<th><input type="checkbox" name="Active" defaultChecked={Collectors.Active === false ? false : true}/></th>
<td>{Collectors.FirstName} {Collectors.LastName} | {Collectors.CollectorCode}</td>
<td>
<input type="checkbox" />
<input type="checkbox" />
<input type="checkbox" />
<input type="checkbox" />
</td>
<td>
<input type="checkbox" />
<input type="checkbox" />
<input type="checkbox" />
<input type="checkbox" />
</td>
<td>
<input type="checkbox" />
<input type="checkbox" />
<input type="checkbox" />
</td>
<td>
<Link to="/updateUser:CollectorID">
<Edit className="editCollector" />
</Link>
<Link to="/deleteUser:CollectorID">
<DeleteOutline className="deleteCollector"/>
</Link>
</td>
</tr>
</thead>
</table>
</div>
))}
<Link to="/newUser">
<button className="userListAddButton">Add Collector</button>
</Link>
<Link to="/deleteUser">
<button className="userListDeleteButton">Delete Collector</button>
</Link>
</div>
);
}
}
export default UserList;
Related
I cannot find any examples using composition api for this and could use some direction. I have a q-select which passes options as a prop using a axios request. The data is in this form:
[{description: "Apple Inc.", displaySymbol: "AAPL"}, {description: "Microsoft", displaySymbol: "MSFT"}]
I have about 20000 records in this JSON response. I am able to display it all in a v-select using:
<q-select
class="grey-7"
filled
v-model="addStockSymbol"
use-input
input-debounce="0"
label="Add New Stock Symbol"
:options="stockTickers"
option-label="description"
option-value="displaySymbol"
#blur="addPosition"
#filter="filterFn"
behavior="menu"
>
<template v-slot:no-option>
<q-item>
<q-item-section class="text-grey">
No results
</q-item-section>
</q-item>
</template>
</q-select>
My issue is I do not know how to setup the filter and update function so I can search this. So far I have the code below but the examples on quasar do not use any arrays with objects but rather simple arrays. So I am wondering how do I approach this?
<script>
import {watch, ref, defineComponent,onMounted} from 'vue'
import {usePortfolioStore} from '../stores/portfolio-store'
import {storeToRefs} from 'pinia'
import {finnhubAPI} from 'boot/axios'
export default defineComponent({
name: 'UploadPositions',
components: {
},
setup () {
//v-models
const addStockSymbol = ref('')
const addShareCount = ref('')
const stockTickers = ref([])
const loadData = () => {
finnhubAPI.get('/api/v1/stock/symbol?exchange=US&token=tedkfjdkfdfd')
.then((response) => {
stockTickers.value = response.data
})
.catch(() => {
console.log('API request failed')
})
}
const filterFn = (val, update) => {
if (val === '') {
update(() => {
stockTickers.value =
})
return
}
}
update(() => {
const needle = val.toLowerCase()
this.options = stringOptions.filter(v => v.toLowerCase().indexOf(needle) > -1)
})
//add on mount API request
onMounted(() => {
loadData()
})
return {
addStockSymbol, addShareCount, portfolio, addPosition, deletePosition,
loadData, stockTickers, modifyTickerData, filterFn, update
}
}
})
</script>
Basically you need to store a complete copy of the response data and keep that around, untouched, so that each time the filter function is called you can filter off of that, looking within its objects for the label prop.
When setting up refs:
//v-models
const addStockSymbol = ref('')
const addShareCount = ref('')
const stockTickers = ref([])
const allResponseData= ref([]) // <-- add this one
Then your loadData function:
const loadData = () => {
finnhubAPI.get('/api/v1/stock/symbol?exchange=US&token=cc8ffgiad3iciiq4brf0')
.then((response) => {
const responseData = response.data.map((item) => ({label: item.description, value: item.displaySymbol}));
allResponseData.value = [...responseData];
stockTickers.value = [...responseData];
})
.catch(() => {
console.log('API request failed')
})
}
Then in your filter function:
const filterFn = (val, update, abort) => {
update(() => {
const needle = val.toLowerCase()
stockTickers.value = allResponseData.value.filter(option => {
return option.label.toLowerCase().indexOf(needle) > -1
})
})
}
See it in action:
const { ref } = Vue
const stringOptions = [
{label: 'Google', value: "goog"}, {label:'Facebook',value:'fb'}, {label:'Twitter', value: "twit"},{label: 'Apple', value: 'App'}]
const app = Vue.createApp({
setup () {
const options = ref(stringOptions)
return {
model: ref(null),
options,
filterFn (val, update, abort) {
update(() => {
const needle = val.toLowerCase()
options.value = stringOptions.filter(option => {
return option.label.toLowerCase().indexOf(needle) > -1
})
})
}
}
}
})
app.use(Quasar, { config: {} })
app.mount('#q-app')
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons" rel="stylesheet"/>
<link href="https://cdn.jsdelivr.net/npm/quasar#2.7.7/dist/quasar.min.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/vue#3/dist/vue.global.prod.js"></script>
<script src="https://cdn.jsdelivr.net/npm/quasar#2.7.7/dist/quasar.umd.prod.js"></script>
<!--
Forked from:
https://quasar.dev/vue-components/select#example--basic-filtering
-->
<div id="q-app" style="min-height: 100vh;">
<div class="q-pa-md">
<div class="q-gutter-md row">
<q-select
filled
v-model="model"
use-input
hide-selected
fill-input
input-debounce="0"
:options="options"
#filter="filterFn"
hint="Basic filtering"
style="width: 250px; padding-bottom: 32px"
>
<template v-slot:no-option>
<q-item>
<q-item-section class="text-grey">
No results
</q-item-section>
</q-item>
</template>
</q-select>
</div>
</div>
</div>
Im trying to insert some data into a SQL table but Im getting nothing from the front or back end I have tried console.log at various intervals but I cant seem to get data from either side.
For reference I have table called products with three columns id, name, image Im trying to insert both name and image with a button click. Additionally im trying to delete data thats been inserted and that also does nothing.
I have already achieved this with one table but that table only has one column.
Heres the front end
import React, {useState, useEffect} from 'react';
import axios from 'axios';
import Helmet from 'react-helmet';
export default function Products() {
const [rows, setRows] = useState([]);
const [name, setName] = useState('');
const [src, setSrc] = useState('');
useEffect(() => {
axios.get('/products/get')
.then(res => {
setRows(res.data);
}).catch(err => {
console.log(err);
});
});
//Insert into database api request
const insertRow = () => {
axios.post('/products/insert', {
row: {name: name, image: src}
});
console.log(name, src);
};
//Delete from database api request
const deleteRow = () => {
axios.delete(`/products/delete/${name, src}`);
};
return (
<>
<Helmet>
<title>Title | products</title>
</Helmet>
<div className="pt-36 sm:pt-44 pb-20 md:pb-48 max-w-[1200px] mx-5 lg:mx-auto">
<input className="border-2 border-black p-1" type="text" onChange={setName} />
<input className="border-2 border-black p-1" type="text" onChange={setSrc} />;
<button className="border-2 border-l-0 border-black p-1" onClick={insertRow}>Submit</button>
{rows.map((row, index) => {
return (
<div key={index}>
<p>{row.name}</p>
<img src={row.image} alt={row.name} />
<button onClick={() => {deleteRow(row)}}>Delete</button>
</div>
)
})}
</div>
</>
);
};
And the back end
const express = require('express');
const cors = require('cors');
const db = require('./config/db');
const app = express();
const PORT = process.env.PORT || 8080;
//Dependencies
app.use(express.json());
app.use(cors());
//#region Products table
app.get('/products/get', (req, res) => {
const selectAll = 'SELECT * FROM products';
db.query(selectAll, (err, rows) => {
if (err) throw err;
res.send(rows);
});
});
//Insert into database
app.post('/products/insert', (req, res) => {
const row = req.body.row; //Row to insert
const insertRow = "INSERT INTO products (name, image) VALUES (?, ?)"; //Insert query
db.query(insertRow, [row], (err, rows) => { //Insert row into database
if (err) throw err;
console.log('inserted: ' + row); //Print row inserted
});
console.log(row);
});
//Delete from database
app.delete('/products/delete/:row', (req, res) => {
const row = req.params.row;
const deleteRow = "DELETE FROM products WHERE name = ?";
db.query(deleteRow, [row], (err, rows) => {
if (err) throw err;
console.log('deleted: ' + row);
});
});
//#endregion
//Server port
app.listen(process.env.PORT || PORT, () => {
console.log('Server started on port ' + PORT);
});
You have a problem in your frontend code, the setName and setSrc are done improperly:
return (
<input className="border-2 border-black p-1" type="text" onChange={setName} />
<input className="border-2 border-black p-1" type="text" onChange={setSrc} />;
)
Here's how it should be:
return (
<input className="border-2 border-black p-1" type="text" onChange={(event) => setName(event.target.value)} />
<input className="border-2 border-black p-1" type="text" onChange={(event) => setSrc(event.target.value)} />;
)
I'm working on a website that uses vue and firebase. After the authentication part the user gets to the dashboard where there is the list of his projects that are a subcollection of the user document in firestore.
I made a pinia store that manages this data and each time a project is created with the form or gets deleted the state.projects updates with the new array of projects that gets cycled to display the list in the view.
Inside the view I have access to the store.projects thanks to a getter that should be reactive but when I add or delete a project nothing happens in the view, but still the state.projects gets updated.
here is the code of the DashboardView.vue:
<template>
<MainHeader mode="dashboard" />
<main class="main">
<div class="main__container">
<section class="main__section">
<div class="section__header">
<h1 class="header__title">Projects</h1>
<!-- <TextInput type="text" placeholder="Search" v-model="filter" /> -->
</div>
<div class="section__content">
<ul class="content__list">
<li
v-for="project in projects"
:key="project.id"
class="content__item"
>
{{ project.id }}
<!-- <router-link
:to="{ name: 'ProjectView', params: { id: project.id} }">
</router-link> -->
<SimpleButton #click="deleteProject(project.id)" type="button" text="delete" />
</li>
</ul>
</div>
<div class="section__footer">
<form #submit.prevent="createProject">
<TextInput type="text" placeholder="name" v-model="form.id" />
<TextInput type="text" placeholder="website" v-model="form.website" />
<SimpleButton type="submit" text="Add" />
</form>
</div>
</section>
</div>
</main>
</template>
<script>
import { useUserDataStore } from "../stores/UserDataStore.js";
import MainHeader from "../components/MainHeader.vue";
import SimpleButton from "../components/SimpleButton.vue";
import TextInput from "../components/TextInput.vue";
import { ref } from '#vue/reactivity';
export default {
name: "DashboardView",
components: {
MainHeader,
SimpleButton,
TextInput,
},
setup() {
// const filter = "";
const form = ref({});
const userDataStore = useUserDataStore();
const projects = userDataStore.getProjects;
const createProject = () => {
userDataStore.createProject(form.value)
}
const deleteProject = (id) => {
userDataStore.deleteProject(id)
}
return {
projects,
form,
createProject,
deleteProject,
};
},
};
</script>
And here the pinia store code:
import { defineStore } from "pinia";
import router from "../router";
import { db } from '../firebase';
import { doc, setDoc, getDoc, getDocs, collection, deleteDoc } from 'firebase/firestore'
export const useUserDataStore = defineStore('UserDataStore', {
state: () => {
userData: { }
projects: []
uid: null
},
actions: {
createNewUser(uid, name) {
setDoc(doc(db, "users", uid), {
name
})
.then(() => {
this.fetchUserData(uid)
})
.catch((error) => console.log(error))
},
fetchUserData(uid) {
this.uid = uid
// Fetch user doc with uid
getDoc(doc(db, "users", uid))
.then((response) => {
this.userData = response.data()
// Fetch user projects
getDocs(collection(db, "users", uid, "projects"))
.then((response) => {
const projectsArray = []
response.forEach(el => {
projectsArray.push({ data: el.data(), id: el.id})
})
this.projects = projectsArray
console.log(this.projects);
router.push({ name: 'DashboardView' })
})
})
.catch((error) => console.log(error))
},
createProject(details) {
const { id, website } = details
setDoc(doc(db, "users", this.uid, "projects", id), {
website
}).then(() => {
console.log('created');
this.fetchUserData(this.uid)
})
.catch((err) => console.log(err))
},
deleteProject(id) {
deleteDoc(doc(db, "users", this.uid, "projects", id))
.then(() => {
console.log('deleted');
this.fetchUserData(this.uid);
})
.catch(err => console.log(err))
}
},
getters: {
getProjects: (state) => state.projects
}
})
A store is reactive object, the reactivity of store property is disabled at the time when it's accessed in setup function:
const projects = userDataStore.getProjects;
It should be either:
const projects = computed(() => userDataStore.getProjects);
Or:
const { getProjects: projects } = storeToRefs(userDataStore);
I created a server with express and have some get/post routes.
In the login page, I have a page that shows the form to login:
app.get("/login", (req, res) => {
res.send(`<h1>Iniciar sesión</h1>
<form method='post' action='/login'>
<input type='email' name='email' placeholder='Email' required />
<input type='password' name='password' placeholder='Contraseña' required />
<input type='submit' value='Ingresar' />
</form>
<a href='/register'>Registrarse</a`);
});
Then I have a Post method in which I set the cookies:
app.post("/login", (req, res) => {
const { email, password } = req.body;
const user = users.filter(
(e) => e.email === email && e.password === password
);
if (user.length >= 1) {
res.cookie("userId", user.id);
res.cookie("password", user.password);
res.redirect("/home");
} else {
console.log("contraseña incorrecta");
res.redirect("/login");
}
});
The problem is that when I go to this route, the user.name and user.email are undefined. In other words, I can´t acces to the cookie:
app.get("/home", (req, res) => {
const id = req.cookies.userId;
console.log(id); //this is undefined
const user = users.filter((u) => u.id === id);
//console.log(user);
res.send(`
<h1>Bienvenido ${user.name}</h1>
<h4>${user.email}</h4>
<a href='/'>Inicio</a>
`);
});
Advices?
Here is the complete code:
const express = require("express");
const morgan = require("morgan");
const cookieparser = require("cookie-parser");
const bodyparser = require("body-parser");
const app = express();
const users = [
{ id: 1, name: "Franco", email: "Franco#mail.com", password: "1234" },
{ id: 2, name: "Toni", email: "Toni#mail.com", password: "1234" },
];
app.use(morgan("dev"));
app.use(cookieparser());
app.use(bodyparser.urlencoded({ extended: true }));
app.use((req, res, next) => {
console.log(req.cookies);
next();
});
app.get("/", (req, res) => {
res.send(`
<h1>Bienvenidos a Henry!</h1>
${
req.cookies.userId
? `<a href='/home'>Perfil</a>
<form method='post' action='/logout'>
<button>Salir</button>
</form>
`
: `
<a href='/login'>Ingresar</a>
<a href='/register'>Registrarse</a>`
}
`);
});
app.get("/register", (req, res) => {
res.send(`<h1>Registrarse</h1>
<form method='post' action='/register'>
<input name='name' placeholder='Nombre' required />
<input type='email' name='email' placeholder='Email' required />
<input type='password' name='password' placeholder='Contraseña' required />
<input type='submit' value='Registrarse' />
</form>
<a href='/login'>Iniciar sesión</a>`);
});
app.get("/login", (req, res) => {
res.send(`<h1>Iniciar sesión</h1>
<form method='post' action='/login'>
<input type='email' name='email' placeholder='Email' required />
<input type='password' name='password' placeholder='Contraseña' required />
<input type='submit' value='Ingresar' />
</form>
<a href='/register'>Registrarse</a`);
});
app.post("/login", (req, res) => {
const { email, password } = req.body;
const user = users.filter(
(e) => e.email === email && e.password === password
);
if (user.length >= 1) {
res.cookie("userId", user.id);
res.cookie("password", user.password);
res.redirect("/home");
} else {
console.log("contraseña incorrecta");
res.redirect("/login");
}
});
app.get("/home", (req, res) => {
const id = req.cookies;
console.log(id);
const user = users.filter((u) => u.id === id);
//console.log(user);
res.send(`
<h1>Bienvenido ${user.name}</h1>
<h4>${user.email}</h4>
<a href='/'>Inicio</a>
`);
});
app.listen(3000, (err) => {
if (err) {
console.log(err);
} else {
console.log("Listening on localhost:3000");
}
});
Part of your problem is that this code:
const user = users.filter(
(e) => e.email === email && e.password === password
);
produces an Array. So, user is an array.
Therefore when you do this:
res.cookie("userId", user.id);
res.cookie("password", user.password);
Both user.id and user.password are ignoring the match you got in user[0] and are referring to non-existent properties on the user array object. They will end up undefined and thus why res.cookie() is not setting a meaningful value.
You should, instead be doing this:
res.cookie("userId", user[0].id);
res.cookie("password", user[0].password);
But, please don't put a password in a user's cookie. There should be no reason to ever do that. Even more so when it's in plain text. If you want to know if the previous user is logged in or not, then use a cryptographically secure token in the cookie (like something express-session uses). Don't put their password in a cookie.
I'm following a tutorial to build a full stack app using VueJS and the MEVN stack. I have
a) built mongo db
b) build api back end with one mongoose model 'Student'
c) got the back end api running at localhost:4000/api
d) got the front end running with VueJS and Axios to read data from
the api
e) got READ, CREATE and DELETE working fine from my VueJS app
f) UPDATE is not working
g) Postman PUT is working fine though, so I know the back end is
fine.
Back end routes are
const express = require('express');
const studentRoute = express.Router();
// model
let StudentModel = require('../models/Student');
studentRoute.route('/create-student').post((req, res, next) => {
console.log('creating one student at /create-student')
StudentModel.create(req.body, (error, data) => {
if (error) {
return next(error)
} else {
console.log(`student created ${JSON.stringify(data)}`)
res.json(data)
}
})
});
studentRoute.route('/').get((req, res, next) => {
console.log('GET all students')
StudentModel.find((error, data) => {
if (error) {
return next(error)
} else {
res.json(data)
}
})
})
studentRoute.route('/edit-student/:id').get((req, res, next) => {
console.log('get one student at /edit-student/:id')
StudentModel.findById(req.params.id, (error, data) => {
if (error) {
return next(error)
} else {
res.json(data)
}
})
})
// Update
studentRoute.route('/update-student/:id').post((req, res, next) => {
console.log(`attempting to update one student with id ${req.params.id}`)
console.log(`request body = `)
console.log(JSON.stringify(req.body))
console.log(req.body)
StudentModel.findByIdAndUpdate(req.params.id,
{ $set: req.body },
(error, data) => {
if (error) {
console.log(`an error has taken place`)
return next(error);
} else {
res.json(data)
console.log('Student successfully updated!')
}
})
})
// Delete
studentRoute.route('/delete-student/:id').delete((req, res, next) => {
console.log('delete one student at /delete-student/:id')
StudentModel.findByIdAndRemove(req.params.id, (error, data) => {
if (error) {
return next(error);
} else {
res.status(200).json({
msg: data
})
}
})
})
module.exports = studentRoute;
front end update code is
<template>
<div class="row justify-content-center">
<div class="col-md-6">
<h3 class="text-center">Update Student</h3>
<form #submit.prevent="handleUpdateForm">
<div class="form-group">
<label>Name</label>
<input type="text" class="form-control" v-model="student.name" required>
</div>
<div class="form-group">
<label>Email</label>
<input type="email" class="form-control" v-model="student.email" required>
</div>
<div class="form-group">
<label>Phone</label>
<input type="text" class="form-control" v-model="student.phone" required>
</div>
<div class="form-group">
<button class="btn btn-danger btn-block">Update</button>
</div>
</form>
</div>
</div>
</template>
<script lang="ts">
import { Vue } from 'vue-class-component';
import axios from "axios";
export default class EditComponent extends Vue {
student!: {
name: '',
email: '',
phone: ''
}
data() {
return {
student: { }
}
}
created() {
let apiURL = `http://localhost:4000/api/edit-student/${this.$route.params.id}`;
axios.get(apiURL).then((res) => {
this.student = res.data;
})
}
handleUpdateForm() {
let id = this.$route.params.id
let apiURL = `http://localhost:4000/api/update-student/${this.$route.params.id}`;
console.log(`attempt to update student at url`)
console.log(apiURL)
console.log(`with id`)
console.log(id)
console.log(`attempt to update student ${JSON.stringify(this.student)}`)
axios.put(apiURL, this.student)
.then(res => {
console.log(`response is ${res}`)
this.$router.push('/view')
})
.catch(error => {
console.log('error when updating student')
console.log(error)
});
}
}
</script>
when I use Postman I get this response from the api
attempting to update one student with id 6119d671cc9ce131207bd37c
request body =
{"_id":"6119d671cc9ce131207bd37c","name":"PHIL","email":"philanderson888#hotmail.com","phone":7888849991,"__v":0}{ _id: '6119d671cc9ce131207bd37c',
name: 'PHIL',
email: 'philanderson888#hotmail.com',
phone: 7888849991,
__v: 0 }
Student successfully updated!
when I use VueJS to update my Student I get the following error from this code
// Update
studentRoute.route('/update-student/:id').post((req, res, next) => {
console.log(`attempting to update one student with id ${req.params.id}`)
console.log(`request body = `)
console.log(JSON.stringify(req.body))
console.log(req.body)
StudentModel.findByIdAndUpdate(req.params.id,
{ $set: req.body },
(error, data) => {
if (error) {
console.log(`an error has taken place`)
return next(error);
} else {
res.json(data)
console.log('Student successfully updated!')
}
})
})
attempt to update student at url
EditComponent.vue?720f:29 http://localhost:4000/api/update-student/6119d671cc9ce131207bd37c
EditComponent.vue?720f:30 with id
EditComponent.vue?720f:31 6119d671cc9ce131207bd37c
EditComponent.vue?720f:32 attempt to update student {"_id":"6119d671cc9ce131207bd37c","name":"PHIL","email":"phil#phil.com","phone":123,"__v":0}
xhr.js?b50d:177 PUT http://localhost:4000/api/update-student/6119d671cc9ce131207bd37c 404 (Not Found)
dispatchXhrRequest # xhr.js?b50d:177
xhrAdapter # xhr.js?b50d:13
dispatchRequest # dispatchRequest.js?5270:52
Promise.then (async)
request # Axios.js?0a06:61
Axios.<computed> # Axios.js?0a06:87
wrap # bind.js?1d2b:9
handleUpdateForm # EditComponent.vue?720f:33
eval # EditComponent.vue?2308:5
eval # runtime-dom.esm-bundler.js?830f:1400
callWithErrorHandling # runtime-core.esm-bundler.js?5c40:6988
callWithAsyncErrorHandling # runtime-core.esm-bundler.js?5c40:6997
invoker # runtime-dom.esm-bundler.js?830f:347
EditComponent.vue?720f:39 error when updating student
EditComponent.vue?720f:40 Error: Request failed with status code 404
at createError (createError.js?2d83:16)
at settle (settle.js?467f:17)
at XMLHttpRequest.handleLoad (xhr.js?b50d:62)
I'm aware mongo has updated their methods for handling updates and have tried the following
1)
StudentModel.findByIdAndUpdate(req.params.id,
{ $set: req.body },
(error, data) => {
StudentModel.findOneAndUpdate({_id:req.params.id},
{ $set: req.body },
(error, data) => {
StudentModel.updateOne({_id:req.params.id},
{ $set: req.body },
(error, data) => {
In each case I am getting the error above and in each case Postman works fine. So there's a problem with the URL being formed and I'm not sure what it is???
Your help would be appreciated!
Thank you
Philip
Also, just in case it is relevant, here is the back end app.js
let express = require('express'),
cors = require('cors'),
mongoose = require('mongoose'),
database = require('./database'),
bodyParser = require('body-parser');
// Connect mongoDB
mongoose.Promise = global.Promise;
//mongoose.set('useFindAndModify',false);
mongoose.connect(database.db, {
useNewUrlParser: true,
useUnifiedTopology: true
}).then(() => {
console.log("Database connected")
},
error => {
console.log("Database could't be connected to: " + error)
}
)
const studentAPI = require('../api/routes/student.route')
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(cors());
// API
app.use('/api', studentAPI)
// Create port
const port = process.env.PORT || 4000;
const server = app.listen(port, () => {
console.log('Connected to port ' + port)
})
const logUsage = (logCode) => {
console.log(`http serving with code ${logCode}`)
}
app.use((req, res, next) => {
console.log(`logging data in 'next'`)
next(logUsage(200));
});
app.use(function (err, req, res, next) {
console.log('in app.use')
console.error(err.message);
if (!err.statusCode) err.statusCode = 500;
res.status(err.statusCode).send(err.message);
});
You can try to replace post in update route with put