MongoDB / Mongoose - Adding new database entry crashes page - javascript

I have problem with adding a team to my database, I have an index page at the moment which is just showing all of the teams in the database at the moment. When I go to this localhost:3000/team which is seen below for team.jade, I enter team name and press the submit button. When I then go to the index page, there it is, my new team is there.
But when I press the submit button, I actually get an error saying:
Express
500 TypeError: Cannot read property 'teamName' of undefined
at module.exports (/home/declan/nodeapps/tournamentManager/routes/index.js:126:24)
at callbacks (/home/declan/nodeapps/tournamentManager/node_modules/express/lib/router/index.js:160:37)
at param (/home/declan/nodeapps/tournamentManager/node_modules/express/lib/router/index.js:134:11)
at pass (/home/declan/nodeapps/tournamentManager/node_modules/express/lib/router/index.js:141:5)
at Router._dispatch (/home/declan/nodeapps/tournamentManager/node_modules/express/lib/router/index.js:169:5)
at Object.router (/home/declan/nodeapps/tournamentManager/node_modules/express/lib/router/index.js:32:10)
at next (/home/declan/nodeapps/tournamentManager/node_modules/express/node_modules/connect/lib/proto.js:190:15)
at Object.handle (/home/declan/nodeapps/tournamentManager/app.js:34:5)
at next (/home/declan/nodeapps/tournamentManager/node_modules/express/node_modules/connect/lib/proto.js:190:15)
at Object.static (/home/declan/nodeapps/tournamentManager/node_modules/express/node_modules/connect/lib/middleware/static.js:55:61)
I'm not sure why I get this, line 126 of index.js is actually this line from below:
var name = teamForm.teamName;
This is one of the first lines creating the new database entry, so if it couldn't read that property, it isn't adding it to the database. That was my thinking, but when I reload the index page, there is my new database entry, so why do you think it isn't working?
index.js # routes
/**
* Add a new Team to database
*/
app.post('/team', function(req, res) {
util.log('Serving request for url[GET] ' + req.route.path);
var teamForm = req.body.teamForm;
var name = teamForm.teamName;
var newTeam = new Team();
newTeam.name = name;
newTeam.save(function(err, savedTeam){
var message = '';
var retStatus = '';
if(!err){
util.log('Successfully created team with Name : ' + name);
message = 'Successfully created new team : ' + name;
retStatus = 'success';
} else {
util.log('Error while creating team : ' + name + ' error : ' + util.inspect(err));
if(err.code === 11000){
message = 'Team already exists';
}
retStatus = 'failure';
}
res.json({
'retStatus' : retStatus,
'message' : message
});
});
});
team.jade # views (html template, you can see the needed id's etc)
extends index
block content
div.row-fluid
div.span9
h2 New Team
div.well.sidebar-nav
div.teamList
form.form-horizontal(method="post", id="team-form")
div.control-group
label.control-label(for="teamName") Team Name :
div.controls
input.input-small(type="text", id="teamName")
div.control-group
div.controls
button#teamConfirm.btn.btn-primary.btn-mini(href='#') To DB
br
p This page is used to demonstrate how an 8 team single elimination tournament would be represented in the final design of my project. The pseudo code conjured up in my initial hand-in document was originally used here to produce the same result. The pseudo code helped create this set of seeded brackets, so that the matches correspond to the seeds of the tournament. For the 8 team bracket, I worked back through from the final, where seeds 1 and 2 should face each other, until I was left at round 1 of the brackets. This was used to give myself a 'new' set of seeds which were in the correct order to just be placed into these brackets.
div.span3
div.well.sidebar-nav
h4 To-Do List:
p - Enter list of teams manually from this page.
p - Do a test to show a bracket with random seed.
p - Show rankings after tournament
team.js # js
var newTeam = function(){
$('#teamConfirm').click(function(){
newTeam.teamForm();
});
};
newTeam.teamForm = function(){
var teamForm = {
teamName : $('#teamName').val()
};
// Basic validation
$.post('/team', {'teamForm' : teamForm}, function(response) {
console.log(response);
});
};
newTeam();
index.js # js
var Main = {};
Main.loadScript = function(url){
var footer = document.getElementById('footer');
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
footer.appendChild(script);
}
$(document).ready(function(response){
Main.loadScript('js/login.js');
Main.loadScript('js/signup.js');
Main.loadScript('js/team.js');
});

I assume that this is because req.body is not being parsed to JavaScript object ( it remains as JSON string ). First check whether you are using
app.use(express.bodyParser());
before any route. If it is not that, then try using .ajax instead of .post with contentType set:
$.ajax({
// some other settings
contentType : "application/json"
});
It might be that content types are messed up and Express is not parsing JSON string received from the client. The other thing you might try is simply doing ( on the server side ):
app.post('/team', function(req, res) {
var body = JSON.parse( req.body );
// other code
}
Perhaps wrapping the additional line with try{}catch{} block.

Related

When I try to use Node.js in Visual Studio Code’s terminal, I get “document is not defined” error messages

I’m brand new to programming and I’m currently working on a MySQL database. I’m using Visual Studio Code for all of my JavaScript, HTML, and CSS files.
I have a JavaScript server file that is giving me issues. Our professor gave us his code for the server JavaScript file (which is posted below), his client JavaScript file (which is named contacts.js), and his HTML file.
He told us to open the server JavaScript file, open a terminal and type: node contacts.js. However, doing this gives me error messages that say that the document is not defined.
Occasionally, I'll even get "module not found" errors.
We just did a similar project last week and the terminal worked just fine with a similar node.js command, but I’m running into issues now and don’t know what to do. Hours on Google haven’t helped at all and my professor can’t be contacted for the entire week.
I’m not sure how to get beyond this “document not defined” error. Any help would be appreciated.
Below is the server JavaScript file:
// The following statements are for database connection and queries
var mysql = require('mysql'); // use the msql libraries. Must use 'npm install msyql --save' before using
var bodyParser = require('body-parser'); // use the body-parser library for JSON use. Must 'npm install body-parser --save'
// Set up the SQL connection to the MYSQL database. This will all need to match what you set up in your DB
var connection = mysql.createConnection({
host:'localhost',
user: 'mike',
password: '********',
database: 'contacts'
});
// do the actual connecting by calling the connect method and log the result
connection.connect();
console.log("After connection to DB established in server, setting up web server");
//The following are for web server setup - we are using the express library that makes this all pretty easy
const express = require('express'); // use express library. must use 'npm install express --save'
const cors = require('cors'); // use cors library. must use 'npm install cors --save'
const app = express(); // get the express application object
const path = require('path'); // use the path library for managing paths. must use 'npm install path --save'
const port = 3000; // constant for the port we're using.
// set up the use of JSON url-encoding. Allows us to put all the arguments in the url
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
// We want to also serve static pages. This command sets that up. In my case, I created a subdirectory called 'public'
// and put the main html page (contacts.html), the javascript client file (contacts.js) and the CSS file (contacts.css)
// in that directory, and therefore I can get everything I need by just goint to (localhost:3000) and it all just works
app.use(express.static('public'));
// This is our main save handler (express calls these 'middleware'). The request coming from the client is a post
// and all the parameters/values are in the query object in the request object (req).
// All the field names here must match the names in the form (name='blah') which we use when we craft the request
// in the javascript saveContact().
// NOTE: we have to use the cors() method to make this all work. Look up cors (Cross-Origin Resource Sharing) to learn about it
app.post('/save', cors(), function (req, res) {
console.log("trying to save contact (post)"); // Log what we're doing
console.log(req); // log the actual request
var curId = req.query.Id; // Get the Id from the query object
var firstName = req.query.fname; // get the fname from the query object
var lastName = req.query.lname; // get the lname from the query object
var age = req.query.age; // etc. etc. etc.
var phone = req.query.phone;
var email = req.query.email;
// We can use the same handler for both cases of saving information:
// 1)we INSERT the new contact in the DB - the Id is 0 in this case
// 2)we UPDATE an existing contact in the DB - the Id is the correct Id for the contact we're updating
// Here we're crafting the appropriate SQL statements using the values above - either INSERT or UPDATE
if (curId > 0) {
var sql = `UPDATE contacts SET fname = '${firstName}', lname = '${lastName}', age = ${age}, phone = '${phone}', email = '${email}' WHERE Id = ${curId}`;
} else {
var sql = `INSERT INTO contacts (fname, lname, age, phone, email) VALUES ('${firstName}', '${lastName}', '${age}', '${phone}', '${email}')`;
}
// Here we're creating the query and the callback function for when we get a response from the DB asynchronously
// This same method executes the SQL call to the database connection we established earlier (above)
connection.query(sql, function (err, result) {
console.log("Trying to save contact into DB"); // log what we're doing
if (err) throw err; // If we get an error, send the error along
console.log(result.affectedRows + " record(s) saved");
res.status(201).send(result); // set the status code (201 = successful add) and send it
console.log(`result of post is: ${result}`); // log the result
console.log(result);
});
});
// This handler is for deleting a user given a valid Id.
// NOTE: we have to use the cors() method to make this all work. Look up cors (Cross-Origin Resource Sharing) to learn about it
app.post('/delete', cors(), function (req, res) {
console.log("trying to delete contact (post)"); // log what we're doing
console.log(req); // log the actual request we received
var curId = req.query.Id; // get the Id from the query object
console.log(curId); // log the Id
// As long as we have a valid Id (in variable curId), we craft the sql statement and execute the query
// all the SQL commands are asynchronous so we provide a callback function
if (curId > 0) {
var sql = `DELETE FROM contacts WHERE Id = ${curId}`; // This is the right SQL statement
connection.query(sql, function (err, result) {
console.log("Trying to delete contact from DB"); // log what we're trying to do
if (err) throw err; // if we get an error, pass it along to the client
console.log(result.affectedRows + " record(s) deleted");
res.status(200).send(result); // otherwise set the status to success (200) and send the result to the client
console.log(`result of post is:`); // log the result
console.log(result);
});
}
});
// THis is our static GET Handler if you just open a browser and type in 'http://localhost:3000'. the '/' means root
// and so this our default page (often called 'index.html' but in this case it's our 'contacts.html')
// Simply send the contacts.html page by getting the default path (wherever we have this javascript file)
app.get('/', function (req, res) {
console.log(req.params);
res.sendFile(path.join(__dirname + '\\contacts.html'));
});
// This is our handler for getting the full list of contacts
// NOTE: we have to use the cors() method to make this all work. Look up cors (Cross-Origin Resource Sharing) to learn about it
app.get('/list', cors(), function (req, res) {
console.log(`inside list GET function, req object is ${req}`);
console.log(req);
// Craft the simple select statement that just gets everything in the contacts table
var sql = `SELECT * FROM contacts`;
//Create the query and execute it, sending the appropriate result back to the client
connection.query(sql, function (err, result) {
console.log(`Trying to get list from DB - result is ${result}`);
console.log(`Inside get list - result first row is ${result[0]}`);
if (err) throw err; // if we get an error, pass it along to the client
res.send(result); // simply send the result of the query to the client.
console.log(`result of GET to list is: ${result}`);
});
});
// This is what actually starts the express server, listening on the port constant we defined at the beginning
// of the file (in this case I'm using 3000) and logging what we're doing.
app.listen(port, () => console.log(`Example app listening on port ${port}!`));
Below is the client JavaScript file:
// This JavaScript file is in support of the contacts application.
// Users can see and manage all their contacts, where a contact is [Id, firstname, lastname, age, phone, email]
// There are functions to manage the http interactions with the server backend
// and to manage the screen/user experience
// This is a globally available array of contacts we get back from the server. Set it initially to an empty array
document.contactList = [];
// This is the function queries the server (using an HTTP GET) to get the list of contacts
// We save the contacts to a globable variable in the document (contactList) and we fill
// both the table at the bottom of the document and a drop-down list used for management
// both of those functionality are function calls ('fillContactTable()' and 'fillContactSelect()')
function getContacts() {
console.log(`Getting contact list from server`); // log what we're doing
var xhttp = new XMLHttpRequest(); // create a variable for HTTP protocol
xhttp.onreadystatechange = function() { // callback function for when a response occurs
console.log(this.responseText); // log the response
// readyState is the XMLHttpRequest state that means we're done. Status is what is returned from the server
// a status code anywhere in the 200's is success. SO if we're done and get a success return code, then we're good!
if (this.readyState == 4 && (this.status >= 200 && this.status < 300)) {
console.log(`Got the contact list successfully`); // Log that we're good
document.contactList = this.responseText; // The response is the actual list of contacts.Set to globabl var in document
fillContactTable(); // Fill the table
fillContactSelect(); // Fill the drop down list (select element)
} else {
console.log(`failed to get contact list`); // Log failure if that's what we got
}
}
// We've set the callback function that handles the result. This is the actual setting up the http request (the open method)
// and the actual sending of the http request (send method)
xhttp.open("GET", "http://localhost:3000/list", true);
xhttp.send();
}
// Given an Id of a contact, get the rest of the contact information and return it
// The pLocal parater is in case we want to get the contact information from the server instead of getting it from
// the global variable (document.contactList). Default is to be local.
function getContactById(pId, pLocal = true) {
console.log(`Getting contact by ID = ${pId}`); // log what we're doing
if (pLocal) { // If we're local, get the data from document.contactList
var contactsJSON = JSON.parse(document.contactList); // parse the contactList into JSON format - easier to deal with
// Loop through all the contacts in the JSON formated list of contacts to look for the one we want (by Id)
for (loopIndex = 0; loopIndex < contactsJSON.length; loopIndex++) {
if (contactsJSON[loopIndex].Id == pId) { // if Id's match, we're good but log what we found
console.log(`Found contact in getContactById. Index = ${loopIndex}`);
console.log(contactsJSON[loopIndex]);
return contactsJSON[loopIndex]; // Return the found contact
}
}
console.log(`Did not find the contact in getContactById`); // log the fact that we didn't find it and return null
return null;
// For now, if we're not local just return null. Will add the code to get the data from the server later
} else {
return null;
}
}
// Simple function that just clears the form that we use for showing, creating new, and updating contacts
function clearEditForm() {
console.log("clearing the contact form"); // Log what we're doing
// Set all the values to empty (or 0 for the Id - that has to be a number)
document.getElementById('contact_id').value = 0;
document.getElementById('contact_fname').value = "";
document.getElementById('contact_lname').value = "";
document.getElementById('contact_age').value = "";
document.getElementById('contact_phone').value = "";
document.getElementById('contact_email').value = "";
// Now control the user experience. Hide the ID fields and change the name of the button to "Insert"
document.getElementById('contact_id').hidden = true;
document.getElementById('contact_id_label').hidden = true;
document.getElementById('save_button').innerHTML = "Insert Contact";
document.getElementById('save_button').name = "Insert Contact";
}
// Main function that saves the contact form. We have two cases to deal with:
// 1) We're inserting a new contact. In that case, the Id (curId below) will be 0
// 2) We're updating an exesting contact. In that case, the Id will NOT be 0
// If the ID is not a number >= 0, we have a problem so we don't do anything
function saveContact() {
console.log("Attempting to save contact"); // Log what we're doing
// Get all the values from the elements in the form by name.
var curId = document.getElementById('contact_id').value;
var curFName = document.getElementById('contact_fname').value;
var curLName = document.getElementById('contact_lname').value;
var curAge = document.getElementById('contact_age').value;
var curPhone = document.getElementById('contact_phone').value;
var curEmail = document.getElementById('contact_email').value;
console.log(`Trying to save contact in saveContact. Id = ${curId}`);
// As long as we have a valid Id (number at least 0) we'll make the http request (a POST)
if (curId >= 0) {
var xhttp = new XMLHttpRequest(); // Create a new HTTP object and put it in xHTTP variable
// As in all of our interactions implementing http, we supply a callback function for when we actually get a response
// Remember, all http request/responses should be asynchronous, and so we have to use callbacks
xhttp.onreadystatechange = function() {
console.log(this.responseText); // log what's happening
// If readyState shows we're done (value == 4) and status code is in the 200's we got a success response
if (this.readyState == 4 && (this.status >= 200 && this.status < 300)) {
console.log(`saved the contact successfully`); // Log our success
getContacts(); // Re-get our contact list since it has changed
} else {
console.log(`failed to save contact `); // Log our failure response
console.log(this.status); // log the actual status code
console.log(this.responseText); // log the actual response text
}
}
// Here we're crafting the http POST request with all the parameters urlencoded. Look up url encoding to understand it
// As usual, the open method is used to set up the call, and the send method actually sends the request
xhttp.open("POST", `http://localhost:3000/save?Id=${curId}&fname=${curFName}&lname=${curLName}&age=${curAge}&phone=${curPhone}&email=${curEmail}`, true);
xhttp.send();
}
}
// Function to delete a contact by creating the right server http request (a POST)
// We'll pass the Id of the contact we want to delete in the url (url-encoded)
// We'll get the name of the contact to be deleted and prompt the user to verify that they want to really delete the contact
// look up the window method 'confirm' to understand how that works
function deleteContact() {
console.log("Attempting to delete contact"); // Log what we're doing
var contactList = document.getElementById('contacts_list'); // get the drop-down select element in the form
var curId = contactList.value; // get the value of the form, which will be an Id of the contact to be deleted
var curIndex = contactList.selectedIndex; // We need the index of the option chosen to get the name for prompting the user
var curName = contactList.options[curIndex].text; // get the name from the option list based on the index
console.log(`Trying to verify delete. curid = ${curId}, curIndex = ${curIndex}, and curName = ${curName}`);
// Prompt the user to confirm using the window.confirm method. If they say ok, confirm returns true
// if they say cancel, confirm returns false. We're checking for the false, thus the not (!) at the beginning of the condition
if (!confirm(`Are you sure you want to delete contact: ${curName}?`)) {
return; // If we're here they said cancel, so just return out of here
}
console.log(`Trying to delete contact in fillEditForm. Id = ${curId}`);
if (curId.length > 0) { // Make sure we have a good Id
var xhttp = new XMLHttpRequest(); // create the http object
// Here's our callback for the asynchronous return. As long as we get a good status code, we update the form appropriately
xhttp.onreadystatechange = function() {
console.log(this.responseText); // log the actual response
// readyState 4 means we're done, and status in the 200's means success, so re-get the contact list from the server
if (this.readyState == 4 && (this.status >= 200 && this.status < 300)) {
console.log(`deleted the contact successfully`);
clearEditForm(); // clear the form since we deleted the contact
getContacts(); // get the contacts from the server
} else {
console.log(`failed to delete contact list`);
}
}
// Create the actual request and send it.
xhttp.open("POST", `http://localhost:3000/delete?Id=${curId}`, true);
xhttp.send();
}
}
// Simple function to clear the table element. We delete all the rows backwards. Make the function generic by allowing
// a parameter (pTable) which is the name of the table to be reset if there is more than one on the form
function tableDeleteRows(pTable = "") {
var curTable;
if (pTable.length == 0) {
curTable = document.getElementById('contacts_table');
} else {
curTable = document.getElementById(pTable);
}
// We start at the end of the rows (rows[length-1]), deleting backwards until we delete all of them
for (i = curTable.rows.length - 1; i >= 0; i--) {
curTable.deleteRow(i);
}
}
// Simple function to clear a drop-down select element. We delete all the rows backwards. Make the function generic by allowing
// a parameter (pSelect) which is the name of the select element to be reset if there is more than one on the form
function selectDeleteOptions(pSelect = "") {
var curSelect;
if (pSelect.length == 0) {
curSelect = document.getElementById('contacts_list');
} else {
curSelect = document.getElementById(pSelect);
}
// Go backward from the end of the list of options in the select, removing them until we remove all of them
for (i = curSelect.length - 1; i >= 0; i--) {
curSelect.remove(i);
}
}
// Assuming we have a contact chosen in the drop-down select element, fill the edit form with all the values for that contact
function fillEditForm() {
console.log("filling the contact form"); // Log what we're doing
var contactList = document.getElementById('contacts_list'); // get the drop-down list
var curId = contactList.value; // the selected element Id is the value of the list
console.log(`Trying to find contact in fillEditForm. Id = ${curId}`);
var curContact = getContactById(curId); // Get the whole contact by calling the function
console.log(curContact); // log the contact we're using to fill the form
// As long as we have a good contact, we fill the form
if (curContact != null) {
document.getElementById('contact_id').value = curContact['Id'];
document.getElementById('contact_fname').value = curContact['fname'];
document.getElementById('contact_lname').value = curContact['lname'];
document.getElementById('contact_age').value = curContact['age'];
document.getElementById('contact_phone').value = curContact['phone'];
document.getElementById('contact_email').value = curContact['email'];
}
// after we fill the form, we set elements appropriate to things like update and delete instead of add new
document.getElementById('contact_id').hidden = false;
document.getElementById('contact_id').disabled = true;
document.getElementById('contact_id_label').hidden = false;
document.getElementById('save_button').innerHTML = "Update Contact";
document.getElementById('save_button').name = "Update Contact";
}
// This function fills the table at the bottom of the document with all the contacts and all the information
function fillContactTable() {
console.log("Filling the contacts table in the form"); // Log what we're doing
tableDeleteRows("contacts_table"); // Reset the table
// if we don't have anything in the global contact list - forget it and return
if (document.contactList.length == 0) {
console.log("the contact list/array is empty!");
return;
}
// We have contacts in the global array, so first parse the array into JSON and process it
var contactsJSON = JSON.parse(document.contactList);
var properties = ['Id', 'fname', 'lname', 'age', 'phone', 'email']; // we need the property names
var tr, curRow; // variables for table properties
var contactTable = document.getElementById("contacts_table"); // get the table element
// cycle through the rows in the contacts array
for (var rowIndex = 0; rowIndex < contactsJSON.length; rowIndex++) {
console.log(`Creating table rows, rowindex is ${rowIndex}`);
tr = document.createElement('tr'); //create a new table row element
curRow = contactsJSON[rowIndex]; // get the current row from the array
console.log(curRow); // log the data in the current row
// Cycle through the columns - defined in the property array above and add column elements to the row in the table
for (var i = 0; i < properties.length; i++) {
console.log(`Creating table columns for row ${i}, property is ${properties[i]} value is ${curRow[properties[i]]}`);
var td = document.createElement('td'); // create a data element for the column
td.appendChild(document.createTextNode(curRow[properties[i]])); //Append the property data to the new data element
tr.appendChild(td); // append the new data element to the row element
}
contactTable.appendChild(tr); // append the row element to the table element
}
console.log("Finished procesing contacts list");
}
// Fill the drop-down select. First reset the select (removing all options), then recreate it
function fillContactSelect() {
console.log("Filling the contacts drop down select in the form"); // log what we're doing
selectDeleteOptions("contacts_list"); // Reset the select element clearing all options
// if we don't have anything in the global contact list - forget it and return
if (document.contactList.length == 0) {
console.log("the contact list/array is empty!");
return;
}
// We have contacts in the global array, so first parse the array into JSON and process it
var contactsJSON = JSON.parse(document.contactList);
var properties = ['Id', 'fname', 'lname']; // only need Id, fname, lname for drop down
var option, curRow; // variables for table properties
var contact = document.getElementById("contacts_list"); // get the select drop down element
// cycle through the rows in the contacts array
for (var rowIndex = 0; rowIndex < contactsJSON.length; rowIndex++) {
console.log(`Creating select items, rowindex is ${rowIndex}`);
option = document.createElement('option'); //create a select option element
curRow = contactsJSON[rowIndex]; // get the current row from the array
console.log(curRow); // log the data in the current row
// the value of this option will be the id, since that's what we'll use to get a contact. The text is fname + lname
option.value = curRow["Id"];
option.appendChild(document.createTextNode(`${curRow['fname']} ${curRow['lname']}`));
contact.appendChild(option); // append the option to the select element
}
console.log("Finished procesing contacts list");
}
// When the windo first loads, get the list of contacts which will also fill the table and drop down list
window.onload = function() {
getContacts();
};
You are running the wrong JS file. You want to do:
node contactserver.js
At the moment you are running contacts.js, which is client-side code.
To expand on this, you're seeing that error because document is a global variable available in browsers, but not in Node.js. Frontend code designed to run in a browser often relies in browser APIs that simply don't exist on a server, so attempting to run a client-side only file in a server environment will throw errors when it can't find global objects that only exist in a browser.
(Props to #Jon Church for the explanation from the comments below)
Turns out that contacts.js was the wrong file. Typing into the terminal: node contactsserver.js was the solution.

How to pass parameters to a template with a response redirect call to a root get request? [Express.js & Node.js]

//cards to be created in template
var coins = [];
var formattedCoins = [];
app.get("/", function(req, res){
for(x in formattedCoins){
for(y in formattedCoins[x])
console.log("From '/': " + formattedCoins[x][y].name);
}
res.render("coin.ejs", {coins: formattedCoins});
});
//retrieve form information
app.post("/getCoin", function(req, res){
var symbol = req.body.formSymbol;
request("https://api.coinmarketcap.com/v1/ticker/", function(error, response, body){
//if no error and status is OK
if(!error && response.statusCode == 200){
//data returned are not JS objects application must parse JSON data first into JS
var parsedData = JSON.parse(body);
//find coin with the same symbol submitted
for(x in parsedData){
if(parsedData[x].symbol == symbol.toUpperCase()){
//create object
var newCoin = {
name: parsedData[x].name,
symbol: parsedData[x].symbol,
usd: parsedData[x].price_usd,
btc: parsedData[x].price_btc
};
//save coin to list
coins.push(newCoin);
//filter into 2D array
formatCoins();
}
}
}
});
res.redirect("/");
});
Hey guys,
bear with me for the long slab of code I didn't know how to minimize it without leaving out anything important that might need to be looked at.
I'm currently making an application that pulls data from the 'coinmarket' API.
How I want the application to work is to render new data with the new coin received after making the post request and redirecting back to " / ". However, what happens is:
Submit Form
Server confirms that object was found and saved in the global array 'coins'.
Format it into a 2D array that can be more easily rendered into the template.
Redirect to " / " (Here is where I want the formattedCoins to be rendered)
Attempt to render "coin.ejs" with 'formattedCoins' parameter to be passed.
Page loads again without rendering 'formattedCoins'
Submit the form again with no input
Page renders with the new coin
I feel like I'm doing something wrong with how I'm routing the get request to " / " for object rendering.
Can I get some help guys? I can't see where the issue is.
Thanks!

JSON variable not retrieving updated value

I am trying to post a quote retrieved from a JSON file. My code posts a tweet every 20 seconds (for testing purposes it is 20 seconds). I can find my quote and put it in a JSON file by using the server(quoteIndex) function. The server(quoteIndex) adds a new quote to my output.json file. I know that output.json updates the {"quote": ""} part each time it finds a quote on an even index. However, in my tweetIt() function, when I assign var quoteFile = require("./output.json"), my quoteFile.quote value does not update. This is an issue because my javascript bot is a twitter bot that tweets quotes. And twitter does not allow duplicate quotes, handing me a "duplicate status" error.
This is the main code
// I wanted to start at the 8th index and continue with every even index.
var quoteIndex = 8;
// post a tweet every 20 seconds
setInterval(tweetIt, 1000*20);
tweetIt()
function tweetIt() {
//
// This will start looking for quotes to post
// It will put the quote in a JSON file
//
quoteIndex = quoteIndex + 2;
console.log('value of index: ' + quoteIndex)
server(quoteIndex);
var js = require('json-update');
js.load('./output.json', function(err, obj) {
console.log("Loaded from json:");
console.log(obj); // loads most recent quote
}); // this is what I want to tweet
var quoteFile = require('./output.json');
// Read from JSON file for the quote
var params = {
status: quoteFile.quote
}
//
// prints same quote each time, does not update
//
console.log("quote to tweet: " + quoteFile.quote)
// tweet a quote
//
// The first quote will tweet, however when the JSON file
// updates, I will get a "duplicate status" error.
// This is because my quoteFile still has not updated.
//
T.post('statuses/update', params, getData);
function getData(err, data, response) {
if (err) {
console.log("Something went wrong!: " + err);
} else {
console.log("Tweeted something!");
}
}
}
server(quoteNumber)
function server(quoteNumber) {
var fs = require('fs');
var request = require("request"),
cheerio = require("cheerio"),
url = "https://en.wikiquote.org/wiki/A_Song_of_Ice_and_Fire";
request(url, function (error, response, body) {
if (!error) {
var $ = cheerio.load(body);
var quote;
var json = {quote : ""};
$( "div.mw-parser-output ul" ).filter(function( INDEX ) {
// even indexed quotes are the ones I want
if (INDEX % 2 == 0 && (INDEX == quoteNumber)) {
quote = $( this ).text();
json.quote = quote; // this also has the most recent quote
}
});
} else {
console.log("We’ve encountered an error: " + error);
}
//
// Write our quotes out to a JSON file.
//
fs.writeFile('output.json', JSON.stringify(json, null, 4).replace(/\\n/g, " "), function(err){
console.log('File successfully written! - Check your project directory for the output.json file');
})
});
Basically, when I run the code using node.js, the first quote will tweet because the JSON file has a quote for me. Then when it is time to find the next quote using quoteIndex = quoteIndex + 2, my JSON file updates as expected in my project folder. My main issues is that in my tweetIt() function, the quoteFile.quote is not showing the updated quote, even though the JSON file has an updated quote for me. How can I have the updated quote?
Any tips would be appreciated, thanks.
Whenever you require() a file, be it a module or JSON file or native addon, it is cached once it is successfully loaded. If you need to be able to reload the JSON file, you should instead just call readFile() and JSON.parse() the resulting file data manually each time.

LDAP JS with Node JS Finding users passing in patterns of string

I am currently using LDAP JS for Authentication in Angular JS app and everything works perfectly fine.
I am now building a new view and the requirement I have is this:
I have text box in which admin will write may be a few letters of a user id present in LDAP.
I want to show app matching ID present in LDAP on a typeahead/suggestions. I know how typeahead works so that's not an issue. The issue is how can I pass a rejex or pattern matching kind of a thing for uid in search() method.
My sample code is here:
function GetAllLDAPUser(dnFilter, res) {
client.search('uid=**WHAT-PATTERN-CAN-I-PASS-HERE**' + dnFilter, opts, function(err, result) {
result.on('searchEntry', function(entry) {
// I usually read entry.object or entry.raw here , that works
});
result.on('end', function(result) {
.......
});
}
}
}
So the question is what should I pass in place of
WHAT-PATTERN-CAN-I-PASS-HERE
Results :
Suppose I type an. The typeahead will show all user id starting with an like ana, anamon, analisa etc.
I have written the final solution and closed the issue on the project's repository
For pattern matching, we need to play with the 'filter' field in option object which we pass to the search method. So I ended up doing something like below:
var dnFilter = 'ou=People,o=Intra,dc=YOURCOMPANY,dc=com'; //depends on your LDAP settings.
var query;
var matchedUsers = [];
query.LDAPName = "dummy"; //some name which resides in LDAP
//You can even have one simple variable rather than having this query object.
opts = {
scope: 'sub',
filter: (shcDisplayName = '+ query.LDAPName + ')
'
};
//Do not use 'shcDisplayName' , this will be any variable stored in your LDAP object. You need get
//the structure of LDAP end point you are working on. For me, I had one variable 'shcDisplayName'
//on which I wanted to play so I am using this variable in my filter.
client.search(dnFilter, opts, function(err, result) {
result.on('searchEntry', function(entry) {
matchedUsers.push({
'Name': entry.object.shcDisplayName,
'Id': entry.object.uid
});
}
result.on('end', function(result) {
if (matchedUsers.length) { //if any match was found.
//send the json result back
res.json(matchedUsers);
//if you want to send json back, do not use res.send() otherwise you will end up getting
//circular reference error.
}
}
result.on('error', function(ex) {
//Handle errors here if any
});
});
}
}

Using Pointers for ios App & Javascript website

I have an iphone app created as a multiplication game and saves the following into a class called 'Results'.
PFObject *Results = [PFObject objectWithClassName:#"Result"];
[Results setObject:levelNumberLabel.text forKey:#"LevelNumber"];
[Results saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) etc.
I also have a class called 'currentUser' that stores the following:
PFObject *currentUser = [PFObject objectWithClassName:#"currentUser"];
[currentUser setObject:_firstnameLabel.text forKey:#"SFirstName"];
I want to run a javascript query that 'links' these two tables. I have a point
er set up called 'currentuser' in the currentUser class and a pointer called 'currentResult'.. These hold no value (undefined).
How am I able to merge these classes together? Will it be a case of linking it through the app or using javascript? I'm slightly confused. Here is my javascript code
var Show = Parse.Object.extend("Result");
var query = new Parse.Query(Show);
query.include('currentUser');
query.find({
success: function(shows) {
for(var i = 0; i < shows.length; i++) {
var show = results[i];
var surname = results.get('SSurname');
console.log(i);
var users = show.get('currentUser');
var username = users.get("SFirstName");
$(".success").append(username + " on " + surname + "<br/>");
Any questions/help please let me know.
Any help on the subject would be greatly appreciated
Parse already gives us a User class (PFUser). Consider starting with that one.
Next, create a class that represents the result of play. "Result" (singular) is an okay name for that. It can have string and number attributes as you see fit. (name those starting with lower case, e.g. "levelNumber"). To associate a result with a user, the Result table must also have a pointer attribute to the User, call it "user".
In Objective-C, when its time to save the result of play:
PFUser *user = [PFUser currentUser]; // this is the signed in PFUser
PFObject *result = [PFObject objectWithClassName:#"Result"];
result[#"user"] = user;
result[#"some_other_col_name"] = some_other_value;
[result saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
// ...
}];
In JS, to find the all of the results created by the play of some user:
// if this is called in a cloud function, the request.user will be
// the PFUser on the client that made the request
function resultsForUser(user) {
var query = new Parse.Query("Result");
query.equalTo("user" user);
return query.find().then(function(results) {
// results are the Result objects whose user is the given user
}, function (error) {
});
}

Categories