Problem with express-handlebars section helpers - javascript

I can't make the section helper work as intended. The body of login.hbs was parsed normally, but the js section was never parsed. I have tried using helpers inside res.render() and put section() straight into engine() and it didn't work either
app.js
import express from "express"
import expressHbs from "express-handlebars"
const app = express();
app.use(express.urlencoded({ extended:true }));
app.engine('hbs', expressHbs.engine({
defaultLayout: 'main.hbs',
helpers: {
section(name, options) {
if (!this._sections)
this._sections = {};
this._sections[name] = options.fn(this);
return null;
},
},
}));
app.set('view engine','hbs');
app.set('views','./view');
app.get("/", (req, res) => {
res.render("login");
})
app.listen(3000, () => console.log("listening"));
main.hbs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
{{{body}}}
{{{_section.js}}}
</body>
</html>
login.hbs
<h1>Hello</h1>
{{#section "js"}}
<script>
console.log("hello world")
</script>
{{/section}}
Edit
I can't embed HTML either
login.hbs
<h1>Hello</h1>
{{#section "js"}}
<p>a paragraph</p>
{{/section}}

I tried to run it. The real reason why it is not rendering is because inside your main.hbs you need to have {{{_sections.js}}} inside the html body tags instead of just {{{_section.js}}} like you have it now. The script tag should run as well.
Sorry for the confusion with the previous answer.

Related

Cannot post back calculation to server

The problem showing up when I click the button submit.The error coming out 404 not found and "Cannot POST/Index" in the website. Am I have logical problems on the code or problem that occur on the syntax. My program is doing without any http request, it's just a normal import express engine and integrate with html which I'm trying to do a basic post back function to express(server) and post the answer back to my angular html.
I'm trying to post the number back to the server for the calculation and doesn't know where is the error that make me could not doing Post Function. Please get the requirement file from me if the file that I uploaded is not completed.
app.component.html
In my HTML file do I need to add somethings for link the server.ts? Is there still any issue that I have to check on it?
<!doctype html>
<html lang="en">
<head>
<Title>Calculator</Title>
<meta charset="utf-8">
<title>Myapp</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />
</head>
<body>
<h1 align="center">Angular Calculator</h1>
<div class="container">
<div class="card">
<div class="card-body">
<form action="index" method="POST">
<input type="number" name="num1" class="form-control" placeholder="Number">
<input type="number" name="num2" class="form-control" placeholder="Number">
<select ng-model="operator" name="operator">
<option>+</option>
<option>*</option>
<option>-</option>
<option>/</option>
</select>
<button type="submit">Submit</button>
</form>
<p>Calculation Of the number is :{{ result }} </p>
</div>
</div>
</div>
</body>
</html>
server.ts file
This is the by default server file that generate by npm which I'm not sure the syntax of code any problems for my first testing of addition functions.
import 'zone.js/dist/zone-node';
import 'reflect-metadata';
import * as bodyParser from 'body-parser';
import * as express from 'express';
import {join} from 'path';
// Express server
const app = express();
const PORT = process.env.PORT || 4000;
const DIST_FOLDER = join(process.cwd(), 'dist/browser');
// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const {AppServerModuleNgFactory, LAZY_MODULE_MAP, ngExpressEngine, provideModuleMap} = require('./dist/server/main');
// Our Universal express-engine (found # https://github.com/angular/universal/tree/master/modules/express-engine)
app.engine('html', ngExpressEngine({
bootstrap: AppServerModuleNgFactory,
providers: [
provideModuleMap(LAZY_MODULE_MAP)
]
}));
app.set('view engine', 'html');
app.set('views', DIST_FOLDER);
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// Example Express Rest API endpoints
// app.get('/api/**', (req, res) => { });
// Serve static files from /browser
app.get('*.*', express.static(DIST_FOLDER, {
maxAge: '1y'
}));
// All regular routes use the Universal engine
app.get('*', (req, res) => {
res.render('/app.component.html', { req });
});
app.get('*', (req, res) => {
res.status(404).send('data requests are not supported');
});
//have body-parser is a piece of express middleware that reads a form's
//input and stores it as a javascript object accessible through
//can not to include body-parser but not to get the raw request, your body and header are not in the root object of request parameter
app.post('/',(req, res) => {
//var num1 = req.body.operator
var result=req.body;
console.log(req.body);
var operator = req.body.operator
if (operator == "+")
{
res.render('/app.component.html', {
result: parseInt(req.body.num1) + parseInt(req.body.num2),
});
}
})
// Start up the Node server
app.listen(PORT, () => {
console.log(`Node Express server listening on http://localhost:${PORT}`);
});
The following line implies you are posting to /index:
<form action="index" method="POST">
For posting to your express service (which is hosted on port 4000 and hence the URL is http://localhost:4000), you have to define a submit behavior on your button. Check this for reference.
I think the problem is you don't include
'angular-route.js'
in your client-side code
you can't post to index <form action="index" method="POST">.
you need a server side file. like: <form action="form_process.php" method="POST">

What is the simplest way to link between .hbs files using handlebars?

I am a complete beginner to handlebars and am trying to modify the simple handlebars template taken from the example on glitch.com
I would like to be able to link between .hbs files as I would link between .html files but when I try however I am given the message cannot GET followed by whatever file I give to it.
Here is a grab of my overall structure for ref;
Here is the index.hbs files I am working with
<!DOCTYPE html>
<html>
{{> head }}
<body>
Link to second page
</body>
</html>
Which I would like to link to (for example) this secondpage.hbs file;
<!DOCTYPE html>
<html>
{{> head }}
<body>
Link back to index
</body>
</html>
Here is the code in my server.js file
// Generic node.js express init:
const express = require('express');
const app = express();
app.use(express.static('public'));
const hbs = require('hbs');
hbs.registerPartials(__dirname + '/views/partials/');
app.set('view engine', 'hbs');
app.set('views', __dirname + '/views');
app.get("/", (request, response) => {
let dt = new Date();
let data = {
projectName: process.env.PROJECT_DOMAIN,
luckyNumber: Math.floor(Math.random()*1000),
serverTime: new Date(),
ip: (request.headers["x-forwarded-for"]||"").split(",")[0]
};
data.json = JSON.stringify(data, null, 2);
response.render('index', data);
});
let listener = app.listen(process.env.PORT, () => {
console.log('Your app is listening on port ' + listener.address().port);
});
and the code in my watch.json
{
"install": {
"include": [
"^package\\.json$",
"^\\.env$"
]
},
"restart": {
"exclude": [
"^public/",
"^dist/"
],
"include": [
"\\.js$",
"\\.hbs$",
"\\.json"
]
},
"throttle": 100
}
If any of the details of the other files is necessary to assist let me know and I can provide.
I appreciate I am probably thinking about this in the wrong way, I have looked at handlebars in more detail and experimented with helpers etc. but it seems overly complicated for what I am trying to achieve, I thought you could write basic html within an hbs file? I am looking for the most straightforward, generic solution to the problem of linking between views in handlebars.
FWIW I want to use handlebars in a pretty simple fashion, basically just looking to have the equivalent of php includes using partials instead, so if there is a better way to approach the creation of the app with that in mind I would be grateful for advice.
Your code looks alright. What is the problem exactly? When you add {{> head}} partial to the index.hbs doesn't it render properly?
EDIT:
Okay, you have mainly 2 problems with your code:
You have no route defined on express linking to your /secondpage endpoint.
You are trying to link to a file Link instead of linking to an URL endpoint Link.
To fix your code you would have to define the endpoint linking to the handlebars file, so you need to change your server.js file to something like this.
const express = require('express');
const hbs = require('hbs');
const app = express();
app.use(express.static('public'));
app.set('view engine', 'hbs');
app.set('views', __dirname + '/views');
hbs.registerPartials(__dirname + '/views/partials/');
// 1st Page Route (URL Endpoint)
app.get('/', (request, response) => {
const data = {
projectName: process.env.PROJECT_DOMAIN,
luckyNumber: Math.floor(Math.random() * 1000),
serverTime: new Date(),
ip: (request.headers['x-forwarded-for'] || '').split(',')[0],
};
data.json = JSON.stringify(data, null, 2);
response.render('index', data);
});
// 2nd Page Route (URL Endpoint)
app.get('/secondpage', (request, response) => {
response.render('secondpage');
});
const listener = app.listen(process.env.PORT, () => {
console.log('Your app is listening on port ' + listener.address().port);
});
And then you need to fix your HTML links to this on index.hbs:
<!DOCTYPE html>
<html>
{{> head }}
<body>
Link to second page
</body>
</html>
And this on secondpage.hbs:
<!DOCTYPE html>
<html>
{{> head }}
<body>
Link back to index
</body>
</html>
Hope this helps you.
Instead of using handlebars I used express-handlebars
Terminal: npm i express-handlebars
Handlebars is a Middleware and functions as a Twig (Template Engine) so for your server I'd suggest:
// Generic node.js express init:
const express = require('express');
const app = express();
app.use(express.static('public'));
const exphbs = require('express-handlebars');
app.set('views', __dirname + '/views');
// added this part
app.engine('.hbs', exphbs ({
defaultLayout: 'main',
layoutsDir: ('views', __dirname + 'layouts'),
partialsDir: ('views', __dirname 'partials'),
extname: '.hbs'
}));
app.set('view engine', 'hbs')
app.get("/", (request, response) => {
let dt = new Date();
let data = {
projectName: process.env.PROJECT_DOMAIN,
luckyNumber: Math.floor(Math.random()*1000),
serverTime: new Date(),
ip: (request.headers["x-forwarded-for"]||"").split(",")[0]
};
data.json = JSON.stringify(data, null, 2);
response.render('index', data);
});
let listener = app.listen(process.env.PORT, () => {
console.log('Your app is listening on port ' + listener.address().port);
});
By doing this, you should have a file in your layouts folder named main.hbs where you will have that dynamic approach you're looking for. Something that stays the same for all pages. I will insert here a suggestion, feel free to adapt for your code.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- CUSTOM CSS -->
<link rel="stylesheet" href="/css/main.css">
</head>
<body>
{{> navigation }}
<main class="container p-5">
{{{ body }}}
</main>
</body>
</html>
Now when you create a navigation.hbs in your partials folder you will have the same frontend in all pages in the navigation. This is because we defined in the server.js our default template to be main.hbs. Whilst for your body, the triple hash ({{{}}}) inserts the components of the other .hbs files that you define. Don't forget to create a index.hbs file inside the views folder.
I learned the basics of hbs by following this tutorial (Note it's in Spanish). The tutorial produces this open-source project (which I am including in case it is useful).

EJS CSS Not loading front end

So i set the middleware and static folder for the .css file, but when i attempt to use it and load it in the EJS file i receive an error in the chrome debugger saying under "network" that it was cancelled.
app.js
// view engine
exapp.set('view engine', 'ejs');
exapp.set('views', path.join(__dirname, 'views'));
console.log('Static location: ' + path.join(__dirname, 'views'));
// body parser
exapp.use(bodyParser.json());
exapp.use(bodyParser.urlencoded({extended: false}));
// set static path
exapp.use(express.static(path.join(__dirname, 'public')));
console.log('Static location: ' + path.join(__dirname, 'public'));
exapp.use(express.static(path.join(__dirname, 'public/css')));
console.log('Static location: ' + path.join(__dirname, 'public/css'));
// get requests
exapp.get('/', function(request, response){
response.render('index');
})
exapp.get('/about', function(request, response){
response.render('about');
})
header.ejs
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Unicorn</title>
<link rel="stylesheet" href="/public/css/main.css" type="text/css" media="screen" charset="utf-8">
</head>
<body>
Picture of what i found in the chrome debugging thing
Fixed it
For some unknown reason i need to add '/public/css' as the first parameter to the use() function
Original
exapp.use(express.static(path.join(__dirname, 'public/css')));
Fixed
exapp.use('/public/css', express.static(path.join(__dirname, 'public/css')));
Hope this helps others :)

Polymer novice, how to get require statement

I'm having trouble starting with polymer. The purpose is (simple) ; an Express server that serve my index.html and the index.html that serve my polymer element.
And my first problem is : How do I use node_moduldes and the require statement inside of my polymer element. I think I found some leads, like Browserify or RequireJS, but it seems complicated. (And browserify didnt work..).
Could someone provide me a simple way to use the node_modules in this polymer element ?
I'll start with my project structure.
And the file :
public/index.html :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="import" href="./bower_components/webcomponentsjs/webcomponents-lite.js">
<link rel="import" href="./elements/neito-photoresistor.html">
<title>Neito's Domotics</title>
</head>
<styl></style>
<body>
<neito-photoresistor></neito-photoresistor>
</body>
</html>
server/app.js
"use strict"
//require
var express = require('express'),
path = require('path');
//Conf const
const _port = 3000;
//Server
var app = express();
//Middleware
app.use(express.static(path.join(__dirname, '/..', 'public')));
//Routing
app.get('/', function (req, res){
res.sendFile('../public/index.html', {root: __dirname});
})
.listen(_port, function (){
console.log('Server listening on : '+_port);
});
and the polymer element him self (I know it is complete bullshit but still the require problem is here): public/elements/neito-resistor.html :
<!DOCTYPE html>
<link rel="import" href="./../bower_components/polymer/polymer.html">
<!-- I know I cannot use the script src="" tag to import my node_modules -->
<dom-module id="neito-photoresistor">
<template>
<style>
</style>
<span>Ambient luminosity = <span>{{lum_pct}}</span> %</span>
</template>
<script>
Polymer({
is: 'neito-photoresistor',
ready: function() {
var mcp = require('mcp3008.js'),//I know that this line cause problem
can = new mcp();
},
properties: {
lum_pct: {
type: Number,
notify: true,
reflectToAttribute: true,
observer: '_getValueLumPct'
}
},
_getValueLumPct()
{
lum_pct = can.poll(0, 1000, function(value){
console.log('Luminosite ambiante = '+(100-((value/1024)*100))+' % ('+value+')');
return 100-((value/1024)*100);
});
}
});
</script>
</dom-module>

Why am I getting this Angular-Mock error and Mocha test is not running

I'm getting the exact error as found here: (window.beforeEach || window.setup) is not a function. However the fix did not work, the author of the tutorial series here even mentioned the same fix.
Here is the Tuts+ author's fix:
Which is simply to place the angular-mock script tag after the Mochai and Chai scripts. Which I did so below:
test/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Mocha Spec Runner</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="icon" href="../app/favicon.ico">
<link rel="apple-touch-icon" href="../app/assets/imgs/apple-touch-icon.png">
<link href="bower_components/mocha/mocha.css" rel="stylesheet">
</head>
<body>
<div id="mocha"></div>
<script src="../bower_components/angular/angular.js"></script>
<script src="../bower_components/mocha/mocha.js"></script>
<script src="../bower_components/chai/chai.js"></script>
<!-- see Angular-mocks is here :( -->
<script src="../bower_components/angular-mocks/angular-mocks.js"></script>
<script>
mocha.setup('bdd');
</script>
<script src="main.spec.js"></script>
<script>
mocha.run();
</script>
</body>
</html>
My main.spec.js file
/**
* #name Mocha Test Runner
* #desc Describes and runs our dashboard tests
*/
var assert = chai.assert;
var expect = chai.expect;
// This Test is designed to fail on purpose
describe('User Login', function() {
console.log('User Login');
describe('Login Failed', function() {
console.log('Login Failed');
if ('Incorrect login should fail', function() {
module('loginController')
inject(function($injector) {
apiFactory = $injector.get('ApiFactory');
});
expect(apiFactory).to.be.an('number');
});
});
});
My Gulp tasks
gulp.task('serve', function() {
return browserSync.init({
notify : false,
port : 3333,
server: {
baseDir: ['app'],
routes: {
'/bower_components' : 'bower_components'
}
}
});
});
gulp.task('serve-test', function() {
browserSync.init({
notify : false,
port : 4444,
server: {
baseDir: ['test', 'app'],
routes: {
'/bower_components' : 'bower_components'
}
}
});
});
In your index.html file, you include the angular-mocks.js script before the call to mocha.setup('bdd'). angular-mocks.js is implemented as an immediately-invoked function expression which attempts to use window.beforeEach. (https://github.com/angular/bower-angular-mocks/blob/master/angular-mocks.js#L2586)
However, mocha.js is not immediately invoked and has to be initialized with the mocha.setup function in order to add its magic to the runtime environment.
Try reversing the order of these script tags, so that mocha.js is included and initialized before angular-mocks.js.
<script src='bower_components/mocha/mocha.js'></script>
<script src='bower_components/chai/chai.js'></script>
<script>
mocha.setup('bdd');
</script>
<script src="bower_components/angular-mocks/angular-mocks.js"></script>

Categories