ID is not passed to edit page, getting 404 because URL shows undefined for ID in console but is right in URL - sql

The above I hope help showing the Home.js pulling the User info working properly. When I click the Edit button for either User it takes me to the edit page where the URL shows properly pulling it for ID 5. The issue is that the page loads the form properly accept it has no user data prefilled based on the ID. I get the error below the URL about the ID being undefined. This is being pulled from an SQL database and the data is being pulled from a SPROC provided below which runs the Home Page fine but for some reason is not able to get the ID to do the edit page.
Any help please to get this resolved.
Home.js
(this pulls the data fine with the same get sproc as the edit)
import axios from "axios";
import { Link } from "react-router-dom";
const Home = () => {
const [users, setUser] = useState([]);
useEffect(() => {
loadUsers();
}, []);
const loadUsers = async () => {
const result = await axios.get(`http://localhost:5000/getCollectors`);
setUser(result.data.reverse());
};
const deleteUser = async CollectorID => {
await axios.delete(`http://localhost:5000/deleteCollector/${CollectorID}`);
loadUsers();
};
return (
<div className="container">
<div className="py-4">
<h1>Home Page</h1>
<table className="table border shadow">
<thead className="thead-dark">
<tr>
<th scope="col">ID</th>
<th scope="col">Active</th>
<th scope="col">Name | Code</th>
<th scope="col">Aging Bucket</th>
<th scope="col">Program Bucket</th>
<th scope="col">Finance Company</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{users.map((user) => (
<tr key={user.CollectorID}>
{/* <th scope="row">{index + 1}</th> */}
<th scope="row">{user.CollectorID}</th>
<td></td>
<td>{user.FirstName} {user.LastName} | {user.CollectorCode}</td>
<td></td>
<td></td>
<td>{user.FinanceCompany}</td>
<td>
<Link className="btn btn-primary mr-2" to={`/users/${user.CollectorID}`}>
View
</Link>
<Link
className="btn btn-outline-primary mr-2"
to={`/users/edit/${user.CollectorID}`}
>
Edit
</Link>
<Link
className="btn btn-danger"
onClick={() => deleteUser(user.CollectorID)}
>
Delete
</Link>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
);
};
export default Home;
EditUser.js
(uses same sproc as the Home.js but trying to get by user ID which is where it breaks)
import axios from "axios";
import { useHistory, useParams } from "react-router-dom";
const EditUser = () => {
let history = useHistory();
const { CollectorID } = useParams();
const [user, setUser] = useState({
// CollectorID: '',
// ProgramBucketID: '',
// CollectorOptionsID: '',
// FinanceCompanyID: '',
Active: '',
LastName: '',
CollectorCode: '',
Aging1to15: '',
Aging31to45: '',
Aging31to60: '',
AgingOver60: '',
ProgramBucketA: '',
ProgramBucketB: '',
ProgramBucketC: '',
ProgramBucketSU: '',
FinanceCompany: ''
});
const { Active, LastName, CollectorCode, Aging1to15, Aging31to45, Aging31to60, AgingOver60, ProgramBucketA, ProgramBucketB, ProgramBucketC, ProgramBucketSU, FinanceCompany} = user;
const onInputChange = e => {
setUser({ ...user, [e.target.name]: e.target.value });
};
useEffect(() => {
loadUser();
}, []);
const onSubmit = async e => {
e.preventDefault();
await axios.put(`http://localhost:5000/UpdateUser/${CollectorID}`, user);
history.push("/");
};
const loadUser = async () => {
const result = await axios.get(`http://localhost:5000/getCollectors/${CollectorID}`);
setUser(result.data);
console.log(result.data);
};
return (
<div className="container">
<div className="w-75 mx-auto shadow p-5">
<h2 className="text-center mb-4">Edit A User</h2>
<form onSubmit={e => onSubmit(e)}>
<div className="form-group">
<input
type="text"
className="form-control form-control-lg"
placeholder="Active Status"
name="Active"
value={Active}
onChange={e => onInputChange(e)}
/>
</div>
<div className="form-group">
<input
type="text"
className="form-control form-control-lg"
placeholder="Enter Your Last Name"
name="LastName"
value={LastName}
onChange={e => onInputChange(e)}
/>
</div>
<div className="form-group">
<input
type="text"
className="form-control form-control-lg"
placeholder="Enter Your Collector Code"
name="CollectorCode"
value={CollectorCode}
onChange={e => onInputChange(e)}
/>
</div>
<div className="form-group">
<input
type="text"
className="form-control form-control-lg"
placeholder="Aging1to15"
name="Aging1to15"
value={Aging1to15}
onChange={e => onInputChange(e)}
/>
</div>
<div className="form-group">
<input
type="text"
className="form-control form-control-lg"
placeholder="Aging31to45"
name="Aging31to45"
value={Aging31to45}
onChange={e => onInputChange(e)}
/>
</div>
<div className="form-group">
<input
type="text"
className="form-control form-control-lg"
placeholder="Aging31to60"
name="Aging31to60"
value={Aging31to60}
onChange={e => onInputChange(e)}
/>
</div>
<div className="form-group">
<input
type="text"
className="form-control form-control-lg"
placeholder="AgingOver60"
name="AgingOver60"
value={AgingOver60}
onChange={e => onInputChange(e)}
/>
</div>
<div className="form-group">
<input
type="text"
className="form-control form-control-lg"
placeholder="ProgramBucketA"
name="ProgramBucketA"
value={ProgramBucketA}
onChange={e => onInputChange(e)}
/>
</div>
<div className="form-group">
<input
type="text"
className="form-control form-control-lg"
placeholder="ProgramBucketB"
name="ProgramBucketB"
value={ProgramBucketB}
onChange={e => onInputChange(e)}
/>
</div>
<div className="form-group">
<input
type="text"
className="form-control form-control-lg"
placeholder="ProgramBucketC"
name="ProgramBucketC"
value={ProgramBucketC}
onChange={e => onInputChange(e)}
/>
</div>
<div className="form-group">
<input
type="text"
className="form-control form-control-lg"
placeholder="ProgramBucketSU"
name="ProgramBucketSU"
value={ProgramBucketSU}
onChange={e => onInputChange(e)}
/>
</div>
<div className="form-group">
<input
type="text"
className="form-control form-control-lg"
placeholder="FinanceCompany"
name="FinanceCompany"
value={FinanceCompany}
onChange={e => onInputChange(e)}
/>
</div>
<button className="btn btn-warning btn-block">Update User</button>
</form>
</div>
</div>
);
};
export default EditUser;
Server.js
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");
// Get collectors
app.get('/getCollectors', (req, res) => {
sql.connect(config).then(pool => {
return pool.request()
.query(`Exec [CollectorAssignment].[sCollectorGet]`).then(result => {
res.send(result.recordset)
})
})
})
// Add Collector Personal Info
app.post('/addCollector', function (req, res) {
sql.connect(config).then(pool => {
return pool.request()
.query(`Exec CollectorAssignment.sCreateCollector
#Active='${req.body.Active}',
#FirstName='${req.body.FirstName}',
#MiddleInitial='${req.body.MiddleInitial}',
#LastName='${req.body.LastName}',
#CollectorCode='${req.body.CollectorCode}',
#CollectionTeamID='${req.body.CollectionTeamID}',
#Aging1to15='${req.body.Aging1to15}',
#Aging31to45='${req.body.Aging31to45}',
#Aging31to60='${req.body.Aging31to60}',
#AgingOver60='${req.body.AgingOver60}',
#ProgramBucketA='${req.body.ProgramBucketA}',
#ProgramBucketB='${req.body.ProgramBucketB}',
#ProgramBucketC='${req.body.ProgramBucketC}',
#ProgramBucketSU='${req.body.ProgramBucketSU}',
#FinanceCompany='${req.body.FinanceCompany}'
`)
.then(result => {
res.send(result)
})
})
});
//Update Collector
app.put('/UpdateUser/:CollectorID', function (req, res) {
sql.connect(config).then(pool => {
return pool.request()
.query(`Exec CollectorAssignment.sUpdateCollector
#CollectorID='${req.body.CollectorID}',
#CollectorOptionsID='${req.body.CollectorOptionsID}',
#ProgramBucketID='${req.body.ProgramBucketID}',
#FinanceCompanyID='${req.body.FinanceCompanyID}',
#Active='${req.body.Active}',
#LastName='${req.body.LastName}',
#CollectorCode='${req.body.CollectorCode}',
#Aging1to15='${req.body.Aging1to15}',
#Aging31to45='${req.body.Aging31to45}',
#Aging31to60='${req.body.Aging31to60}',
#AgingOver60='${req.body.AgingOver60}',
#ProgramBucketA='${req.body.ProgramBucketA}',
#ProgramBucketB='${req.body.ProgramBucketB}',
#ProgramBucketC='${req.body.ProgramBucketC}',
#ProgramBucketSU='${req.body.ProgramBucketSU}',
#FinanceCompany='${req.body.FinanceCompany}'
`)
.then(result => {
res.send(result.recordset)
})
})
});
// Delete Collector
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');
})
Stored Procedure being ran for the getCollectors
GO
/****** Object: StoredProcedure [CollectorAssignment].[sCollectorGet] Script Date: 3/29/2022 2:37:07 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: Wesley Seitz
-- Create date: 01/13/2022
-- Description: To pull in collector information for the options page of the assignmnet tool
-- =============================================
ALTER PROCEDURE [CollectorAssignment].[sCollectorGet]
-- Add the parameters for the stored procedure here
--#CollectorID INT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
SELECT
Active,
FirstName,
LastName,
CollectorCode,
Aging1to15,
Aging31to45,
Aging31to60,
AgingOver60,
ProgramBucketA,
ProgramBucketB,
ProgramBucketC,
ProgramBucketSU,
FinanceCompany,
tCollectorsTest.CollectorID,
tCollectorOptionsTest.ProgramBucketID,
tCollectorOptionsTest.FinanceCompanyID,
tCollectorOptionsTest.CollectorOptionsID
FROM CollectorAssignment.tCollectorsTest
INNER JOIN CollectorAssignment.tCollectorOptionsTest ON tCollectorOptionsTest.CollectorID = tCollectorsTest.CollectorID
INNER JOIN CollectorAssignment.tProgramBucketTest ON tProgramBucketTest.ProgramBucketID = tCollectorOptionsTest.ProgramBucketID
INNER JOIN CollectorAssignment.tFinanceCompanyTest ON tFinanceCompanyTest.FinanceCompanyID = tCollectorOptionsTest.FinanceCompanyID
END

As discussed in the comments, your issue here was that, in your EditUser component, you were trying to access a property called CollectorID from the result of useParams() but the only property in this object was id. Changing the line
const { CollectionID } = useParams();
to
const { id } = useParams();
and then changing subsequent references from CollectorID to id resolves the 404 by populating the correct id in the url.
Your follow-up question of why you are not seeing your data populate in the EditUser component should probably be asked in another question (I'd advise trying to recreate the issue with a simpler code example).

Related

How can I send an image from an input type="file" to my SQL database with React and Node?

I would like to get an image from an input of type="file" and send it to my SQL database but I don't know how to do this ?
Here is my Node.js function :
app.post("/ajouter-mon-restaurant", (req, res) => {
const name = req.body.name;
const address = req.body.address;
const description = req.body.description;
const formData = req.body.formData;
db.query(
"INSERT INTO restaurant (nom, adresse, description, image_resto) VALUES (?,?,?,?)",
[name, address, description, formData],
(err, result) => {
console.log(err);
}
);
});
And here is my React code :
import React from 'react';
import { useState } from "react";
import Axios from "axios";
import './ajouterMonRestaurant.css';
function AjouterMonRestaurant() {
const [name, setName] = useState("");
const [address, setAddress] = useState("");
const [description, setDescription] = useState("");
const [image, setImage] = useState("");
const addMyRestaurantToDatabase = () => {
const formData = new FormData()
formData.append('myFile', image, image.name);
// console.log(formData);
Axios.post("http://localhost:3001/ajouter-mon-restaurant", {
name: name,
address: address,
description: description,
formData: formData,
}).then((response) => {
console.log(response)
});
};
const fileChangedHandler = (event) => {
setImage(event.target.files[0]);
};
return(
<div>
<div className='mainContainerAjouterMonResto'>
<div class="login-box">
<h2>Mon Restaurant</h2>
<form>
<div class="user-box">
<input type="text" name="" required="" onChange={(e) => { setName(e.target.value);}}/>
<label>Nom du restaurant</label>
</div>
<div class="user-box">
<input type="text" name="" required="" onChange={(e) => { setAddress(e.target.value);}}/>
<label>Adresse du restaurant</label>
</div>
<div class="user-box">
<input type="text" name="" required="" onChange={(e) => { setDescription(e.target.value);}}/>
<label>Description</label>
</div>
<div class="user-box">
<input type="file" name="myFile" onChange={fileChangedHandler} />
<label>Importer une photo de votre établissement</label>
</div>
<a href="#" onClick={addMyRestaurantToDatabase}>
<span></span>
<span></span>
<span></span>
<span></span>
Submit
</a>
</form>
</div>
</div>
</div>
);
}
export default AjouterMonRestaurant;
So as you can see here, I tried with a FormData but I also tried with a normal (binary) sending but nothing is working. I have everytime this in my console VSCode :
code: 'ER_PARSE_ERROR',
errno: 1064,
sqlMessage: "You have an error in your SQL syntax; check the manual that corresponds to your MySQL
server version for the right syntax to use near ')' at line 1",
sqlState: '42000',
index: 0,
sql: "INSERT INTO restaurant VALUES ('zfzf','zfzf','zfzff',)"
}
but when I print with a console.log(formData); , everything is good. So I don't know why is my database don't receive the image.
PS : the image_resto column in the table restaurant is a VARBINARY(255) type.

Best way to grab id from post to send along with comment to database

So I have a social media page that has an array of posts stored in a sql database. Each post has an id, author, and body. I have another database for comments that will be associated with a certain post. My question is, what is the best way to send the id of the post that is being commented on, to the comment database so that each comment is linked to a post by its ID? When i later query the database i want to display comments on each post but not all the comments from the database, just the one that is associated with the post it was made on. Hope that all makes sense. Here is some of my code, I am open to any and all suggestions.
Post Component:
import React, {useState, useContext} from 'react';
import {AuthContext} from '../AuthContext';
import './Post.css';
import axios from 'axios';
const Post = ({posts, getComment, comments, key}) => {
const {user} = useContext(AuthContext);
const {username} = user;
const [comment, setComment] = useState({
author: username,
comment: '',
id: need this to be the id from the posts that are being passed in as props,
});
const handleSubmit = async (e) => {
e.preventDefault();
try {
const response = await axios.post('/post/comment', comment);
getComment()
console.log(response);
} catch (error) {
console.error(error);
}
};
const onChange = (e) => {
setComment({...comment, [e.target.name]: e.target.value});
console.log(comment);
};
return (
<section>
<ul>
{posts.map((post) => (
<div className="postCard">
<p className="author">{post.author}</p>
<img src="" alt="" />
<div className="postBody">
<p>{post.body}</p>
</div>
<div className="comments">
<form action="submit" onSubmit={handleSubmit}>
<input
type="textarea"
name="comment"
onChange={onChange}
/>
<button>Comment</button>
</form>
<div>
{' '}
{comments.map((comment) => (
<div>
<p>{comment.author}</p>
</div>
))}
</div>
<p>
<i class="far fa-thumbs-up"></i>
</p>
</div>
</div>
))}
</ul>
</section>
);
};
export default Post;
You have each post's id when you are mapping over them, so you can use it as an argument for handleSubmit like so:
<ul>
{posts.map((post) => (
<div className="postCard">
<p className="author">{post.author}</p>
<img src="" alt="" />
<div className="postBody">
<p>{post.body}</p>
</div>
<div className="comments">
// Send the event and the post's id
<form action="submit" onSubmit={(e) => handleSubmit(e, post.id)}>
<input
type="textarea"
name="comment"
onChange={onChange}
/>
<button>Comment</button>
</form>
<div>
{' '}
{comments.map((comment) => (
<div>
<p>{comment.author}</p>
</div>
))}
</div>
<p>
<i class="far fa-thumbs-up"></i>
</p>
</div>
</div>
))}
</ul>
Then in your handleSubmit function you can send the post id along with the comment you are sending now to your backend.
// Receive the event and id
const handleSubmit = async (e, id) => {
e.preventDefault();
try {
// Send comment and id to your backend
const response = await axios.post('/post/comment', {comment, id});
getComment()
console.log(response);
} catch (error) {
console.error(error);
}
};

vuejs problem change route get userChoice in localstorage but push on the profile route before getting new userChoice?

the problem is that on click I increments the new userChoice according to the user chosen but it pushes on the profile route before retrieving the new userChoice click.
what to do here is my template I will put everything in the same function change use the push at the end but it does not work either then I do 2 functions but it does not work either what is the solution ??
<template>
<section
class="stopPadMarg container-fluid d-md-flex justify-content-between"
>
<div class="py-5 stopPadMarg bg-primary col-md-1">
<img
src="../assets/image/icon.png"
width="60px"
class="rounded-circle"
alt="logo"
/>
</div>
<div class="largeur80">
<form class="justify-content-center form-inline py-3 my-2 my-lg-0">
<input
v-model="searchKey"
id="search"
class="form-control mr-sm-2"
type="search"
placeholder="Search"
aria-label="Search"
/>
</form>
<div>
<h3
class="backPrimaire opacity mx-1 text-primary bordurePost bordureRond"
>
<b-icon-chevron-double-down
class="mr-5 my-1 pt-1 text-secondary"
animation="cylon-vertical"
font-scale="1"
></b-icon-chevron-double-down>
Vos collegues
<b-icon-chevron-double-down
class="ml-5 my-1 pt-1 text-secondary"
animation="cylon-vertical"
font-scale="1"
></b-icon-chevron-double-down>
</h3>
</div>
<div class="hauteur">
<div class="mt-5 d-flex flex-wrap">
<div
v-for="(user, id) in filteredList"
v-bind:key="id"
class="col-md-3 d-flex flex-column align-items-center align-content-center"
>
<div #click="changeUser(user)" class="cursor">
<img
#click="changeRoute"
v-if="user.image_url !== null || ''"
:src="user.image_url"
width="100px"
height="100px"
class=" justify-content-left bordureProfil
rounded-circle"
/>
<img
v-else
src="../assets/image/icon.png"
width="100px"
class=" justify-content-left bordureProfil rounded-circle"
/>
</div>
<div>
<h5 class="mt-2">
{{ user.nom.toUpperCase() }}
</h5>
<h6 class="mb-3">{{ user.prenom.toLowerCase() }}</h6>
</div>
</div>
</div>
</div>
</div>
<div class="py-5 stopPadMarg bg-primary col-md-1">
<img
src="../assets/image/icon.png"
width="60px"
class="rounded-circle"
alt="logo"
/>
</div>
</section>
</template>
<script>
import axios from "axios";
export default {
components: {},
data() {
return {
searchKey: "",
postes: [],
users: [],
user_id: localStorage.getItem("userId"),
userChoice: localStorage.getItem("userChoice"),
};
},
async created() {
this.postes = [];
this.users = [];
await axios
.get("http://localhost:3000/postes")
.then(
(response) => ((this.postes = response.data), console.log(response))
)
.catch((error) => console.log(error));
await axios
.get("http://localhost:3000/users")
.then(
(response) => ((this.users = response.data), console.log(this.users))
)
.catch((error) => console.log(error));
await axios
.get("http://localhost:3000/users")
.then(
(response) => (
(this.userDef = response.data.find((user) => {
return user.id;
})),
console.log(this.userDef)
)
)
.catch((error) => console.log(error));
await axios
.get(`http://localhost:3000/user/${this.user_id}`)
.then(
(response) => (
(this.userConnect = response.data), console.log(this.userConnect.id)
)
)
.catch((error) => console.log(error));
await axios
.get("http://localhost:3000/commentaires")
.then(
(response) => (
(this.comments = response.data), console.log(this.comments)
)
)
.catch((error) => console.log(error));
},
computed: {
filteredList() {
return this.users.filter((user) => {
return user.nom.toLowerCase().includes(this.searchKey.toLowerCase());
});
},
},
methods: {
async changeUser(user) {
await localStorage.removeItem("userChoice");
await localStorage.setItem("userChoice", user.id);
this.$router.push(`/profil/${this.userChoice}`);
},
async changeRoute() {
await this.$router.push(`/profil/${this.userChoice}`);
},
},
};
</script>
<style></style>
and the picture here
if I press a second time on the same profile it gives it to me if I return to the colleagues page but not if I change profile there is an empty page
here picture of the routes path
in fact the route does not change profile and remains on 58 here c the profile of that which is connected and if we change number on the route it launches a page page so this is the problem with the path of the route that the we see in the browser cache
Having looked at your code it's obvious why you'd get an empty page when changing routes. Let me explain:
Your routes say this:
Register a route /profil/${userChoice} (which is a value read from localStorage).
This route definition is only read once, at page intialisation. So, when your page loads only /profil/58 will be defined, /profil/59 wont.
What you are probably looking for is route parameters:
https://router.vuejs.org/guide/essentials/dynamic-matching.html
You'd want the number part of this url to be dynamic and respond to changes.
So, instead of reading the value from localStorage, you would write:
{
path: '/profil/:user_id',
name: 'ProfilUser',
...
}
Now when your Profil components is initialized instead of accessing localStorage you read the provided value as follows:
created() {
var userChoice = this.$route.params.user_id;
}
(note it is also possible to get this param as a prop, consult the vue-router docs on how to do this)
Another thing you need to keep in mind is that you need to respond when this parameter changes. Your component will not be refreshed/remounted.
To respond to parameter changes you can do the following:
watch: {
'$route.params.user_id'() {
this.reloadAllStuff();
}
}
I would recommend to not use localStorage for this use case, let the URL parameter be the main source of truth.
Further reading:
https://qvault.io/2020/07/07/how-to-rerender-a-vue-route-when-path-parameters-change/

Trying to inline edit an article and submit the values

I'm trying to inline edit an article and submit the values from the form. However, the v-model values are empty on submit.
Check out my code below. So the top form is for new articles only. And in my v-for there's a switch between 'view' and 'edit' mode.
<template>
<div>
<h2>Articles</h2>
<hr />
<form class="mb-3" #submit.prevent="addArticle">
<div class="form-group">
<input class="form-control" placeholder="Title" v-model="article.title" />
</div>
<div class="form-group">
<textarea class="form-control" placeholder="Bodytext" v-model="article.body"></textarea>
</div>
<button type="submit" class="btn btn-light btn-block">Add new</button>
</form>
<hr />
<div class="card card-body mb-2" v-for="article in articles" v-bind:key="article.id">
<template class="article-row" v-if="edit === article.id">
<form #submit.prevent="editArticle">
<div class="form-group">
<input class="form-control" placeholder="Title" v-model="article.title" />
</div>
<div class="form-group">
<textarea class="form-control" placeholder="Bodytext" v-model="article.body"></textarea>
</div>
<!-- <input type="hidden" v-model="article.id" /> -->
<button type="submit" class="btn btn-light btn-block">Update</button>
</form>
</template>
<template v-else>
<h3>{{ article.title }}</h3>
<p v-html="article.body"></p>
<hr />
<div>
<button #click="toggleEditMode(article.id)" class="btn btn-warning">Edit</button>
<button #click="deleteArticle(article.id)" class="btn btn-danger">Delete</button>
</div>
</template>
</div>
</div>
</template>
<script>
export default {
data() {
return {
articles: [],
article: {
id: "",
title: "",
body: ""
},
article_id: "",
edit: false
};
},
created() {
this.fetchArticles();
},
methods: {
fetchArticles(page_url) {
let vm = this;
page_url = page_url || "/api/articles";
fetch(page_url)
.then(res => res.json())
.then(res => {
this.articles = res.data;
vm.makePagination(res.meta, res.links);
})
.catch(err => console.log(err));
},
addArticle() {
console.log(JSON.stringify(this.article));
fetch("/api/article", {
method: "post",
body: JSON.stringify(this.article),
headers: {
"content-type": "application/json"
}
})
.then(res => res.json())
.then(data => {
this.article.title = "";
this.article.body = "";
alert("Article added!", "success");
this.fetchArticles();
})
.catch(err => console.log(err));
},
editArticle() {
console.log(JSON.stringify(this.article));
fetch("/api/article", {
method: "put",
body: JSON.stringify(this.article),
headers: {
"content-type": "application/json"
}
})
.then(res => res.json())
.then(data => {
alert("Article updated!", "success");
this.fetchArticles();
})
.catch(err => console.log(err));
},
toggleEditMode(article_id) {
this.edit = article_id;
}
}
};
</script>
The console.log(JSON.stringify(this.article)); on the first line of the editArticle function returns an empty object (the default value)... What am i doing wrong?
You need to set the article befeore trying to update it like that:
toggleEditMode(article_id) {
for (let index = 0; index < this.articles.length; index++) {
const article = this.articles[index];
if(article.id === article_id){
this.article = article;
break;
}
}
this.edit = article_id;
}
Fiddle

Insert and updating the data to database from frontend

I am new to web development. I am working in development of an angular application. I have developed an Angular form in front end, Node.js and Sql server in backend. I need some help to connect my angular form to the sql server database. I want to save the data from my angular form to my sql server database.
Versions:
Angular CLI: 8.0.3
Node: 10.16.0
OS: win32 x64
Angular: 8.0.1
I have tried using the restful api to insert data through the server page using post and get.
How can i to connect my angular form to sql databse and insert and update the data when the submit button in my angular form is clicked.
var express = require("express");
var bodyParser = require("body-parser");
var tediousExpress = require("express4-tedious");
var path = require("path")
var app = express();
// Body Parser Middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
//CORS Middleware
app.use(function (req, res, next) {
//Enabling CORS
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, contentType,Content-Type, Accept, Authorization");
next();
});
app.get('/', function (req, res) {
var sql = require("mssql");
// config for your database
var config = {
server:'******',
database: '*******',
user:'******',
password: '*****',
};
// connect to your database
sql.connect(config, function (err) {
if (err) console.log(err);
// create Request object
var request = new sql.Request();
// query to the database and get the records
request.query('select * from dbo.contact', function (err, recordset) {
if (err)
console.log(err)
else
// send records as a response
res.send(recordset);
});
});
});
app.use("/contact", (req, res) => {
res.sendfile( __dirname + "/src/app/contact/contact.component.html");
});
app.use("/product", (req, res) => {
res.sendfile( __dirname + "/src/app/product/product.component.html");
});
app.use("/homepage", (req, res) => {
res.sendfile( __dirname + "/src/app/home/home.component.html");
});
const port = process.env.PORT || 3000;
app.listen(port, () => console.log(`Listening on port ${port}....`));
<div style="text-align:center">
<h1 class="well">
We are available here for you
</h1>
<div class="loader" *ngIf="dataloading"></div>
<div class = "row">
<div class="column">
<div class ="container">
<div class="col-md-5">
<div class="form-area">
<form role="form" (ngSubmit)="processForm()">
<br style="clear:both">
<h3 style="margin-bottom: 50px; text-align: center;">Contact</h3>
<div class="form-group">
<input required ngModel name="Name" #FirstName="ngModel" (change)="log(Name)" type="text" class="form-control" id="Name" name="name" placeholder="Name" [(ngModel)]="name" required>
<div class="alert alert-danger" *ngIf="Name.touched && !Name.valid" > Name is required.</div>
</div>
<div class="form-group">
<input required type="email" class="form-control" id="email" name="email" placeholder="Email" [(ngModel)]="email" required>
<div class="alert alert-danger" *ngIf="email.touched && !email.valid" > Email is required.</div>
</div>
<div class="form-group">
<input type="phone" class="form-control" id="mobile" name="mobile" placeholder="Mobile Number" [(ngModel)]="mobile" required>
</div>
<div class="form-group">
<input type="text" class="form-control" id="subject" name="subject" placeholder="Subject" [(ngModel)]="subject" required>
</div>
<div class="form-group">
<textarea class="form-control" type="textarea" id="message" name="message" placeholder="Message max(200)" [(ngModel)]="message" maxlength="140" rows="7"></textarea>
</div>
<hr class="mb-4">
<button type="button" id="submit" name="submit" class="btn btn-primary btn-lg btn-block" (click)="save(name, email, mobile, subject, message)">Submit</button>
</form>
</div>
</div>
</div>
````
````contact.component.ts
import { Component, OnInit} from '#angular/core';
import {HttpClient} from '#angular/common/http';
import {HttpErrorResponse} from '#angular/common/http';
import {Router} from '#angular/router';
#Component({
selector: 'app-contact',
templateUrl: './contact.component.html',
styleUrls: ['./contact.component.css']
})
export class ContactComponent {
title = 'Simple Example Contact-us page using Angular 4';
public data:any=[]
constructor(private http: HttpClient){
}
save(name, email, mobile, subject, message): void {
this.data['name']= name;
this.data['email']= email;
this.data['mobile']= mobile;
this.data['subject']= subject;
this.data['message']= message;
console.log(this.data);
//add request to send email or into mysql
this.http.post<any>('/contact1', this.data).subscribe(
res => {
console.log(res);
},
(err: HttpErrorResponse) => {
if (err.error instanceof Error) {
console.log("Client-side error occured.");
} else {
console.log("Server-side error occurred.");
}
});
}
}
````