Using JS Handlebars to render different child objects












0














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.










share|improve this question



























    0














    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.










    share|improve this question

























      0












      0








      0







      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.










      share|improve this question













      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






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked 29 mins ago









      Eric S

      14614




      14614



























          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
          });


          }
          });














          draft saved

          draft discarded


















          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
















          draft saved

          draft discarded




















































          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.




          draft saved


          draft discarded














          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





















































          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







          Popular posts from this blog

          Morgemoulin

          Scott Moir

          Souastre