Node.js and Express handlebars - 404 Error - node.js

For my class I have to design an app that says at the top of the page whether an incoming request is GET or POST, then has to print a table that shows all parameter names and values that were sent in the URL query string, and the property names and values that were received in the request body.
So far I have been able to get my localhost:port to work, it correctly shows whether a request is GET or POST. But when I go to the subpage that is supposed to display the tables, I get a 404 instead.
Here is the render page that I think is causing the problem:
function runQ(req) {
console.log(req.qParams);
console.log(req.body);
var context = {};
context.queryParams = [];
context.bodyParams = [];
context.queryCount = 0;
context.bodyCount = 0;
for( var p in req.qParams) {
context.queryCount++;
context.queryParams.push({'name': p, 'value': req.qParams[p] });
}
for( var p in req.body) {
context.bodyCount++;
context.bodyParams.push({'name': p, 'value': req.body[p] });
}
context.methodType = req.method;
return context;
}
app.get('/request', function(req, res) {
res.render('request', runQ(req));
});
app.post('/request', function(req, res) {
res.render('request', runQ(req));
});
I have a request.handlebar saved in my ubuntu/getpost/views folder along with the 404 and 500 handlebars.
The command I use for testing is:
$ curl --data "a=1&b=2&c=3" localhost:port
I replaced the localhost:port with an actual IP and port address when I have node running.
My console returns this on the tab that is running node:
undefined
{ a: '1', b: '2', c: '3' }
And this on the tab where I typed the cURL command:
<!doctype html>
<html>
<head>
<title>Demo Page</title>
</head>
<body>
<h1>POST Request Received</h1>
<table>
<caption><p>Request Body Table</p></caption>
<thead>
<tr>
<th>Property Names</th>
<th>Values</th>
</tr>
</thead>
<tbody>
<tr>
<td>a</td>
<td>1</td>
</tr>
<tr>
<td>b</td>
<td>2</td>
</tr>
<tr>
<td>c</td>
<td>3</td>
</tr>
</tbody>
</table>
</body>
So everything seems to be working from the console but when I try to access localhost:port/request, I go to the 404 error instead of a page that displays the tables.
Can anyone tell me what I'm doing wrong? Thank you all for your time.

Related

unable to display data using fetch API - node.js

So, I am getting the below error,
inspected via google chrome
What I am trying to achieve is to explore the Fetch Api by retrieving some data via userApi.js file which pulls it from a srcServer.js (I have hardcoded some data here). I am using webpack bundle and index is the entry point of my project. I have created index.html to bind the data via innerhtml.
Earlier I was using import 'isomorphic-fetch' in my userApi.js file but that too didn't help and hence I found some suggestions on google to use isomorphic-fetch, node-fetch etc. nothing of that sort worked.
I have added most of the artifacts below can you please guide me what is that I am missing here.
Project Structure
userApi.js
import 'isomorphic-fetch'
import 'es6-promise'
export function getUsers () {
return get('users')
}
function get (url) {
return fetch(url).then(onSuccess, onError) //eslint-disable-line
}
function onSuccess (response) {
return response.json()
}
function onError (error) {
console.log(error)
}
index.js
/* eslint-disable */ // --> OFF
import './index.css'
import {getUsers} from './api/userApi'
// Populate table of users via API call.
getUsers().then(result => {
let usersBody = ''
result.forEach(element => {
usersBody+= `<tr>
<td><a href='#' data-id='${user.id}' class='deleteUser'>Delete</a></td>
<td>${user.id}</td>
<td>${user.firstName}</td>
<td>${user.lastName}</td>
</tr>` //eslint-disable-line
})
global.document.getElementById('users').innerHTML = usersBody
})
index.html
<!DOCTYPE <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h1>Users</h1>
<table>
<thead>
<th> </th>
<th>Id</th>
<th>First Name</th>
<th>Last Name</th>
</thead>
<tbody id="users">
</tbody>
</table>
<script src="bundle.js"></script>
</body>
</html>
srcServer.js
// sample api call data
app.get('/users', function (req, res) {
// Hard coded for simplicity
res.json([
{ 'id': 1, 'firstName': 'P', 'lastName': 'K' },
{ 'id': 2, 'firstName': 'M', 'lastName': 'K' },
{ 'id': 3, 'firstName': 'S', 'lastName': 'K' }
])
})
The error is giving you the exact reason, i.e. user is not defined. Have you tried to print console.log(element); in your forEach loop? You will see what you need to change.
You are accessing the user information incorrectly. In your forEach loop, each value is represented as element not user
result.forEach(element => {
usersBody+= `<tr>
<td><a href='#' data-id='${element.id}' class='deleteUser'>Delete</a></td>
<td>${element.id}</td>
<td>${element.firstName}</td>
<td>${element.lastName}</td>
</tr>` //eslint-disable-line
})

Multiple mongoDB queries in one router.get method nodejs

I would like to have multiple queries in a single router method as follows in my index.js file,
router.get('/users', function(req, res) {
var db = req.db;
var users = db.get('users');
var col_name=req.query.colname;
var col_value=req.query.colvalue;
var query={};
query[col_name]=col_value;
console.log(col_name);
console.log(col_value);
console.log(query);
//using this i would like to populate my dropdown list
users.distinct('symbol',{limit: 10000},function(e, syms){
res.send('users', {
title: 'usersSym',
'usersSym': syms
});
});
// using this I would populate a table in html
users.find(query,{limit: 10000},function(e, docs){
res.render('users', {
title: 'Users',
'users': docs
});
});
});
And in my .ejs file I'm trying to do the following :
<html>
<head>
//drop down list populating with first query
<select id="selected" name="colvalue" >
<option value="">--Select--</option>
<% usersSym.forEach(function(usersym) { %>
<option value="<%= usersym.symbol %>"><%= usersym.symbol %></option>
<% }); %>
</select>
//Table populating with second query
<table >
<tr >
<th>Symbol</th>
<th>Order_id</th>
</tr>
<tr>
<% users.forEach(function(user) { %>
<td ><%= user.symbol %></td>
<td><%= user.order_id %></td>
</tr>
<% }); %>
</table>
</body>
</head>
</html>
But no luck. Wondering whether I'm going in right direction or not. If not please guide me in right way.
// 1st fetch symbol
users.distinct('symbol',{limit: 10000},function(e, syms){
// 2nd fetch [users]
users.find(query,{limit: 10000},function(e, docs){
res.render('users',
{
usersSym: syms,
users: docs
}
);
});
});
// P.S. do not forget to check on error on each callback
You can only send data back to the client once. One way would be to do all those DB queries in a sequence, and then send all the data. Another might be to do it your way, check the status of all DB queries, and if all are done, then send the data.

MVC 5 get value of DropDownList within a table row

I have a view with a table of products that can be added to a shopping cart. Each row has a DropDownList with allowed quantities that can be ordered along with a button to add to cart. Everything is populating and displaying properly. I know how to pass the item ID in the ActionLink but how can I get the value of the DownDownList associated with the table row of the ActionLink that was clicked?
I am guessing possibly using JQuery that fires when the ActionLink is clicked?
I also thought of making every row a form but that seems overkill.
Is there an easy MVC way to do this?
In prepping more info for a proper question and went ahead and solved it. Thank you Stephen for the nudge and info.
I tried putting a Html.BeginForm around each <tr> tag in the details section. This did indeed work for me. I was able to easily get the unique form info to POST for each individual row. However, when I would enable JQuery DataTables the submit would break. DataTables must be capturing the submit or click somehow. Haven't figured that out but it made me try JQuery which seems a much better way to do it.
Here is how I construct the table data row:
#foreach (var item in Model)
{
<tr>
<td>
<img src="#item.GetFrontImage()" width="100" />
</td>
<td>
<strong>#Html.DisplayFor(modelItem => item.DisplayName)</strong>
</td>
<td>
#Html.DisplayFor(modelItem => item.CustomerSKU)
</td>
<td>
#Html.DropDownList("OrderQty", item.GetAllowedOrderQuantities(), htmlAttributes: new { #class = "form-control" })
</td>
<td>
<a class="btn btn-default pull-right" data-id="#item.ID">Add to Cart</a>
</td>
</tr>
}
This creates a select with id of OrderQty and I embedded the item ID in data-id attribute of the link. I then used this JQuery to capture the info and POST it to my controller. Just have a test div displaying the results in this example:
// Add to Cart click
$('table .btn').click(function () {
// Gather data for post
var dataAddToCard = {
ID: $(this).data('id'), // Get data-id attribute (Item ID)
Quantity: $(this).parent().parent().find('select').val() // Get selected value of dropdown in same row as button that was clicked
}
// POST data to controller
$.ajax({
url: '#Url.Action("AddToCart","Shopping")',
type: 'POST',
data: JSON.stringify(dataAddToCard),
contentType: 'application/json',
success: function (data) { $('#Result').html(data.ID + ' ' + data.Quantity); }
})
});
The JQuery function receives the reference to the link being clicked so I can extract the Item ID from the data-id attribute. I can then get a reference to the dropdown (select) that is in the same row by using .parent.parent (gets me to the <tr> tag) and then just finding the next 'select' tag. Probably pretty obvious to a lot of you.
This works great for my purposes. I can also update other elements with data returned from the POST.
Thank you
Karl
for the table in html:
<div class="table-responsive">
<table id="employeeTable"class="table table-bordered">
<thead>
<tr>
<th class="text-center">ُُُEmpId</th>
<th class="text-center">Name</th>
<th class="text-center">Absense State</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>#item.Id</td>
<td>#item.Name</td>
<td class="text-center">#Html.DropDownList("DDL_AbsentStatus", new SelectList(ViewBag.statusList, "Id", "Name"), new { #class = "form-control text-center" })</td>
</tr>
}
</tbody>
</table>
</div>
in javascript to get the selected value:
//Collect Date For Pass To Controller
$("#btn_save").click(function (e) {
e.preventDefault();
if ($.trim($("#datepicker1").val()) == "") {
alert("ادخل تاريخ يوم صحيح!")
return;
}
var employeesArr = [];
employeesArr.length = 0;
$.each($("#employeeTable tbody tr"), function () {
employeesArr.push({
EmpId: $(this).find('td:eq(0)').html(),
EntryDate: $.trim($("#datepicker1").val()),
StatusId: $(this).find('#DDL_AbsentStatus').val()
});
});
$.ajax({
url: '/Home/SaveAbsentState',
type: "POST",
dataType: "json",
data: JSON.stringify(employeesArr),
contentType: 'application/json; charset=utf-8',
success: function (result) {
alert(result);
emptyItems();
},
error: function (err) {
alert(err.statusText);
}
});
})

Using Ember Data to load data async from node sever

My Model :
App.Contacts = DS.Model.extend({
name : DS.attr('string'),
number : DS.attr('number')
});
This is how i save a record :
App.AddController = Ember.Controller.extend({
actions : {
addContact : function(){
var post = this.store.createRecord('Contacts',{
name : this.get('name') ,
number : this.get('number')
});
post.save();
}
}
});
Acc to Ember's offical guide, this would send a POST request to /Contacts , so to handle it, i used this in nodejs/expressjs
app.post('/contacts',function(req,res){
posts.push( req.body);
console.log(posts);
res.send({status: 'OK'});
});
Now i wish to retrieve it, into another template called all so i used :
App.AllRoute = Ember.Route.extend({
model : function(){
return this.store.find('Contacts');
},
setupController : function(controller,model){
controller.set('contactList',model);
}
});
Acc to Emberjs guides, model hook supports promises out-of-the-box . so i assumed this should work.
My template :
<script type="text/x-handlebars" id="all" >
Hello
<table>
{{#each contact in contactList}}
<tr>
<td>{{contact.name}} </td>
<td>{{contact.number}} </td>
</tr>
{{else}}
<tr><td>No contacts yet </td> </tr>
{{/each}}
</table>
</script>
Question
But the model returns nothing, i understand that this.store.find('Contacts') doesn't return a javascript array, but essentially and object , implimenting Ember.Enumerable
But on the server side, the posts is an javascript array, therefore there might be an type mismatch between then. how to resolve this?
EDIT:
To avoid any confusions in client side Ember code , This works properly, so there is some problem with the round trip to server.
App.AllRoute = Ember.Route.extend({
model : function(){
return this.store.all('Contacts');
},
setupController : function(controller,model){
controller.set('contactList',model);
}
});
If you could provide a jsfiddle, it be nice. I'm not sure whether contactList is defined or not and whether the alias for that controller is actually defined. So based on what I see, I think the problem is you're iterating over a controller that does not have the model properly defined.
I'd suggest trying to do:
{{#each}}
<tr>
<td>{{contact.name}} </td>
<td>{{contact.number}} </td>
</tr>
{{else}}
<tr><td>No contacts yet </td> </tr>
{{/each}}
If you really want to use the contactList controller, then you need to make sure that the App.AllController "needs" the contactListController.
App.ContactListController = Ember.ArrayController.extend({}) // needs to be an array controller
App.AddController = Ember.ArrayController.extend({
needs: ["contactList"], // controller's used within this controller
contactList: Ember.computed.alias("controllers.contactList"), // needed to iterate over the model how you're doing it.
Both of these solutions should work assuming your data is actually loaded in Ember Data. You might want to check the "data" tab on the ember-data console. If you don't have that browser extension installed, do it. It's incredibly useful.
If all else fails, try logging to verify expected values using {{log contactList}}
Good luck

parsing strange html with node.js

I am trying parse a site, but the html is a mess. Can anyone with more experience in parsing sites help me?
<tr>
<td><font FACE=Tahoma color='#CC0000' size=2><b>Date</b></font></td>
<td><font FACE=Tahoma color='#CC0000' size=2><b>Place</b></font></td>
<td><font FACE=Tahoma color='#CC0000' size=2><b>Situation</b></font></td>
</tr>
<tr><td rowspan=2>16/09/2011 10:11</td><td>New York</td><td><FONT COLOR="000000">Situation Red</font></td></tr>
<tr><td colspan=2>Optional comment hello new york</td></tr>
<tr><td rowspan=2>16/09/2011 10:08</td><td>Texas</td><td><FONT COLOR="000000">Situation Green</font></td></tr>
<tr><td colspan=2>Optional comment hello texas </td></tr>
<tr><td rowspan=1>06/09/2011 13:14</td><td>California</td><td><FONT COLOR="000000">Yellow Situation</font></td></tr>
</TABLE>
A strange and crazy thing is the comment not in the head of table also the start point(california) dont have comment. So, start point always will be like this:
Date: 06/09/2011 13:14
Place: California
Situation: Yellow Situation
Comment: null
all others places have a comment and will be like this:
Date: 16/09/2011 10:11
Place: New York
Situation: Situation Red
Comment: Optional comment hello new york.
I have tried some approaches, but I don't have much experience with node.js and less with HTML parsing. I need a getting started with parsing crazy stuff.
I built a distributed scraper in node.js. I found it easier to parse html that had been parsed through html tidy.
Here is a module to run html through tidy:
var spawn = require('child_process').spawn;
var fs = require('fs');
var tidy = (function() {
this.html = function(str, callback) {
var buffer = '';
var error = '';
if (!callback) {
throw new Error('No callback provided for tidy.html');
}
var ptidy = spawn(
'tidy',
[
'--quiet',
'y',
'--force-output',
'y',
'--bare',
'y',
'--break-before-br',
'y',
'--hide-comments',
'y',
'--output-xhtml',
'y',
'--fix-uri',
'y',
'--wrap',
'0'
]);
ptidy.stdout.on('data', function (data) {
buffer += data;
});
ptidy.stderr.on('data', function (data) {
error += data;
});
ptidy.on('exit', function (code) {
//fs.writeFileSync('last_tidy.html', buffer, 'binary');
callback(buffer);
});
ptidy.stdin.write(str);
ptidy.stdin.end();
}
return this;
})();
module.exports = tidy;
Example (if saved as tidy.js):
require('./tidy.js');
tidy.html('<table><tr><td>badly formatted html</tr>', function(html) { console.log(html); });
Result:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="generator" content="HTML Tidy for Linux/x86 (vers 25 March 2009), see www.w3.org" />
<title></title>
</head>
<body>
<table>
<tr>
<td>badly formatted html</td>
</tr>
</table>
</body>
</html>

Resources