Express function sending multiple times - node.js

My react js file is currently like this
export default function Blog() {
const [title, setTitle] = useState('');
const [blog, setBlog] = useState('');
const sumbitBlog = () => {
axios.post('http://localhost:3001/api/insert', {
title: title,
blog: blog
});
}
return (
<div className='container'>
<div className='row'>
<form className='col-lg-12 form-group'>
<div className="form-group">
<label for="formGroupExampleInput">Title</label>
<input type="text" className="form-control"placeholder="Title" name="title" onChange={(e)=>{
setTitle(e);
}}/>
</div>
<div className="form-group">
<label for="formGroupExampleInput2">Body</label>
<input type="text" className="form-control" placeholder="Body" name="blog" onChange={(e) =>{
setBlog(e);
}}/>
</div>
<button className='btn-primary' type="submit"onClick={sumbitBlog()}>Submit</button>
</form>
</div>
</div>
);
}
And my nodejs back end code :
app.post('/api/insert', (req, res) =>{
const title = req.body.title;
const blog = req.body.blog;
const sql = `INSERT INTO posts (title, body) VALUES ("this","works")`;
db.query(sql,[title, blog], (err, result)=>{
if(err) throw err;
console.log(title);
console.log(blog)
});
});
even though it looks right, it keep sending multiple requests
I have I don't know what is happening, I tried using different ways of doing it looking from the internet, but only this way it inserts to the database. any other way it wont even try connecting to it.
the database

Try to pass a reference to the function instead of firing it every time you render it.
So:
onClick={sumbitBlog}
instead of:
onClick={sumbitBlog()}

Your backend function does not send a response back to the client, because it lacks a res.json() function call or similar. If you insert a statement
res.json(result);
after the two console.log statements, the client will receive a JSON response, which you must then use to somehow update the client so that the user can read that the insertion was successful. The following code simply alerts the user and displays the JSON, but you probably want something more elegant.
const sumbitBlog = async () => {
var response = await axios.post('http://localhost:3001/api/insert', {
title: title,
blog: blog
});
alert(JSON.stringify(response.data));
}

Related

File upload (with other inputs and textarea) using Angular 13 and Node Js

I am trying to upload files to server using Angular and Node, using multer.
I have Todo Model as :
export class TodoModel {
todo_id !:number;
todo_title !:string;
todo_description !:string;
todo_status !:number;
todo_deleted_flag !:boolean;
todo_image !:Object;
}
todo.component.ts
title:string;
desc:string;
selected_image:File = null;
fileUploadListener(event){
//console.log(event)
//console.log(event.target.files[0])
this.selected_image = <File>event.target.files[0]
console.log(this.selected_image)
}
onSubmit(form:NgForm){
const fd = new FormData()
if(this.selected_image) {
fd.append('todo_image',this.selected_image,this.selected_image.name)
}
console.log(fd);
const todo_model : TodoModel = {
todo_id: null,
todo_title:this.title,
todo_description:this.desc,
todo_status:1,
todo_deleted_flag:false,
todo_image:null
}
console.log(fd);
this.todoAdd.emit(todoadded);
this.todoAdd_DB.emit(todo_model);
this.addTodo_DB(todo_model, fd)
form.resetForm();
}
addTodo_DB(todo_db: TodoModel, fileUpload:Object){
//const todo_db
return this.http.post<{message:any}>('http://localhost:3000/api/todos/post_all_todos_db', todo_db,fileUpload).subscribe(data => {
console.log(data.message);
console.log(todo_db);
})
}
todo.component.html
<div class="col-md-12">
<form (ngSubmit)="onSubmit(todoForm)" #todoForm="ngForm">
<div class="mb-3">
<label for="todo_title" class="form-label">Title</label>
<input type="text" class="form-control" id="todo_title" [(ngModel)]="title" name="title">
</div>
<div class="mb-3">
<label for="label" class="form-label">Description</label>
<textarea class="form-control" id="todo_description" [(ngModel)]="desc" name="desc"></textarea>
</div>
<div class="mb-3">
<label for="todo_image" class="form-label">Image</label>
<input type="file" class="form-control" id='todo_image' (change)="fileUploadListener($event)">
</div>
<button type="submit" class="btn btn-success">Add To Do</button>
</form>
</div>
</div>
And on Server Side, using Node Js and PgSQL :-
app.post('/api/todos/post_all_todos_db',upload_using_multer.single('todo_images') , (req, res, next) => {
// const todo_post = req.body;
const files = req.file;
console.log(files) // - ----------> This does NOT work
console.log(req.body) //------> this works
//PGSQL insert query here
res.status(201).json({
message:"Post Added Successfully"
})
})
While doing console.log() in Angular side, I am getting the form data, but, on Node Js side, I get it as null.
Almost every tutorial I see, uses only one file upload , and that too, try to submit the form using the Form's action. I dont want to do that, so I tried doing this.
I
i once had the same issue and solved it with formdata, my example uploads multiple files. here is an example:
Node.JS
const serverRoutes = (function () {
const express = require('express');
const router = express.Router();
const multer = require('multer');
const upload = multer();
router.post('/myresource', upload.any(), (req, res) => {
console.log(req.files);
});
return router;
});
on angular
export class DataService {
constructor(private http: HttpClient) { }
sendMyFiles(file): Observable<MyResponse> {
const formData = new FormData();
formData.append("file", file);
return this.http.post<MyResponse>(
`${environment.backendAPI}myresource`,
formData
);
}
}

Passing Data between app.post to app.get in nodejs

I am fairly new to nodejs and express. I am using nodejs and handlebars to create a simple back end CRUD App. Right now I am stuck on how to pass the value from a form I created in handlebars to an app.get function in my index.js file so inside my app.get function I can use the value to do a database query. After I do the query I want to display the results using app.get and render it to web page.
This is my Handlebars code:
<section id="main" class="wrapper">
<div id="view" class="container">
<section id="main" class="wrapper">
<div id="class" class="container">
<div class="card-body">
<form action="/getid/submit" method="POST">
<div class="form-group">
<label for="id"></label>
<input type="text" class="form-control" id="id" name="id"
placeholder="Enter ID">
</div>
<button type="submit" class="btn btn-primary">Enter ID</button>
</form>
</div>
</div>
</section>
This is the post function in index.js
app.post('/getid/submit',(req,res)=>{
const id = req.body.id;
console.log(id);
res.redirect('page1');
});
This is the app.get function:
app.get('/view/id',(req,res)=>{
//id = ?
var sql = `SELECT * FROM class WHERE Id =${id}`;
db.query(sql,function (err,result){
if(err) throw error;
res.render('page2',{title: 'test', items: rows})
});
});
My main question would be How do I pass the value that I am getting from the app.post form to my app.get function so I can run the query with that ID and render the values to the webpage. THank you in advance.
The id you need to achieve is in request parameters. So you should try:
app.get('/view/:id', (req, res) => {
//id = ?
const id = req.params.id
var sql = `SELECT * FROM class WHERE Id =${id}`;
db.query(sql, function (err, result) {
if (err) throw error;
res.render('page2', { title: 'test', items: rows })
});
});

React reloads the page after replacing images

I am uploading images to a server. If it is present and replaced, then React refreshes the page with a loss of state. How can I stop this behavior?
Node:
let form = new formidable.IncomingForm();
form.parse(req, function (err, fields, files) {
let {size, path, name, type} = files.image,
newpath = pathLib.join(__dirname, '../client/public/uploads') + name;
fs.rename(path, newpath, function (err) {
if(err) throw err;
});
});
React:
<form id="uploadForm">
<input id="uploadInput" name="image" type="file" />
</form>
<span onClick={() => {
let form = document.querySelector("#uploadForm"),
formData = new FormData(form);
if(form.querySelector("#uploadInput").files.length)
uploadFiles(formData, (res) => {
console.log(res.data.errors);
});
}}>Save</span>
An important addition! Page refreshed even without interaction with React components. Replacing an image through the Windows file manager calls the re-render.
Just call event.preventDefault() when submit form. See the example here:
<form id="formSubmit"}>
<input id="uploadInput" name="image" type="file" />
<button type="submit"></button>
</form>
document.getElementById('formSubmit').addEventListener('submit',function(event){
event.preventDefault()
// write here your others code
})

Axios POST request doesn't work

I'm using Axios to send POST request to Node.js server but it doesn't work. Do you have any idea how to resolve it?
My code is shown below:
server.js:
app.post('/registration', (req, res) => {
console.log(req.body);
});
my class:
export default class Registration extends Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
this.state = {}
}
handleSubmit (e) {
e.preventDefault;
axios.post('/registration', {name: document.getElementById('name') }).then(res => {
console.log(res);
})
}
render() {
return (<form className="registrationForm">
<input type="text" name="name" id="name" required="required" placeholder="name"/>
<br/>
{/*<input type="text" name="email" required="required" placeholder="email"/>
<br/>
<input type="number" name="phoneNumber" required="required" placeholder="phoneNo"/>
<br/>
<input type="password" name="password" required="required" placeholder="pass"/>
<br/> */}
<button className="registerButton" onClick={this.handleSubmit}>register</button>
</form>)
};
}
You have various problems in your code
preventDefault is method. You need to call it
I doubt you want to send DOM element to the server
You want to handle network failure using catch
Corrected handleSubmit should look like this
handleSubmit (e) {
e.preventDefault(); // NB
const data = {name: document.getElementById('name').value /* NB */ };
axios.post('/registration', data).then(res => {
console.log(res);
}).catch(console.error) // now you could see what the actual problem is
}
Also it is generally not adviced to use DOM lookup methods in your React up. You should better keep a ref to the input.
<input ... ref={input => this.name = input}/>
const data = {name: this.name.value };
The problem was for just a single line that I didn't write in my server side application.
The only thing to check is to put the following line after requiring the body-parser in your file.
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));

Getting specific record using user input in form with MongoDB, NodeJS and Angular5

I am trying to get back a record out of my MongoDB database using user input on an Angular template. Here's what's in my api.js file:
// Response handling
let response = {
status: 200,
key: [],
message: null
};
router.get('/keys/:key', (req, res, next) => {
connection((db) => {
db.collection('keys')
.findOne({key: req.params.key})
.then((keys) => {
response.key = keys;
res.json(keys);
})
.catch(err => {
return next({ status: 500, message: 'messed up'})
});
});
});
Here's my keys.service.ts file:
#Injectable()
export class KeysService {
result: any
constructor(private _http: Http) {}
getKeys(typeKey) {
return this._http.get(`/api/keys/:key${typeKey}`)
.map(result => this.result = result.json().key);
}
}
Here's the template (I apologize about the formatting):
<div class="container">
<div style="text-align:center">
<h1>
Welcome to {{ title }}!
</h1>
</div>
<div class="row">
<div class="col-xs-12 col-sm-10 col-md-8 col-sm-offset-1 col-md-offset-2">
<input type="text" [(ngModel)]="typeKey">
<button class="btn btn-primary" (click)="getKeyClass(typeKey)">Check Your
Key Spelling</button>
<br><br>
<h2>The Correct Key Spelling is: {{ keySpelling }}</h2>
</div>
</div>
</div>
What I am receiving as an error right now is "type error, can not read property key of null". It is referring to "key" in the keys.service.ts file on the last line.
I am not using mongoose or monk here. I had this working with a general query of my db that gave me the entire contents of the collection "keys" but when I try and make an individual query, no dice. Anyone have any ideas what I am doing wrong?

Resources