Output Classes
Output classes offer a way to return structured output templates.
Introduction
The goal of an output class is to have a modular, reusable class that returns output. Learn more about output here.
Output classes are stored in a component's output
folder. As a convention, the files are usually named like the class, for example MenuOutput.ts
.
Each output class contains:
- A
build()
method that returns an output template options
that can be passed using$send()
- Optionally helper methods that can be used to build the output object
Here is an example of a HelloWorldOutput
class:
import { BaseOutput, Output, OutputTemplate } from '@jovotech/framework'; @Output() export class HelloWorldOutput extends BaseOutput { build(): OutputTemplate | OutputTemplate[] { return { message: 'Hello World!', }; } }
An output class can get passed to the $send()
method (which you can learn more about in the output documentation):
import { SomeOutput } from './output/SomeOutput'; // ... yourHandler() { // ... return this.$send(SomeOutput, { /* output options */ }); }
Build Method
The most important part of an output class is an output template that is returned by a build()
method. This object is then translated into the appropriate platform response.
build(): OutputTemplate | OutputTemplate[] { return { message: 'Hello World!', }; }
Usually, you don't do more inside build()
than modifying the output object directly.
There are several ways how you could add further modifications. For example, you can add helper methods like this:
build(): OutputTemplate | OutputTemplate[] { return { message: 'Hello World!', carousel: this.getCarousel(), }; } getCarousel() { // ... }
There's also the possibility that there is completely distinct output depending on a few factors. For example, output could differ for voice and text based interfaces. You could modify build()
in a way that it returns different output objects:
build(): OutputTemplate | OutputTemplate[] { if(/* some condition */) { return { message: 'Output A', }; } else { return { message: 'Output B', }; } }
Output Options
As a convention, an output template should only be responsible for organizing the output, not collecting any data. To achieve this, the handler should first collect all necessary information and then pass it to the output class as options
:
return this.$send(YourOutput, { /* options */ });
There are two types of properties that can be passed:
- Reserved properties: You can pass elements like
message
to be automatically added to the output template - Custom options: Pass any additional data to be used in the output class
Reserved Properties
Reserved properties are output elements that can be passed as options. They are automatically added to the output object and allow the $send()
method to override generic output properties in the output template.
For example, a message
can be passed right from the handler:
return this.$send(YourOutput, { message: 'Hi there!' });
Even if YourOutput
already includes a message
property, it will be replaced with "Hi there!"
.
The following properties are reserved:
message
reprompt
listen
quickReplies
card
carousel
platforms
All properties except platforms
replace the current property in the output template. For platforms
, the content gets merged to allow for more granularity.
Custom Options
You can pass any other options that are not reserved properties and reference them inside the output class using this.options
.
For example, here we're passing a user's name
:
return this.$send(YourOutput, { name: 'Sam' });
We can then greet them by their name using this.options.name
:
build(): OutputTemplate | OutputTemplate[] { return { message: `Hey ${this.options.name}!`, }; }
Option Types
Extend OutputOptions
to create an interface for your output option types:
import { BaseOutput, OutputOptions } from '@jovotech/framework'; // ... export interface YourOutputOptions extends OutputOptions { name: string; } export class YourOutput extends BaseOutput<YourOutputOptions> { // ... }
The above code example creates YourOutputOptions
that are then passed to BaseOutput
as generics with BaseOutput<YourOutputOptions>
.
getDefaultOptions
If you want to set default options, you can implement the following method:
getDefaultOptions() { return { /* default options */ }; }
Using TypeScript, you can also add the types:
import { BaseOutput, Output, OutputOptions, OutputTemplate } from '@jovotech/framework'; // ... export interface YourOutputOptions extends OutputOptions { name: string; } @Output() export class YourOutput extends BaseOutput<YourOutputOptions> { build(): OutputTemplate | OutputTemplate[] { return { message: `Hey ${this.options.name}!`, }; } getDefaultOptions(): YourOutputOptions { return { name: 'there', }; } }
If the $send()
method doesn't pass a proper name
to the output class in the above example, the response will be Hey there!
.
Helper Methods
You can add helper methods to the output class and reference them with this.helperMethodName()
.
build(): OutputTemplate | OutputTemplate[] { return { message: `Here are our categories: ${this.listCategories(this.options.categories)}`, }; } listCategories(categories) { // ... }
You can also use get
properties:
build(): OutputTemplate | OutputTemplate[] { return { message: `Here are our categories: ${this.listCategories}`, }; } get listCategories() { this.options.categories.forEach(/* ... */); // ... }
Constructor
By default, your class does not need a custom constructor.
However, if you wish to add one, you can do the following:
import { Output, BaseOutput, OutputOptions } from '@jovotech/framework'; // ... export interface YourOutputOptions extends OutputOptions { // ... } Output(); export class YourOutput extends BaseOutput<YourOutputOptions> { // ... constructor(jovo: Jovo, options: DeepPartial<YourOutputOptions>) { super(jovo, options); // Do something } }