It's about time I call in the big guns for this as I can't seem to figure it out.
I have a simple CRUD API in Node. I'm using EJS on the front-end. Essentially, I've got a selectAllRecords view where I display a table of all the records. I have a button next to each record to edit the record. When the button is clicked, it redirects to an editrecord.ejs page, hits the API for a single record where each line is displayed as a value in an input box. From there, I have an onclick method with an XMLHttpRequest making a put request to update the database. However, I'm getting an error - 500 (Internal Server Error) - I'm sure it's something fairly simple I'm missing, but I can't seem to figure it out.
Any help is greatly appreciated! Code below:
First on my view:
<script type="text/javascript">
function someFunc() {
var id = <%= id %>;
var url = '/api/edit/' + candID;
console.log('url ' + url);
var name = document.getElementById("name").value;
var email = document.getElementById("email").value;
var data = {
name: name,
email: email,
}
var json = JSON.stringify(data);
console.log('json ' + json);
var xhr = new XMLHttpRequest();
xhr.open("PUT", url, true);
xhr.setRequestHeader('Content-type', 'application/json; charset=utf-8');
xhr.send(json);
};
and in my queries.js file:
function updateCandidate(req, res, next) {
var candID = parseInt(req.params.id);
console.log('hit update');
console.log('name ' + req.body.name);
db.none('update cands set name=$1, email=$2 where id=$3',
[req.body.name, req.body.email, candID])
.then(function () {
var candID = candID
var name = data.name;
var email = data.email;
res.render("edited", {"candID":candID, "name":name, "email":email});
})
.catch(function (err) {
return next(err);
});
}
A potentially important note, when I hit the update button and execute the someFunc() function, the dev tool logs show a PUT request to 'api/edit/50' (or whatever ID) and '500 (Internal Server Error)' -- If i hard reload the 'getAllRecords' view, the updates are reflected so it's an issue with the render or redirect (I've tried both)
EDIT
As suggested, I removed the render from the updateCandidate method, but I still get a 500 Internal Server Error. the devtools show me the PUT request is hitting the right URL so i'm really not sure why this isn't functioning correctly. Updated code below...
function updateCandidate(req, res, next) {
var candID = parseInt(req.params.id);
db.none('update cands set name=$1, email=$2, client=$3, jobtitle=$4, question1=$5, question2=$6, question3=$7 where id=$8',
[req.body.name, req.body.email, req.body.client,
req.body.jobtitle, req.body.question1, req.body.question2, req.body.question3, candID])
.then(function (data, err) {
res.status(200)
.json({
status: 'success',
message: `Edited Candidate`
});
})
.catch(function (err) {
return next(err);
});
}
You are sending an ajax request to update the record. So, you should not try to render a view or redirect user as the response of this request. Instead, you can send back a JSON object with some properties e.g. "status".
Then on client side, you check the returned JSON response and based on "status" parameter ( or any other you chose ), you can either update your data or reload the page using window.reload on client side.
Your db query says
db.none('update cands set name=$1, email=$2 where id=$8', [req.body.name, req.body.email]) ...
Shouldn't it be
db.none('update cands set name=$1, email=$2 where id=$8', [req.body.name, req.body.email, candID])
Related
I'm trying to allow users to type a search query into a box on an index.html page and have it send them to a results.html page with results displayed.
Currently I have this working only on an index.html page where the old HTML is removed and replaced with the search results.
//Pertinent Node code:
app.get('/', function(req, res){
res.header("Access-Control-Allow-Origin", "*");
res.redirect('index.html');
});
// A search box in index.html calls the /search below
app.get('/search', function (req, res) {
res.header("Access-Control-Allow-Origin", "*");
const item_id = req.query.item_id;
var json = {};
var sql_query = "a SQL query";
var result = connection.query(sql_query, function(err, result, fields) {
if (err) throw err;
json["result"] = result;
console.log("Sent JSON to client");
res.send(JSON.stringify(json));
});
})
//Client-side:
function get() {
var search = document.getElementById("search").value;
// Validate input to prevent injections
var new_search = search.replace("<", "");
var validated = new_search.replace(">", "");
var url = host + "/search?search=" + validated;
fetch(url, {method : 'GET'})
.then(checkStatus)
.then(function(responseText) {
var json = JSON.parse(responseText);
displaySearchResults(json, search);
})
.catch(function(error) {
});
}
What I'm trying to do is similar to what you might see on Google where clicking search send you to a new page with a url like: "https://www.google.com/searchresults?query=bicycles" that displays a different HTML page from index.html (such as results.html) with the JSON from index.html being moved to and processed in results.html.
How can I make this happen?
Adding some details to what Brad kindly mentioned in comments.. The full solution is:
<form action="search.html" method="GET" name="search">
Then in the Javascript file for search.html, access the form data with:
var search = window.location.search;
If you need to get the "?search=" out of the data, instead use:
var search = window.location.search.replace("?search=", "");
I am using casperJS to got ta a page and collect an id from the URL, this is what my start function is doing. I would then like to put the id in to a new url and go there.
This works for the user var, this is coming in from the terminal. However sid is undefined and not the value I updated it to.
Any help would be appreciated. I am wondering if I found a limitation with casperJS. please not that this is not the full code (as that is much longer), if you message me I can provide you the whole script.
var user = decodeURIComponent(casper.cli.get(0).replace(/\+/g, ' '))
var sid
casper.start('https://editor.storify.com/', function() {
sid = this.getCurrentUrl()
sid = sid.split('/')[3]
})
casper.thenOpen('https://storify.com/' + sid, function() {
console.log('lets view the posts')
console.log(token)
console.log(sid)
if (dev)
this.capture('storeheading.png')
})
you can solve this problem by warping the thenOpen inside of a then
casper.then(function() {
casper.thenOpen('https://storify.com/' + sid, function() {
console.log('lets view the posts')
console.log(token)
console.log(sid)
if (dev)
this.capture('storeheading.png')
})
})
I want to know when a user logs in successfully onto Facebook he is redirected to home page with its first name and last name being part of the url.
How is that process being carried out and how to do the same using nodejs.
var checkSession=require('./../custom-modules/sessionManager');
var express=require('express');
var router = express.Router();
var builtLoginMaster=require('./../custom-modules/BuiltLoginMaster');
var scripts=require('./../cdnscripts.json');//cdn scripts
//handle login authentication
router.post('/logincheck',function(req,res,next){
console.log("got hit on authenticate url");
var session=req.session;
var email = req.body.email;
var pass = req.body.password;
builtLoginMaster.authenticateUser(email,pass,function(object){
if(object!==null)
{
console.log('Rendering chat page and result');
console.log("setting session");
// console.log(session);
session.user=object.toJSON();//set user object in session
//here home page
//here only home page rendered with same '/logincheck' whereas i want something "http://example.com/firstname.lastname"
res.render('home',{title:"Twiddle",
url:scripts,
user:object.toJSON()});
}
else{
session.err="Invalid credentials";
}
});
});
//=============================Root file===========================
router.get('/',checkSession,function(req,res,next){
console.log("after checked session");
console.log(req.session);
if(!req.isLoggedIn)
{
console.log('user not logged in');
res.render('login',{ title:'Login Page',
url:scripts,
session:req.session});
}
else
{
res.render('home',{title:"Twiddle",
url:scripts,
user:req.session}) ;
console.log("redirect to home");
}
});
router.get('/register',function(req,res,next){
res.render('register',{ title:'Registration',
url:scripts});
});
router.get('/test',function(req,res,next){
res.render('test',{ title:'test',
url:scripts});
});
module.exports = router;
Instead of
res.render('home...
what you wanna do instead is
res.redirect('/user/' + user.username);
Note, you should use /user/:username instead of just /:username because that could get tricky and handling that kind of "unified" path would not be very efficient. You'll essentially be querying the database on every request /xyz to check whether xyz is a valid user/name or just another path.
Now from the /logincheck you assigned the user object in session so it'll be available in req.session.user on each new request. So you can in a way just continue on from there.
You then want to define the path /user/:username
app.get('/user/:username', function(req, res, next){
// Here, if you don't want just anybody to view this page, you can verify
if(req.session.user.username != req.params.username) return res.status(401).send('Unauthorized!');
// Then continue to render whatever you like
res.render('home',{title:"Twiddle", user:req.session.user});
});
Some resources for more info on the following:
req.session,
req.params
A bit of a newbie here. I've been looking for an answer that works and found some similarities in a Jade problem but I'm not using Jade. I have passed an "user" attribute into an HTML view as so:
app.get('/profile', isLoggedIn, function(req, res) {
res.render('profilePage/profilePage.html', {
user : req.user // get the user out of session and pass to template
});
});
Then, in my profile HTML, I can access my user property like so:
<%=user.local.firstname%>'s Profile
However, I want to allow Stripe to send the user's credit card info via the Stripetoken. I have managed to include a variable amount from a text field the user inputs. However, I want to append the user property so I can use it in my callback. Here is the javascript/jquery that's included in the profile html:
<!-- New section -->
<script type="text/javascript">
<!-- Fill in your publishable key -->
Stripe.setPublishableKey('pkkey');
var stripeResponseHandler = function(status, response) {
var $form = $('#contactForm');
var $amount = $('#amount').val();
if (response.error) {
// Show the errors on the form
$form.find('.payment-errors').text(response.error.message);
$form.find('button').prop('disabled', false);
} else {
// token contains id, last4, and card type
var token = response.id;
// Insert the token into the form so it gets submitted to the server
$form.append($('<input type="hidden" name="stripeToken" />').val(token));
$form.append($('<input type="hidden" name="amount" />').val($amount));
// and re-submit
$form.get(0).submit();
}
};
jQuery(function($) {
$('#contactForm').submit(function(e) {
var $form = $(this);
// Disable the submit button to prevent repeated clicks
$form.find('button').prop('disabled', true);
Stripe.card.createToken($form, stripeResponseHandler);
// Prevent the form from submitting with the default action
return false;
});
});
</script>
As you can see, I have managed to append the $amount variable so I can access it in the callback:
module.exports = function(app, passport) {
app.post('/stripe', function(req,res) {
// =====STRIPETOKEN======
var transaction = req.body;
var stripeToken = transaction.stripeToken;
var donationAmount = transaction.amount;
stripe.customers.create({
source : stripeToken,
account_balance : 0
},function(err, customer) {
if (err) {
console.log(err);
} else {
console.log("Success!");
}});
// ====CREATE CHARGE======
var charge =
{
amount : donationAmount,
currency : 'USD',
card : stripeToken
};
stripe.charges.create(charge, function(err, charge) {
if(err)
console.log(err);
else
{
res.json(charge);
console.log('Successful charge sent to Stripe!');
console.log(charge);
};
});
// ====PROFILE PAGE REDIRECT=====
res.render('profilePage/profilePage.html', {
});
});
So here's my problem. I want to pass the user's information, kind of like I did the amount, into the post method so when it redirects on success, I can pass it back in the res.render function, as well as send it to Stripe for description purposes. The only thing I can think of is to put the user info in a hidden field in HTML and access it like that, but that sounds messy and not proper.
This is my first time posting here so I apologize if it was too lengthy or not specific enough. Thanks!
The answer was in the way I was declaring passport and stripe in my application. Make sure you declare passport after everything to make the user variable available to stripe and all views.
I'm kind of new using node.js. I'm using express with jQuery and mySQL.
I'm trying to add a record in to the db by filling 2 fields in the UI and then call a server via getJSON to add the record. I'm giving the details into the url.
This is not working.
Here is a snippet from the code (I adjust it and eliminate all the checks to make it short)
client side
$("#btnAddEvent").click( function() {
// Send details to the server to add a record to the db
var url2Send = '/insert/title/' + $("#Title").val() + '/desc/' +
$("#Desc").val()
$.getJSON( url2Send, function( data ) {
$("#Title").empty();
$("#Desc").empty();
});
});
}
Server side
router.get('/insert/title/:t/desc/:d', function(req, res) {
var qry = "insert into events (evt_title, evt_desc) " +
"values (\'" + req.params.t + "\',\'" + req.params.d + "\')";
app.connection.query( qry, function(err, qry_res) {
if (err) {
console.log( 'Error: ' + err );
return false;
}
else {
console.log( 'Event added .....' );
res.json(dd);
return true;
}
});
});
When I run and try to go through this code, it doesn't succeed and display the homepage instead. In the server console it shows it's trying to get the following
GET /?add_event_title=lkjhkjhkj&add_event_desc=kjhkjhkj 200 306.584 ms - 19709
add_event_title and add_event_desc are the IDs of the UI fields in the form used to define the db fields evt_title and evt_desc respectively.
Any explanation for this please? Any way to make the communication smooth?
Thanks