Skip to content

Instantly share code, notes, and snippets.

@crrobinson14
Created July 21, 2018 02:25
Show Gist options
  • Select an option

  • Save crrobinson14/7a889498e8ca266fcdc98eff31488b5c to your computer and use it in GitHub Desktop.

Select an option

Save crrobinson14/7a889498e8ca266fcdc98eff31488b5c to your computer and use it in GitHub Desktop.

Revisions

  1. crrobinson14 created this gist Jul 21, 2018.
    19 changes: 19 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,19 @@
    # EJS template rendering in ActionHero 19+

    This example provides a proof of concept for simple EJS-based template rendering in ActionHero. Note that EJS is this author's favorite "simple" NodeJS
    template engine but it could easily be replaced with any other engine you wish.

    ## Sample Usage

    1. Copy `ejs.js` to `initializers/`.
    1. Create a folder called `templates/` and copy `leaderboard.js` there.
    1. Copy the sample 'getLeaderboard.js' action to `actions/`.

    Once you do this, start or restart your local ActionHero service. Assuming you started it on port 3000, the following two
    URLs should now work:

    http://localhost:3000/?action=getLeaderboard
    http://localhost:3000/?action=getLeaderboard&format=html

    If format is not specified as HTML, standard JSON (API-style) is returned to the client as you would expect. If format is
    set to html, a template is rendered with the same data.
    38 changes: 38 additions & 0 deletions ejs.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,38 @@
    const { Initializer, api } = require('actionhero');

    const ejs = require('ejs');

    const ejsOptions = {
    async: true,
    };

    const ejsMiddleware = {
    name: 'EJS Template Renderer',
    global: true,
    priority: 1,
    postProcessor: async data => {
    const { template, templateData } = data.response;

    if (template) {
    data.toRender = false;
    data.connection.setStatusCode(200);
    data.connection.setHeader('Content-Type', 'text/html');

    const rendered = await ejs.renderFile(`templates/${template}`, templateData || {}, ejsOptions);
    data.connection.pipe(rendered);
    }
    }
    };


    module.exports = class Secrets extends Initializer {
    constructor() {
    super();
    api.ejs = ejs;
    this.name = 'EJS Template Rendering';
    }

    async initialize() {
    api.actions.addMiddleware(ejsMiddleware);
    }
    };
    38 changes: 38 additions & 0 deletions getLeaderboard.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,38 @@
    const { Action } = require('actionhero');

    const formatValidator = param => {
    if (['html', 'json'].indexOf(param) === -1) {
    throw new Error('Invalid format, must be "html" or "json".');
    }
    };

    module.exports = class getLeaderboard extends Action {
    constructor() {
    super();

    this.name = 'getLeaderboard';
    this.description = 'Get the Leaderboard';

    this.inputs = {
    format: { required: false, validator: formatValidator, },
    };
    }

    async run(data) {
    const { format } = data.params;

    const leaderboardData = [
    { id: 'abc123', name: 'Halle Berry', score: 45000 },
    { id: 'xyz123', name: 'Chuck Berry', score: 44999 },
    { id: '123xyz', name: 'Halley\'s Comet', score: 30000 },
    { id: '123abc', name: 'Halley\'s Comment', score: 20000 },
    ];

    if (format === 'html') {
    data.response.template = 'leaderboard.ejs';
    data.response.templateData = { leaderboardData };
    } else {
    data.response.leaderboardData = leaderboardData;
    }
    }
    };
    7 changes: 7 additions & 0 deletions leaderboard.ejs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,7 @@
    <h1>Leaderboard</h1>
    <% leaderboardData.forEach(function(leader){ %>
    <div class="leader">
    <span class="name"><%= leader.name %></span>
    <span class="score"><%= leader.score %></span>
    </div>
    <% }); %>