Using JS Handlebars to render different child objects
I have an app that returns an HTML file (handlebars compiled template) with different Shape
objects. Each Shape
is displayed differently. I have a Shape
parent class with inheriting children classes Circle
, Triangle
, and Rectangle
Shape.js
function Shape(id, name, color) {
this.id = id;
this.name = name;
this.color = color;
};
Shape.prototype.getDisplayName = function() {
return this.id + ":" + this.name;
}
module.exports = Shape;
Circle.js
const Shape = require('./shape');
Circle.prototype = Object.create(Shape.prototype);
Circle.prototype.constructor = Circle;
function Circle(id, name, color, radius) {
Shape.call(this, id, name, color);
this.radius = radius;
};
module.exports = Circle;
Triangle.js
const Shape = require('./shape');
Triangle.prototype = Object.create(Shape.prototype);
Triangle.prototype.constructor = Triangle;
function Triangle(id, name, color, angles, lengths) {
Shape.call(this, id, name, color);
this.angles = angles;
this.lengths = lengths;
};
module.exports = Triangle;
Rectangle.js
const Shape = require('./shape');
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;
function Rectangle(id, name, color, width, height) {
Shape.call(this, id, name, color);
this.width = width;
this.height = height;
};
module.exports = Rectangle;
An array of these Shapes are sent to the handlebars template to be compiled and rendered. Each shape has a corresponding Handlebars Partial
. Using a Dynamic Partial
, I determine which partial to render.
app.js (entry point)
const express = require('express')
const fs = require('fs');
const app = express();
const port = 8080;
const Circle = require('./circle');
const Triangle = require('./triangle');
const Rectangle = require('./rectangle');
const handlebars = require('hbs');
handlebars.registerPartials(__dirname + "/public/partials");
handlebars.registerHelper('shape', (shape) => {
if(shape instanceof Circle){
return "circle";
} else if(shape instanceof Triangle){
return "triangle";
} else if(shape instanceof Rectangle){
return "rectangle";
} else {
throw new Error(shape + " is not a valid shape");
}
});
app.get('/', async (req, res) => {
let circle1 = new Circle('id1', 'Circle', 'red', 5);
let triangle1 = new Triangle('id2', 'Triangle', 'pink', [120,30,30], [40,10,10])
let circle2 = new Circle('id3', 'Circle', 'blue', 12);
let rectangle1 = new Rectangle('id4', 'Rectangle', 'green', 210, 100);
let shapes = [circle1, triangle1, circle2, rectangle1];
let file = await loadFile('./public/index.hbs');
let template = handlebars.compile(file, { strict: true, noEscape: true });
let html = template({'shapes': shapes});
res.send(html);
});
var loadFile = function(filePath){
return new Promise(function(resolve, reject) {
fs.readFile(filePath, 'utf-8', (err, data) => {
if (err){
return reject('Error reading handlebar files: ' + err.message);
}
resolve(data);
});
});
};
app.listen(port, () => console.log(`listening on port ${port}!`))
index.hbs
<!doctype html>
<html>
<head>
</head>
<body>
{{#each shapes}}
{{> (shape this) }}
{{/each}}
</body>
</html>
circle.hbs
<div class="circle">
I am a circle, {{getDisplayName}}.
Radius: {{radius}}
</div>
rectangle.hbs
<div class="rectangle">
I am a rectangle, {{getDisplayName}}.
Height: {{height}}
Width: {{width}}
</div>
triangle.hbs
<div class="triangle">
I am a triangle, {{getDisplayName}}.
Angles: {{angles}}
Lengths: {{lengths}}
</div>
This is a small app from work. It's not technically Shapes, but I thought replacing the current business logic with Shapes would be easier than diving into all of that. The app currently has no children objects and instead has only one object that is too much of a "God" object with some properties null depending on what type of object it is representing. This is requiring quite a bit of view logic and is too difficult to refactor. Every time a change is required, it's a bit of a headache.
What I want out of the code review
It would be beneficial to me if you could review my handlebars design. I know the .hbs
files could be improved and that the index
route is a little weird. But that is all just to tie this app together. Is my Helper
a good way of solving this problem? Note: All of the Shapes need to be passed in one Shape array. I can't pass an array of Circles, an array of Triangles, etc.
javascript node.js
add a comment |
I have an app that returns an HTML file (handlebars compiled template) with different Shape
objects. Each Shape
is displayed differently. I have a Shape
parent class with inheriting children classes Circle
, Triangle
, and Rectangle
Shape.js
function Shape(id, name, color) {
this.id = id;
this.name = name;
this.color = color;
};
Shape.prototype.getDisplayName = function() {
return this.id + ":" + this.name;
}
module.exports = Shape;
Circle.js
const Shape = require('./shape');
Circle.prototype = Object.create(Shape.prototype);
Circle.prototype.constructor = Circle;
function Circle(id, name, color, radius) {
Shape.call(this, id, name, color);
this.radius = radius;
};
module.exports = Circle;
Triangle.js
const Shape = require('./shape');
Triangle.prototype = Object.create(Shape.prototype);
Triangle.prototype.constructor = Triangle;
function Triangle(id, name, color, angles, lengths) {
Shape.call(this, id, name, color);
this.angles = angles;
this.lengths = lengths;
};
module.exports = Triangle;
Rectangle.js
const Shape = require('./shape');
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;
function Rectangle(id, name, color, width, height) {
Shape.call(this, id, name, color);
this.width = width;
this.height = height;
};
module.exports = Rectangle;
An array of these Shapes are sent to the handlebars template to be compiled and rendered. Each shape has a corresponding Handlebars Partial
. Using a Dynamic Partial
, I determine which partial to render.
app.js (entry point)
const express = require('express')
const fs = require('fs');
const app = express();
const port = 8080;
const Circle = require('./circle');
const Triangle = require('./triangle');
const Rectangle = require('./rectangle');
const handlebars = require('hbs');
handlebars.registerPartials(__dirname + "/public/partials");
handlebars.registerHelper('shape', (shape) => {
if(shape instanceof Circle){
return "circle";
} else if(shape instanceof Triangle){
return "triangle";
} else if(shape instanceof Rectangle){
return "rectangle";
} else {
throw new Error(shape + " is not a valid shape");
}
});
app.get('/', async (req, res) => {
let circle1 = new Circle('id1', 'Circle', 'red', 5);
let triangle1 = new Triangle('id2', 'Triangle', 'pink', [120,30,30], [40,10,10])
let circle2 = new Circle('id3', 'Circle', 'blue', 12);
let rectangle1 = new Rectangle('id4', 'Rectangle', 'green', 210, 100);
let shapes = [circle1, triangle1, circle2, rectangle1];
let file = await loadFile('./public/index.hbs');
let template = handlebars.compile(file, { strict: true, noEscape: true });
let html = template({'shapes': shapes});
res.send(html);
});
var loadFile = function(filePath){
return new Promise(function(resolve, reject) {
fs.readFile(filePath, 'utf-8', (err, data) => {
if (err){
return reject('Error reading handlebar files: ' + err.message);
}
resolve(data);
});
});
};
app.listen(port, () => console.log(`listening on port ${port}!`))
index.hbs
<!doctype html>
<html>
<head>
</head>
<body>
{{#each shapes}}
{{> (shape this) }}
{{/each}}
</body>
</html>
circle.hbs
<div class="circle">
I am a circle, {{getDisplayName}}.
Radius: {{radius}}
</div>
rectangle.hbs
<div class="rectangle">
I am a rectangle, {{getDisplayName}}.
Height: {{height}}
Width: {{width}}
</div>
triangle.hbs
<div class="triangle">
I am a triangle, {{getDisplayName}}.
Angles: {{angles}}
Lengths: {{lengths}}
</div>
This is a small app from work. It's not technically Shapes, but I thought replacing the current business logic with Shapes would be easier than diving into all of that. The app currently has no children objects and instead has only one object that is too much of a "God" object with some properties null depending on what type of object it is representing. This is requiring quite a bit of view logic and is too difficult to refactor. Every time a change is required, it's a bit of a headache.
What I want out of the code review
It would be beneficial to me if you could review my handlebars design. I know the .hbs
files could be improved and that the index
route is a little weird. But that is all just to tie this app together. Is my Helper
a good way of solving this problem? Note: All of the Shapes need to be passed in one Shape array. I can't pass an array of Circles, an array of Triangles, etc.
javascript node.js
add a comment |
I have an app that returns an HTML file (handlebars compiled template) with different Shape
objects. Each Shape
is displayed differently. I have a Shape
parent class with inheriting children classes Circle
, Triangle
, and Rectangle
Shape.js
function Shape(id, name, color) {
this.id = id;
this.name = name;
this.color = color;
};
Shape.prototype.getDisplayName = function() {
return this.id + ":" + this.name;
}
module.exports = Shape;
Circle.js
const Shape = require('./shape');
Circle.prototype = Object.create(Shape.prototype);
Circle.prototype.constructor = Circle;
function Circle(id, name, color, radius) {
Shape.call(this, id, name, color);
this.radius = radius;
};
module.exports = Circle;
Triangle.js
const Shape = require('./shape');
Triangle.prototype = Object.create(Shape.prototype);
Triangle.prototype.constructor = Triangle;
function Triangle(id, name, color, angles, lengths) {
Shape.call(this, id, name, color);
this.angles = angles;
this.lengths = lengths;
};
module.exports = Triangle;
Rectangle.js
const Shape = require('./shape');
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;
function Rectangle(id, name, color, width, height) {
Shape.call(this, id, name, color);
this.width = width;
this.height = height;
};
module.exports = Rectangle;
An array of these Shapes are sent to the handlebars template to be compiled and rendered. Each shape has a corresponding Handlebars Partial
. Using a Dynamic Partial
, I determine which partial to render.
app.js (entry point)
const express = require('express')
const fs = require('fs');
const app = express();
const port = 8080;
const Circle = require('./circle');
const Triangle = require('./triangle');
const Rectangle = require('./rectangle');
const handlebars = require('hbs');
handlebars.registerPartials(__dirname + "/public/partials");
handlebars.registerHelper('shape', (shape) => {
if(shape instanceof Circle){
return "circle";
} else if(shape instanceof Triangle){
return "triangle";
} else if(shape instanceof Rectangle){
return "rectangle";
} else {
throw new Error(shape + " is not a valid shape");
}
});
app.get('/', async (req, res) => {
let circle1 = new Circle('id1', 'Circle', 'red', 5);
let triangle1 = new Triangle('id2', 'Triangle', 'pink', [120,30,30], [40,10,10])
let circle2 = new Circle('id3', 'Circle', 'blue', 12);
let rectangle1 = new Rectangle('id4', 'Rectangle', 'green', 210, 100);
let shapes = [circle1, triangle1, circle2, rectangle1];
let file = await loadFile('./public/index.hbs');
let template = handlebars.compile(file, { strict: true, noEscape: true });
let html = template({'shapes': shapes});
res.send(html);
});
var loadFile = function(filePath){
return new Promise(function(resolve, reject) {
fs.readFile(filePath, 'utf-8', (err, data) => {
if (err){
return reject('Error reading handlebar files: ' + err.message);
}
resolve(data);
});
});
};
app.listen(port, () => console.log(`listening on port ${port}!`))
index.hbs
<!doctype html>
<html>
<head>
</head>
<body>
{{#each shapes}}
{{> (shape this) }}
{{/each}}
</body>
</html>
circle.hbs
<div class="circle">
I am a circle, {{getDisplayName}}.
Radius: {{radius}}
</div>
rectangle.hbs
<div class="rectangle">
I am a rectangle, {{getDisplayName}}.
Height: {{height}}
Width: {{width}}
</div>
triangle.hbs
<div class="triangle">
I am a triangle, {{getDisplayName}}.
Angles: {{angles}}
Lengths: {{lengths}}
</div>
This is a small app from work. It's not technically Shapes, but I thought replacing the current business logic with Shapes would be easier than diving into all of that. The app currently has no children objects and instead has only one object that is too much of a "God" object with some properties null depending on what type of object it is representing. This is requiring quite a bit of view logic and is too difficult to refactor. Every time a change is required, it's a bit of a headache.
What I want out of the code review
It would be beneficial to me if you could review my handlebars design. I know the .hbs
files could be improved and that the index
route is a little weird. But that is all just to tie this app together. Is my Helper
a good way of solving this problem? Note: All of the Shapes need to be passed in one Shape array. I can't pass an array of Circles, an array of Triangles, etc.
javascript node.js
I have an app that returns an HTML file (handlebars compiled template) with different Shape
objects. Each Shape
is displayed differently. I have a Shape
parent class with inheriting children classes Circle
, Triangle
, and Rectangle
Shape.js
function Shape(id, name, color) {
this.id = id;
this.name = name;
this.color = color;
};
Shape.prototype.getDisplayName = function() {
return this.id + ":" + this.name;
}
module.exports = Shape;
Circle.js
const Shape = require('./shape');
Circle.prototype = Object.create(Shape.prototype);
Circle.prototype.constructor = Circle;
function Circle(id, name, color, radius) {
Shape.call(this, id, name, color);
this.radius = radius;
};
module.exports = Circle;
Triangle.js
const Shape = require('./shape');
Triangle.prototype = Object.create(Shape.prototype);
Triangle.prototype.constructor = Triangle;
function Triangle(id, name, color, angles, lengths) {
Shape.call(this, id, name, color);
this.angles = angles;
this.lengths = lengths;
};
module.exports = Triangle;
Rectangle.js
const Shape = require('./shape');
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;
function Rectangle(id, name, color, width, height) {
Shape.call(this, id, name, color);
this.width = width;
this.height = height;
};
module.exports = Rectangle;
An array of these Shapes are sent to the handlebars template to be compiled and rendered. Each shape has a corresponding Handlebars Partial
. Using a Dynamic Partial
, I determine which partial to render.
app.js (entry point)
const express = require('express')
const fs = require('fs');
const app = express();
const port = 8080;
const Circle = require('./circle');
const Triangle = require('./triangle');
const Rectangle = require('./rectangle');
const handlebars = require('hbs');
handlebars.registerPartials(__dirname + "/public/partials");
handlebars.registerHelper('shape', (shape) => {
if(shape instanceof Circle){
return "circle";
} else if(shape instanceof Triangle){
return "triangle";
} else if(shape instanceof Rectangle){
return "rectangle";
} else {
throw new Error(shape + " is not a valid shape");
}
});
app.get('/', async (req, res) => {
let circle1 = new Circle('id1', 'Circle', 'red', 5);
let triangle1 = new Triangle('id2', 'Triangle', 'pink', [120,30,30], [40,10,10])
let circle2 = new Circle('id3', 'Circle', 'blue', 12);
let rectangle1 = new Rectangle('id4', 'Rectangle', 'green', 210, 100);
let shapes = [circle1, triangle1, circle2, rectangle1];
let file = await loadFile('./public/index.hbs');
let template = handlebars.compile(file, { strict: true, noEscape: true });
let html = template({'shapes': shapes});
res.send(html);
});
var loadFile = function(filePath){
return new Promise(function(resolve, reject) {
fs.readFile(filePath, 'utf-8', (err, data) => {
if (err){
return reject('Error reading handlebar files: ' + err.message);
}
resolve(data);
});
});
};
app.listen(port, () => console.log(`listening on port ${port}!`))
index.hbs
<!doctype html>
<html>
<head>
</head>
<body>
{{#each shapes}}
{{> (shape this) }}
{{/each}}
</body>
</html>
circle.hbs
<div class="circle">
I am a circle, {{getDisplayName}}.
Radius: {{radius}}
</div>
rectangle.hbs
<div class="rectangle">
I am a rectangle, {{getDisplayName}}.
Height: {{height}}
Width: {{width}}
</div>
triangle.hbs
<div class="triangle">
I am a triangle, {{getDisplayName}}.
Angles: {{angles}}
Lengths: {{lengths}}
</div>
This is a small app from work. It's not technically Shapes, but I thought replacing the current business logic with Shapes would be easier than diving into all of that. The app currently has no children objects and instead has only one object that is too much of a "God" object with some properties null depending on what type of object it is representing. This is requiring quite a bit of view logic and is too difficult to refactor. Every time a change is required, it's a bit of a headache.
What I want out of the code review
It would be beneficial to me if you could review my handlebars design. I know the .hbs
files could be improved and that the index
route is a little weird. But that is all just to tie this app together. Is my Helper
a good way of solving this problem? Note: All of the Shapes need to be passed in one Shape array. I can't pass an array of Circles, an array of Triangles, etc.
javascript node.js
javascript node.js
asked 29 mins ago
Eric S
14614
14614
add a comment |
add a comment |
active
oldest
votes
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f210713%2fusing-js-handlebars-to-render-different-child-objects%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f210713%2fusing-js-handlebars-to-render-different-child-objects%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown