Skip to content

Templating

View is a decorator which can be used on a controller method (endpoint). This decorator will use the data returned by the method, and the configured view to create the response.

template engine

Configuration

Install the Ts.ED engines:

sh
npm install --save @tsed/engines
sh
yarn add @tsed/engines
sh
pnpm add @tsed/engines
sh
bun add @tsed/engines

The default template engine installed with Ts.ED is EJS.

ts
import {Configuration} from "@tsed/di";

@Configuration({
  views: {
    root: `../views`,
    viewEngine: "ejs",
    extensions: {
      // optional
      ejs: "ejs",
      hbs: "handlebars"
    },
    options: {
      ejs: {} // global options for ejs engine. See official engine documentation for more details.
    }
  }
})
class Server {}

Options

typescript
export interface PlatformViewsSettings {
  /**
   * Views directory.
   */
  root?: string;
  /**
   * Enable cache. Ts.ED enables cache in PRODUCTION profile by default.
   */
  cache?: boolean;
  /**
   * Provide extensions mapping to match the expected engines.
   */
  extensions?: Partial<PlatformViewsExtensionsTypes>;
  /**
   * Default view engine extension.
   * Allow omitting extension when using View decorator or render method.
   */
  viewEngine?: string;
  /**
   * Options mapping for each engine.
   */
  options?: Partial<PlatformViewsEngineOptions>;
}

Supported template engines

Some package has the same key name, @tsed/engines will load them according to the order number. For example, with dust, @tsed/engines will try to use in this order: dustjs-helpers and dustjs-linkedin.

NamePackage Name / OrderWebsite / State
atplnpm install atpl-
bracketnpm install bracket-template-
dotnpm install dot(website)
dustnpm install dustjs-helpers (2) or
npm install dustjs-linkedin (3)
(website)
ectnpm install ect(website)
ejsnpm install ejs(website)
hamletnpm install hamlet-
hamljsnpm install hamljs-
haml-coffeenpm install haml-coffee-
handlebarsnpm install handlebars(website)
hogannpm install hogan.js(website)
htmlingnpm install htmling-
jazznpm install jazz-
justnpm install just-
liquornpm install liquor-
lodashnpm install lodash(website)
markonpm install marko(website)
motenpm install mote(website)
mustachenpm install mustache-
nunjucksnpm install nunjucks(website)
platesnpm install plates-
pugnpm install pug(website) / (formerly jade)
ractivenpm install ractive-
reactnpm install react-
slmnpm install slm-
squirrellynpm install squirrelly(website)
swignpm install swig-templates (2)-
teacupnpm install teacup-
templayednpm install templayed(website)
twignpm install twig(wiki)
twingnpm install twing(website)
underscorenpm install underscore(website)
vashnpm install vash-
velocityjsBETA(website)
walrusnpm install walrus(website)
whiskersnpm install whiskers-

Note

You must still install the engines you wish to use, add them to your package.json dependencies.

Usage

Template Engine Instances

Template engines are exposed via the requires Map, but they are not instantiated until you've called the getEngine(engine).render() method. You can instantiate them manually beforehand if you want to add filters, globals, mixins, or other engine features.

Nunjucks

typescript
import {Configuration} from "@tsed/di";
import nunjucks from "nunjucks";

const nunjucksInstances = nunjucks.configure("./views");
nunjucksInstances.addFilter("foo", function () {
  return "bar";
});

@Configuration({
  views: {
    root: `${rootDir}/views`,
    viewEngine: "nunjucks",
    extensions: {
      njk: "nunjucks"
    },
    options: {
      nunjucks: {
        requires: nunjucksInstances
      }
    }
  }
})
export default class ShopApp {}

With decorator

Here is an example of a controller using the View decorator:

ts
import {View} from "@tsed/platform-views";
import {Get} from "@tsed/schema";
import {Controller} from "@tsed/di";

@Controller("/events")
export class EventsCtrl {
  @Get("/:id")
  @View("event.ejs")
  public get(): any {
    return {startDate: new Date(), name: "MyEvent"};
  }
}
html
<h1><%- name %></h1>
<div>Start: <%- startDate %></div>

TIP

Like Express.js or Koa.js, View decorator uses express.response.locals or koa.context.state to populate data before rendering the template. See Locals decorator usage for more information.

With render method

It's also possible to render a view by injecting and using PlatformResponse instance.

ts
import {PlatformResponse, Res} from "@tsed/platform-http";
import {Get} from "@tsed/schema";
import {Controller} from "@tsed/di";

@Controller("/events")
export class EventsCtrl {
  @Get("/:id")
  public async get(@Res() response: PlatformResponse): Promise<string> {
    const options = {startDate: new Date(), name: "MyEvent"};

    const result = await response.render("event.ejs", options);

    console.log(result);

    return result;
  }
}
html
<h1><%- name %></h1>
<div>Start: <%- startDate %></div>

With PlatformViews

Ts.ED provides the PlatformViews service to render views. In fact, View decorator uses PlatformResponse.render() method which itself uses the PlatformViews.render() method. It is useful if you want to render a template from a service.

ts
import {Inject, Injectable} from "@tsed/di";
import {PlatformViews} from "@tsed/platform-views";

@Injectable()
export class MyService {
  @Inject()
  platformViews: PlatformViews;

  public async renderTemplate(data: any) {
    const result = await this.platformViews.render("view.ejs", {
      // some other options
      // ...
      ...data
    });

    console.log(result);

    return result;
  }
}

Alter render options

You can alter the render options before rendering the view. Listen the $alterRenderOptions hook to inject data:

typescript
import {Injectable, DIContext} from "@tsed/di";

@Injectable()
class AlterOptions {
  async $alterRenderOptions(options: Record<string, any>, $ctx: DIContext) {
    // only called when the response.render is called by your code
    options.alter = "alter";
    return options;
  }
}

Caching

To enable caching, simply pass { cache: true } to the View decorator. All engines that consolidate.js / @tsed/engines implements I/O for, will cache the file contents, ideal for production environments.

ts
import {View} from "@tsed/platform-views";
import {Get} from "@tsed/schema";
import {Controller} from "@tsed/di";

@Controller("/events")
export class EventCtrl {
  @Get("/:id")
  @View("event.ejs", {cache: true})
  public get(): any {
    return {startDate: new Date(), name: "MyEvent"};
  }
}

TIP

Ts.ED enables cache by default in PRODUCTION profile.

Implement your own engine

@tsed/engines let you register your own engine by using the @ViewEngine decorator. Here an is example of pug engine implementation:

typescript
import {Engine, ViewEngine} from "@tsed/engines";

@ViewEngine("pug", {
  requires: ["pug", "then-pug"] // multiple require is possible. Ts.ED will use the first module resolved from node_modules
})
export class PugEngine extends Engine {
  protected $compile(template: string, options: any) {
    return this.engine.compile(template, options);
  }

  protected async $compileFile(file: string, options: any) {
    return this.engine.compileFile(file, options);
  }
}

Released under the MIT License.