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

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")

Related

Retrieve token/Create charge - Stripe

This might be a stupid question but here we go.
I've set up Stripe Elements (https://stripe.com/docs/elements) to collect credit card info, and tockenize it.
Now I'm trying to set up charges, but I'm unsure of how to set up my "server-side" code.
Submitting the form in my controller.js:
function stripeTokenHandler(token) {
// Insert the token ID into the form so it gets submitted to the server
var form = document.getElementById('payment-form');
var hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'stripeToken');
hiddenInput.setAttribute('value', token.id);
form.appendChild(hiddenInput);
// Submit the form
form.submit();
}
https://stripe.com/docs/charges:
"On your server, grab the Stripe token in the POST parameters submitted by your form."
From my Nodecharge.js:
// Set your secret key: remember to change this to your live secret key in
production
// See your keys here: https://dashboard.stripe.com/account/apikeys
var stripe = require("stripe")("sk_test_111111111111111111");
// Token is created using Stripe.js or Checkout!
// Get the payment token ID submitted by the form:
var token = request.body.stripeToken; // Using Express
// Charge the user's card:
stripe.charges.create({
amount: 1000,
currency: "sek",
description: "Example charge",
source: token,
}, function(err, charge) {
// asynchronously called
});
My HTML-form:
<form action="/charge" method="post" id="payment-form">
<div class="form-row">
<label for="card-element">
Credit or debit card
</label>
<div id="card-element">
<!-- a Stripe Element will be inserted here. -->
</div>
<!-- Used to display form errors -->
<div id="card-errors" role="alert"></div>
</div>
<button>Submit Payment</button>
</form>
Submitting a payment with the test card, I get redirected to /charge with a 404.
I'm new to this, and I've obviously copy/pasted some code, but I'm trying hard to wrap my head around it, and I want to understand it, not just make it work.
I kinda get how the credit card info retrieval works with js, but I'm a bit confused when it comes to the charging/redirecting/404/.
I mean, this action-line points me to a non-existing page on my end, right? Do I need to create this page?
<form action="/charge" method="post" id="payment-form">
Sorry for the length of this post, please help me understand what's going on here, or what I need to fix.
Appreciate any help.
How are you serving your backend --- Express?
If you're seeing a 404 when you submit your form to /charge it sounds like you might not have a app.post route setup for /charge in Express.
You can read through the guide on routing for a little more detail
https://expressjs.com/en/guide/routing.html
If you want to see a simple working example, take a look at this (make sure to replace the pk_test and sk_test with your actual test keys):
var stripe = require("stripe")("sk_test_xxxyyyzzz");
var express = require('express'), bodyParser = require('body-parser');
var urlencodedParser = bodyParser.urlencoded({ extended: false })
var app = express();
app.get('/',function(req, res) {
// for kicks, just sending checkout
res.send('<form action="/charge" method="POST">Buy it !<script src="https://checkout.stripe.com/checkout.js" class="stripe-button" data-key="pk_test_xxxyyyyzzzz"></script></form>')
});
app.post('/charge',urlencodedParser, function(req, res) {
// grab a token
var token = req.body.stripeToken;
// creating a charge, for real use add things like error handling
stripe.charges.create({
amount: 2000,
currency: "usd",
source: token, // obtained with Stripe.js
description: "Charge"
}, function(err, charge) {
res.send("You made a charge: "+ charge.id);
});
});
app.listen(5000)
To create source token via stripe, first need to refer stripe.js from stripe.com and it must be from stripe.com.
And then add below code to add your card info and generate a token.
var stripe = Stripe('Your stripe publisheable key');
var elements = stripe.elements;
stripe.createToken(elements[0], additionalData).then(function (result) {
example.classList.remove('submitting');
if (result.token) {
// If we received a token, show the token ID.
example.querySelector('.token').innerText = result.token.id;
example.classList.add('submitted');
}
Here, you will get a token, that will be necessary to create your customer. Use below code to create your customer. I used C#.NET
StripeConfiguration.SetApiKey("sk_test_JTJYT2SJCb3JjLQQ4I5ShDLD");
var options = new CustomerCreateOptions {
Description = "Customer for jenny.rosen#example.com",
SourceToken = "tok_amex"
};
var service = new CustomerService();
Customer customer = service.Create(options);
Now, you can get your required amount form this user from the card token you got from stripe like below:
StripeConfiguration.SetApiKey("sk_test_JTJYT2SJCb3JjLQQ4I5ShDLD");
var options = new ChargeCreateOptions {
Amount = 2000,
Currency = "aud",
Description = "Charge for jenny.rosen#example.com",
SourceId = "tok_amex" // obtained with Stripe.js, }; var service = new ChargeService();

KeystoneJS post request does not work

This is my view
form.contact-form(method="post").col-md-12
input(type='hidden', name='action', value='notes.edit' + data.post.id)
.form-group.col-md-12
.form-group.col-md-12
label.text-center Title
input.form-control.input-box(type='text', name='title', value=data.post.title, placeholder='Title' required)
.form-group.col-md-12
label.text-center Content *
.row
.col-md-6
input.form-control.input-box(type='text', name='briefcontent', value=data.post.content.brief, placeholder='brief content')
.col-md-6
input.form-control.input-box(type='text', name='extendedcontent', value=data.post.content.extended placeholder='extended content')
button(type='submit').btn.btn-success Edit Notes
form.contact-form(method="post").col-md-12
This is my post route
view.on('post', { action: 'notes.edit'}, function(next) {
console.log('edit notes')
res.redirect('/')
});
This is my route bindings
// Setup Route Bindings
exports = module.exports = function (app) {
// Views
app.all('/', routes.views.index);
app.get('/blog/:category?', routes.views.blog);
app.get('/blog/post/:post', routes.views.post);
app.get('/gallery', routes.views.gallery);
app.get('/registration', routes.views.registration);
app.post('/registration', routes.views.registration);
app.all('/signin', routes.views.signin);
app.all('/signout', routes.views.signout);
app.all('/contact', routes.views.contact);
app.all('/addnotes', routes.views.addnotes);
app.all('/editnotes/:post', routes.views.editnotes);
app.all('/editnotes', routes.views.editnotes);
The post request does not seem to work at all. I try console.log for the post request but in does not appear in terminal.
You're appending the data.post.id to the value property of your input. Thus, the input value changes to be something that isn't notes.edit. Your POST route is expecting a request with an action value of only notes.edit, therefore the POST request isn't being handled by that route.
In your Pug template:
input(type='hidden', name='action', value='notes.edit')
EDIT:
You have a second form within your form. That may have something to do with it as well. Try removing it.

Update and delete buttons using node.js

I am very new to programming, it might sound stupid but can anyone of you please help me out. I am designing a cart page using node.js which adds each item at once. There are two buttons update and delete, everything is working fine except these buttons. Can anyone help me out to make these buttons working.
Thank you
Here is my code.
cart.js
var express = require('express');
var router = express.Router();
router.all('/', function (req, res, next) {
var cartTgt = [];
if (req.session.cart !== undefined) {
cartTgt = req.session.cart;
}
res.render('cart', {title: 'Your Cart', cart: cartTgt,message: 'Successfully Added'});
});
module.exports = router;
order.js
var express = require('express');
var router = express.Router();
router.all('/', function (req, res, next) {
var message = '';
if (req.method === 'POST') {
if (req.session.cart === undefined) {
req.session.cart = [];
}
var item = {};
item.itemname = req.body.itemname;
item.quantity = req.body.quantity;
req.session.cart.push(item);
console.log(req.session.cart);
}
res.render('order', {title: 'Order Form', message: 'The item has been added to the cart!'});
});
module.exports = router;
cart.jade
html
head
title= title
link(rel='stylesheet', href='/stylesheets/style.css')
body
header
h1= title
hr
section
form(method='post' action='/cart')
table
thead
tr
th Item Name
th Quantity
th Update
th Delete
tbody
each item in cart
tr
td #{item.itemname}
td #{item.quantity}
td: input(type='submit',value='Update')
td: form(method='post' action='/cart')
input(type='submit',value='Delete')
br
p= message
order.jade
html
head
title= title
link(rel='stylesheet', href='/stylesheets/style.css')
body
h1= title
hr
form(method='POST', action='/order')
label Item Name:
br
input(type='text', name='itemname')
br
label Quantity:
br
input(type='text', name='quantity')
br
input(type='submit')
br
a(href='/') Home Page
br
a(href='/cart') Cart Page
hr
p= message
Solution:
You are using nested form to update and delete, besides you are not sending which item quantity is to be updated or deleted. Thus, better option is to eliminate the nested forms and use simple anchor tags, in which you can send a GET request with itemname in the query string and on cart.js retrieve the itemname and update the req.session.cart as you need.
Cart.jade
td: a(href='http://yourwesite/cart/update?item='+item.itemname) Update
td: a(href='http://yourwesite/cart/delete?item='+item.itemname) Delete
Cart.Js
app.get('/update',function(req,res,next){
// get the itemname from querystring using req.query.itemname
// and perform operations in the req.session.cart array
var temp = req.session.cart.map(function(value,index,array){
if(value.itemname === req.query.itemname){
value.quantity +=1;
}
return value;
});
req.session.cart = temp;
res.render('cart', {title: 'Your Cart', cart: req.session.cart, message: 'Successfully Added'});
});
app.get('/delete',function(req,res,next){
// get the itemname from querystring using req.query.itemname
// and perform operations in the req.session.cart array
var temp = req.session.cart.filter(function(value,index,array){
if(value.itemname === req.query.itemname){
// remove the item from the cart array
return false;
}
return true;
});
req.session.cart = temp;
res.render('cart', {title: 'Your Cart', cart: req.session.cart, message: 'Successfully Added'});
});
Notes:
If you have to use POST request then you have to have two separate forms. But you can achieve it using GET request also thus a tags are favorable for that.
In both cases:
The form should be there for each item, not for the whole table. Considering there are no more problems, only one item would be changed regardless of which "Update" button was pressed.
You're also not sending the item name to the server when submitting the form. When using HTML forms, everything you want to send in the request must be inside an <input> tag (or you use XMLHttpRequest and specify what you want manually). I suggest adding an hidden field to store it like this:
input(type='hidden' name='itemname' value='#{item.itemname}')
Also, you cannot nest HTML forms, so the two used in the table must be separated. And finally, are you sure everything worked as expected? The quantity cannot be edited without using an input tag for it in the cart page.
I suggest you change your code (inside cart.jade) as such:
html
head
title= title
link(rel='stylesheet', href='/stylesheets/style.css')
body
header
h1= title
hr
section
//form(method='post' action='/cart') -> Moved below
table
thead
tr
th Item Name
th Quantity
// No th Update, explained why below
th Delete
tbody
each item in cart
tr
td #{item.itemname}
// The whole form needs to be inside a single <td> tag, so the quantity and update columns are merged together
td
form(method='post' action='/cart')
// Send the item's name
input(type='hidden' name='itemname' value='#{item.itemname}')
// Expose the quantity as a editable text box (in an input so it gets sent)
input(type='number' name='quantity' value='#{item.quantity}')
input(type='submit' value='Update')
// The delete button form, completely contained in the <td> tag
td
form(method='post' action='/cart')
// Send the item's name
input(type='hidden' name='itemname' value='#{item.itemname}')
input(type='submit' value='Delete')
br
p= message
To avoid the duplicate hidden inputs you could try sending requests without forms: with XMLHttpRequest. I advise against using it directly so try a library like qwest or jQuery.

Proper display of user editing form (CRUD model) with checkbox

I'm making a simple CRUD model with input checkbox. I have no problems on server side, everything is fine. I use NodeJS +MongoDB. But I have problem in editing existing user. When I edit an existing user with a checked checkbox( I get JSON object with parameter checked=true ) how should I display it using JS? This is part of my users.js file in /routes/ folder
var express = require('express');
var router = express.Router();
var User = require('../../models/User');
var rest = require('restler');
router.get('/adduser', function(req, res){
var user = new User();
user.contacts.push({phone: '', email: ''});
rest.get('http://localhost:3000/api/adduser').on('complete', function(data) {
res.render('users/add', { title: 'Add New Users' , n: user});
});
});
And this is views/users/fields.jade part of file for better understanding:
.form-group
label.col-sm-2.control-label(for='email') E-mail:
.col-sm-10
input(type="email", placeholder="email", name="email", value = n.contacts[0].email,required)
.form-group
.col-sm-offset-2.col-sm-10
input#enabled(type="checkbox",style='text-align: center; vertical-align: middle;',placeholder="", name="enabled", value = n.enabled)
| Enable user
So my problem is that I don't understand how I should display that checkbox is really checked when loading existing user.
If user is checked attribute n.enabled=true and if not n.enabled=false. So if user is checked on load of that user I need the input filed to be checked.
I've tried it to do the following way, but it wrote me that n wasn't defined...and I don't know how to pass n as the parameter for that function:
$(document).ready(function(){
if(n.enabled=="true"){$("enabled").toggle(this.checked);}
});
In fields.jade, change value = n.enabled to checked = (n.enabled ? 'checked' : '')
Use # for id-selectors and use n.enabled directly to hide or show your element like,
$("#enabled").toggle(n.enabled);
//-^ prepend # before id selectors
toggle() will show/hide your element, To check uncheck use the prop() like
$(document).ready(function(){
$("#enabled").prop("checked",n.enabled);
});

Meteor easy search and iron-router

I'm using this easy serach for my project https://github.com/matteodem/meteor-easy-search
my search Index
EasySearch.createSearchIndex('searchIndex', {
'collection' : blog,
'field' : ['title', 'tags'],
'limit' : 20,
"use":"mongo-db",
'query' : function (searchString) {
// Default query that will be used for searching
var query = EasySearch.getSearcher(this.use).defaultQuery(this, searchString);
return query;
}
});
and now I have search box and when User enters something and click on enter I want to route to search page
this.route("search",{
path:'/search/:slug',
waitOn:function(){
//here I want the search data to be sent to search page
var query=this.params.slug;
EasySearch.search('searchIndex', query, function (err, data) {
console.log(data);
});
},
data:function(){
}
});
In this router I want the searchIndex data to be sent to search page, how to do this
my click event
'submit .search':function(e){
e.preventDefault();
var quer=$("#query").val();
// Router.go('search');
}
UPDATE
My main question is in the router waiton function how we get the data in callback and send it to the search page?
In your click event handler, you have commented out the line: Router.go('search').
If you write
Router.go('search', {slug: quer})
That would route you to the search page with the query data collected from the page, if that is what you want.

Categories