button should delete specific item on server side - javascript

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("/");
});

Related

How do I get the next row of database results from a button click using Node.js?

I'm using Node.js to serve my webpage and get the database results from mysql. Right now I have it successfully connected and showing the first row of data.(I'm using these as button values in the html code below) However, I want the user to be able to click a button and get the next row of data.
var express = require("express");
var app = express();
var mysql = require('mysql');
var con = mysql.createConnection({
// working connection
});
con.connect(function(err) {
if (err) throw err;
con.query("SELECT * FROM my_table limit 10", function (err, result, fields) {
if (err) throw err;
else{
sandbox.big1Value = result[0].big1;
sandbox.big2Value = result[0].big2;
}
});
});
app.get('/mypage', function (req, res) {
res.render('mypage', { dbinput: sandbox });
});
<button type="button" id="big1" onclick="myFunction(this.value)" value=<%= dbinput.big1Value %> ><%= dbinput.big1Value %> </button>
<button type="button" id="big2" onclick="myFunction(this.value)" value=<%= dbinput.big2Value %>><%= dbinput.big2Value %> </button>
<!-- I want this button to get the next set of values -->
<button type="button" id="next" onclick="doSomething()" value="Next">Next One</button>
You can do this using limit and offset in mysql From documentation
Syntax: LIMIT {[offset,] row_count | row_count OFFSET offset}
Here in your case you can use:
SELECT * FROM my_table LIMIT 10, 10; # Retrieve rows 11-20

How to receive data from a button in a form?

This seems very simple but I can't figure it out. I am trying to get back the value of a button so I can conditionally render a page template. I can't seem to capture the value of the button though.
Here is my js code.
app.get("/trades", (req, res) => { // line 465
let button_value = req.params.value;
console.log(button_value);
// res.render("activate_pause")
});
And here is my html/ejs markup:
<form action="/trades" methods="get, post" name="groups_button">
<button class="orange" type="submit" name="frontpage_trades_button" value="pause">Pause Campaigns</button>
<button type="submit" name="frontpage_trades_button" value="enable">Activate Campaigns</button>
</form>
The values 'pause' or 'enable' will be used to set a status of true or false, which will render the desired template ( or so I hope!). Can anyone help??
methods is not a valid attribute of the <form> element
console.log('Is method in <form>?: ', 'method' in HTMLFormElement.prototype);
console.log('Is methods in <form>?: ', 'methods' in HTMLFormElement.prototype);
So the first thing to do is to replace methods with method and set only one method (I'd suggest POST).
Then in the Node.js code, make sure you have the proper middleware in order to decode URL encoded forms:
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: true }));
This should allow you to retrieve the value of the clicked button, like this:
app.post("/trades", (req, res) => {
let button_value = req.body.frontpage_trades_button;
console.log(button_value);
// res.render("activate_pause")
});
u can use data attribute to take it
<button type="submit"id="x" name="frontpage_trades_button" data-value="enable">Activate Campaigns</button>
app.get("/trades", (req, res) => { // line 465
let button_value = req.params.value;
console.log($("#x").data("value"));
// res.render("activate_pause")
});

mongoose syntax with user.id connecting to a form

Hi I am new to mongoose and with angular through ionic. I am trying to build an app and having problem with it. I have no Idea if this syntax mongoose is right because it still is not working in my front end where the user picks and answer and it saves it to the database
Heres my mongoose question.js
var express = require('express');
var router = express.Router();
var mongoose = require('mongoose');
var Question = require('../models/Question.js');
var app = express();
// GET questions listing. questions/yourroute
router.get('/', function(req, res, next) {
Question.find(function(err, questions){
if(err) return next(err);
res.json(questions);
});
});
router.post('/saved-questions', function(req, res){
var now = Date()
User.findById(user.id, function(err, user){
var newanswer1 = {
question: '58ccb991caf9756f8e1d8a6c',
answer_text: req.body.Q1,
postdate: now
}
});
user.users_answers.push(newanswer1);
//repeat for Q 2 and 3, push each time
User.save()
});
module.exports = router;
And this is the form in ionic.. I don't know why its not working, maybe its how im putting it in the ionic form. There suppose to be slides of questions in ionic and each possible answer is in the ion check box
<div id="questions" ng-controller="QCntrl">
<ion-content>
<ion-slide-box>
<ion-slide>
<div class="intro" ng-controller="PopupCtrl">
<h1 class="hidden">Intro Question</h1>
<h3>Just need to ask some questions to make this app personalized for you</h3>
<button class="button" value="next" ng-click="nextSlide()">OKAY</button>
<button class="button2 button-positive" ng-click="PopAlert()">
Why?
</button>
</div>
</ion-slide>
<ion-slide>
<div id="Q1box">
<h2>{{questions[0].question_text}}</h2>
<ul>
<li data-ng-repeat="answer in answers1">
<ion-checkbox id="Q1" ng-model="filter.users_answers">{{answer.label}}</ion- checkbox>
</li>
</ul>
Next Question
</div>
</ion-slide>
Where you have User.save(), try changing it to user.save and move the }) that's before User.save and put it after where you change User.save to user.save
You are editing the user you just found with User.findById(user.id, function(err, user){
and it seems you then want to save the push you made to user.users_answers which user.save should do for you

ReCaptcha validation on Node.js

on my express server, g-recaptcha-response always return nothing. This is my code at the moment:
<div class=container-fluid id=mcenter>
<form id='monitstart' action="/monitstart" method="POST">
<input type="text" class="form-control" aria-label="..." name=>
<button class="g-recaptcha" data-sitekey="SITEKEYHERE" data-callback="onSubmit"></button>
</form>
</div>
and on my server
var express = require('express')
var router = express.Router()
var request = require('request')
router.post('/monitstart', function (req, res) {
request({url: "https://www.google.com/recaptcha/api/siteverify?secret=SECRETHERE&response=" + req.body['g-recaptcha-response']} + '&remoteip=' + req.connection.remoteAddress, function (err, response, body) {
req.send(body)
})
})
module.exports = router
And when I try to validate it, it give me a code 500 and say TypeError: Cannot read property 'g-recaptcha-response' of undefined
The correct answer, accepted by the OP during the short discussion below the question involves adding the body parsing middleware (the body-parser) to the pipeline so that the body property of the request object is correctly initialized before a value is read from there.

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.

Categories