Save HTML form data to text file using node js - javascript

I am using node js and my requirement is save HTML form values which is sent by user, and store those values in text file using node js, and each time data should be save to next lines instead of saving to same line.I got stuck how to do this process.
HTML Code:
<form method="POST" action="/users/contact">
<select name="car" size="1" required id="rankx">
<option value="" selected disabled hidden>Option</option>
<option value="volvo">volvo</option>
<option value="swift">swift</option>
</select>
<br />
<select name="model" size="1" required>
<option value="" selected disabled hidden>Rank</option>
<option value="c500">c500</option>
<option value="Ta66">Ta66</option>
</select>
<input type="submit" value="Submit" name="submit" id="submit"/>
Node js Code:
var express = require('express');
var fs = require ('fs');
router.post("/contact",function(req,res){
let car = req.body.car;
let model = req.body.model;
var form_data = {
car: car,
model: model
}
fs.appendFileSync('./message.txt',form_data.toString());
});
Required outpt: // store in text file userData.txt
id carname carmodel
1 abc abc_1
2 xyz xyz_1

The solution what happens to me was first create a JSON file to save the data and next put this information in a text file. Following four steps:
Step 1: First you need read the existing data from JSON file.
Step 2: Add new car using push method.
Step 3: Write the new and old data in JSON file.
Step 4: Write the new info in the a text file.
Here is the code:
app.js
const express = require('express');
const app =express()
var fs = require ('fs');
// middleware
app.use(express.urlencoded({extended:true}))
// STEP 1: Read the existing data from json file
let users= require("./message.json")
// API routes
app.get('/', (req, res) => {
res.sendFile(__dirname + '/public/index.html');
})
app.post("/",function(req,res){
let car = req.body.car;
let model = req.body.model;
// new car
let formData = {
car: car,
model: model
}
res.send(formData)
// STEP 2: add new user data to users object using push method
users.push(formData)
// STEP 3: Writing data in a JSON file
fs.writeFile('message.json', JSON.stringify(users), err =>{
if(err) throw err
console.log("Done writting JSON file")
})
// STEP 4: Write the new info in the text file named message
fs.writeFile('./message.txt',JSON.stringify(users), err =>{
if(err) throw err
console.log("Done writting text file")
});
});
app.listen(3000, function(){
console.log("server started on port 3000")
})
You need create a JSON file to save data like this:
message.json
[]
and a empty message.txt to storage the data, this file overwrite when save the data.
Leave screenshots.
I hope help you.

Related

How do I use data from the server side on the cliente side?

This is my app.js
var products = [
{description: "Hi"},
{description: "Hi2"}
]
app.get('/', function (req, res){
res.render("home.ejs");
})
app.get('/checkout', function (req, res){
res.render('checkout.ejs', {products:products});
});
app.post('/checkout', function(req, res){
var description = req.body.description;
var newProduct = {description};
products.push(newProduct);
res.redirect('/');
});
This is my home.ejs
<form action="/checkout" method = "POST">
<p class = "item-description">LP Snake Pocket Tee</p>
<input type="hidden" name = "description" class = "item-description-post">
<div class="btn-group btn-add mr-2" role="group" aria-label="Second group">
<button class="btn btn-success btn-add-cart">ADD TO CART</button>
</div>
</form>
And this is my hoje.js file, which just basically fills my input value with what I want, so I can send that as POST input
var item = $(".item-description")[0].innerHTML;
var postInput = $(".item-description-post").val(item);
Now I'm my checkout.ejs file I can do something like this, and print all my products (descriptions only so far)
<% products.forEach(function(product){ %>
<p> <%= product.description %> </p>
<% }); %>
My question is, how can I do the same thing, but in a separate .js file?
I do have a javascript file connected with my checkout.ejs
<!-- JAVASCRIPT -->
<script type = "text/javascript" src="./checkout.js"></script>
But that file can not access my array 'products'. Which makes sense, because my back end is only sending that data to my ejs file, so basically, how do I send that data 'products' from my app.js file to my checkout.js file? :)))
You can't.
Note: You can only pass data from .ejs file to .js file but not the other way. It won't work because .ejs is rendered on the server side while .js runs on the client side. I am assuming you are using EJS on server side
Why:
The EJS template will be rendered on the server before the js is started execution(it will start on browser), so there is no way going back to server and ask for some previous changes on the page which is already sent to the browser.

button should delete specific item on server side

I'm working on an app to track my expenses with javascript, nodejs , express and as templating engine handelbars.
So I have a div "list" which contains all expenses. ( i have an add button next to the div list, not visible on the pic)
Everytime a I add an expense , I add the div "obj" with a delete button ,a "B" button and some information about the expense.
here is the code in my html:
<div class="list">
{{#each expArr}}
<div id="obj" class="obj">
<form action="/removetodo" method="POST" >
<button class="btn2">X</button>
</form>
<button onclick="openNav()" class="btn">B</button>
<a>{{date}}</a> <n>{{name}}</n> <a>{{value}} </a>
{{description}}
</div>
{{/each}}
Now, my backend is runnning on a NodeJS server with express.
here is my index.js file :
var express = require('express');
var router = express.Router();
var expArr = [];
router.get('/', function(req, res, next) {
res.render('index' , {expArr: expArr} );
});
router.post('/addtodo', function (req, res, next) {
var exp = new Object();
exp.name = req.body.name;
exp.value = req.body.val;
exp.date = req.body.date;
exp.description = req.body.descr;
expArr.push(exp);
res.redirect('/');
});
router.post('/removetodo', function (req, res, next) {
expArr.pop();
res.redirect("/");
});
module.exports = router;
In addtodo I simply adding all the informtion to an array on the server (later I will add a database).
Now my question:
The delete button on every expense should delete the right expense.
In other words, I want ,by clicking the delete button , that the right entry in the array on the server deletes.
How do I do that?
Thanks!
you're storing everything in memory, taking that for granted, you can start by using a plain object rather then an array to store your data
expArr = {}
and then add a unique identifier like a hash or a date in ms for each instance
var exp = new Object();
exp.id = new Date().getUTCMilliseconds();
exp.name = req.body.name;
exp.value = req.body.val;
exp.date = req.body.date;
exp.description = req.body.descr;
expArr[exp.id] = exp;
now be sure to pass from the client the right id when you want to remove an expense
router.post('/removetodo', function (req, res, next) {
if(expArr[req.body.id]) {
delete expArr[req.body.id];
}
res.redirect("/");
});

Uploading file from form to server

I am currently working on a dashboard, and have been stuck for some couple of hours now... What I like to do is to have a form including 3 <input type="file"> (two of them allow multiple files, one not), and each of them posting to 3 different post-methods in the server. When I try to console log the request on the server side the data is empty ({}) . I do not understand why, can someone please help me solve this issue?
I am using angularjs, and nodejs btw.
This is what my current code is : (files and paths are dummy-names)
HTML:
<form role="form" enctype="multipart/form-data">
<div class="form-group">
<label for="file1">File1:</label>
<input type="file" id="file1" accept=".txt, .json" multiple>
</div>
<div class="form-group">
<label for="file2">File2:</label>
<input type="file" id="file2" accept=".json">
</div>
<div class="form-group">
<label for="file3">File3:</label>
<input type="file" id="file3" multiple>
</div>
<button type="button" ng-click="save()" class="btn btn-default"> Save</button>
</form>
JS:
module.exports = function($scope, $http) {
$scope.save = function () {
file1(document.getElementById('file1').files);
file2(document.getElementById('file2').files);
file3(document.getElementById('file3').files);
};
function file1(files) {
$http.post('/file1', {f: files}).success(function (res) {
//todo
});
};
function file2(files) {
$http.post('/file2', {f: files}).success(function (res) {
//todo
});
};
function file3(files) {
$http.post('/file3', {f: files}).success(function (res) {
//todo
});
};
}
Server.js
var express = require("express"),
fs = require("fs"),
bodyParser = require('body-parser'),
app.use(express.static("build"));
app.use(bodyParser());
app.post('/file1', function (req, res) {
console.log(req.body.f) // returns empty: {}
// like to move files to path: a/b/c
});
app.post('/file2', function (req, res) {
// like to move files to path: a/d/e
});
app.post('/file3', function (req, res) {
// like to move files to path: a/f/g
});
Update:
after receiving the answer from GrimurD, I have modified the server.js, but still struggling. Any takers?
var express = require("express"),
fs = require("fs"),
bodyParser = require('body-parser'),
multer = require('multer'), //<-- updated
upload = multer({ dest: './uploads/' }) //<-- updated
app.use(express.static("build"));
app.use(bodyParser());
app.use(multer({ dest: './uploads/' }).array()); // <-- updated
app.post('/file1', upload.array('file1'), function (req, res) {
console.log(req.body.f) // returns empty: {}
console.log(req.files); // returns undefined // <-- updated
// like to move files to path: a/b/c
});
app.post('/file2', upload.single('file2'), function (req, res) {
console.log(req.file); // returns undefined // <-- updated
// like to move files to path: a/d/e
});
app.post('/file3', upload.array('file3'), function (req, res) {
console.log(req.files); // returns undefined // <-- updated
// like to move files to path: a/f/g
});
When uploading a file the form must use multipart/form-data which body-parser doesn't support. You must use a specialized middleware to handle this type. Multer is one such that I have used with success.
You can get around this using FileReader.readAsDataURL(..) on the File objects in the input fields. I often like to use the multi-select ability on the file input type so that I can upload a bunch of files and do this async.
So what I normally do is access the files property on the input element and loop through them, then I use the FileReader.readAsDataURL to get the base64 of the binary for the files then passing the base64 to a webserivce method with a signature that accepts that a string param for the base64, convert the b64 to binary and you're back in business.
var fileRunner = {
files: [],
run: function(el) {
this.files = el.files;
this.read();
},
read: function() {
// begin the read operation
console.log(this.files.length);
for (var i = 0; i <= this.files.length - 1; i++) {
var reader = new FileReader();
reader.readAsDataURL(this.files[i]);
reader.onload = this.process
}
},
process: function(evt) {
var result = evt.target.result
if (result.length > 0) {
var parts = result.split(',')
var dataBsf = parts[parts.length - 1];
console.log(dataBsf);
//call method to pass the base 64 here.
}
}
};
<body>
<input id="fup" type="file" multiple="multiple" onchange="fileRunner.run(this)" />
</body>
I did not include a server side component to this because I think that should be agnostic and slightly out of scope here.
I am only logging the output to the console, but you would take the output and pump it to the web service.
Additionally, I referenced the input element in the event handler for the onchange using "this" because I had no idea how you wanted to handle it. Allowing the passing of an element provided a bit of loose assumptions on my part.

Sails.js req.files is empty and req.body.image is undefined

I've been trying to understand this since yesterday but I can't find any solutions, even by asking Google and StackOverFlow.
The problem is that I'm building a project inside which I have "Product" Model, Controller, and Views. On the new.ejs view, I have a form which contains a file tag (named image). So, on the controller, I try to get the image path by logging req.files.image.path in the console but req.files is empty. I also tried to display req.body.image which is undefined.
Here is the client-side code (views/product/new.ejs) :
(This is a Sails.js app)
Here is the client-side code (views/product/new) :
<div class='container'>
<form action='/product/create' role='form' class='form-signin' enctype="multipart/form-data" id='product-form'>
<div class='form-group'>
<label class='sr-only' for='name'>Name of the product</label>
<input type="text" class='form-control' placeholder="Name" name='name' id='name' />
</div>
<div class='form-group'>
<label class='sr-only' for='image'>Image of the product</label>
<input type="file" name='image' id='image' />
</div>
.
.
.etc...
and here is the server-side (api/controllers/ProductController.js) :
'create': function(req, res, next) {
// Include the node file module
var fs = require('fs');
console.log(req.files); //This logs : { } in the console
console.log(req.body.image); //This logs : undefined in the console
//Readfile with fs doesn't work cause req.files is empty
// fs.readFile(req.files.image.path, function(error, data) {
// //get image name
// var imageName = req.files.data.name;
// //if enable to get name
// if (!imageName) {
// console.log('error uploading image');
// res.redirect('/product/new');
// //Else if we have an image
// } else {
// //change the path to our own
// var newPath = __dirname + '/assets/images/products/fullsize/' + imageName;
// fs.writeFile(newPath, data, function(error) {
// console.log(newPath);
// //res.redirect('/product' + imageName);
// });
// }
// });
}
Thanks for your help.
Mat.
Also available here : https://github.com/balderdashy/sails/issues/1127
use method=post in your html form

passing data between server and client (node.js + mongodb)

I'm working with node.js express and mongodb, I have a input data from client, I need to pass the data to server look for its property and send to the client in another page.
Now I have problem with req.body.age that suppossed to get the data from client's input and use find() to get its appropriate property.
Server side code:
functions are routed in another .js file
exports.find_user = function(req, res) {
res.render('find_user.jade');
};
exports.user = function(req, res){
member = new memberModel();
member.desc.age = req.body.age; //problem
console.log(req.body.age); //undefined
memberModel.find({desc: {age: '7'}}, function(err, docs){
res.render('user.jade', { members: docs });
console.log(docs);
});
};
memberModel.find({desc: {age: '7'}} just hardcode picking up user with age 7 (works)
client side code (jade):
page for data input:
find_user.jade
form(action='/', method='post')
fieldset
lable(for="age") Find user by age:
input(type="text", size="30", name="age", required="required")
input(type='button', value='Find', onclick='location.href=\'find_user/user/\'')
page for data output with its property:
user.jade
tr
th Name
th Age
tbody
- members.forEach(function(member){
tr
td= member['name']
td= member['desc']
- });
You are not submitting your data in find_user.jade file when the user clicks the button. Instead, the client is only redirected to another page.
This is how your find_user.jade file should look like:
form(action='find_user/user/', method='post')
fieldset
label(for="age") Find user by age:
input(type="text", size="30", name="age", required="required")
input(type='submit', value='Find', name="submit")

Categories