Bixby Developer Center

Guides

Dialog Macros

Note

Both template-macro and template-macro-def will be deprecated in a future release. You should switch to using generic macro and macro-def keys instead to create dialog macros. For more information, see Reusing Content with Macros.

Dialog can often contain complex logic that you might want to factor out. You can use dialog macros to avoid having to duplicate dialog logic.

Take, for example, this common pattern within a capsule:

if (exists(concept)) {
template ("#{concept} and #{value(string2)}")
} else {
template ("#{value(string2)}")
}

Often, this logic can be even more complicated. If you have to repeat it across hundreds of dialog files, it would be tedious, especially if design changes call for rendering that string differently.

Video Tutorial: Using Dialog Macros in Bixby

The following video tutorial shows how to reuse text with dialog macros.

Dialog Macro Definition

With a dialog macro, you can define that pattern using the macro-def key.

macro-def (id1) {
content {
template (ID1 text)
}
}

Here is another example that also uses conditionals:

macro-def (id2) {
params {
param (x) {
type (example.testNamedDialog.TestConcept)
min (Required)
max (One)
}
param (t) {
type (Text)
}
}
content {
if (exists(t)) {
template ("#{t} : #{value(x)}")
} else {
template ("#{value(x)}")
}
}
}

Dialog Macro Invocation

You can invoke this dialog macro by calling the macro with the ID you specified in your macro-def:

If using a macro:

dialog (Result) {
match: example.testNamedDialog.TextConcept (this)
macro (id2) {
param (x) {
expression (this)
}
param (t) {
literal ("some text")
}
}
}
Note

You cannot have a macro with the same ID if the macro is defined in the same resource folder. For example, if you have a macro with the ID "this-test-macro" in the bixby-mobile-en-US target, you cannot have another different macro with the same name in that target.

However, if the macro's target is in a higher level resource folder, the more specific target will override the more general target. For example, say you have a macro in bixby-mobile-en and another macro in bixby-mobile-en-US, both with the ID "this-test-macro". The macro in the bixby-mobile-en-US target will render for the bixby-mobile-en-US target, but the bixby-mobile-en macro will render for the bixby-mobile-en-GB target.

Macros with the same ID but in different targets (for example, bixby-mobile-ko-KR and bixby-mobile-en-US) are allowed and are encouraged, especially when localizing or handling development for multiple devices.

If later you need to change this complex logic, you only need to change it in the macro definition once.

You can use template macros anywhere you can use a template, including in views:

result-view {
match {
Receipt (receipt) {
min (Required)
max (One)
}
}

message {
macro (RECEIPT_RESULT) {
param (receipt) {
expression (receipt)
}
}
}

render {
layout {
macro (receipt-header) {
param (receipt) {
expression (receipt)
}
}
macro (receipt-contact-information) {
param (receipt) {
expression (receipt)
}
}
macro (receipt-order-total) {
param (receipt) {
expression (receipt)
}
}
}
}
}

View master on GitHub

Note that you can also use macros without any parameters, and you can declare more than one in a single dialog macro file:

// In a hello-dialog.macro.bxb file
macro-def (HelloWorld) {
content {
template ("Hello World!")
}
}

macro-def (WelcomeMessage) {
content {
template ("Welcome to the wonderful world of Bixby!")
}
}

Not only is this feature useful for composing complicated dialog, but it is also useful for localization. When a capsule is multi-locale, you can factor out strings into macros in separate files, which can then be translated by translation services. You can then place the translated versions in the appropriate resources locale folder. If you do so, ensure that the resulting composed strings work properly in the locale you are targeting.

Here is an example for a capsule in which you declare several dialog macros for contact information:

macro-def (ContactInformation) {
content {
template ("Contact information")
}
}

macro-def (Name) {
content {
template ("Name")
}
}

macro-def (PhoneNumber) {
content {
template ("Phone number")
}
}

macro-def (Email) {
content {
template ("Email")
}
}

View 1e25bcd on GitHub

Each dialog macro can include related parameters, which consist of a parameter name param, associated type, and cardinality rules (min and max).

There is also always corresponding content, which is where you include the text of the dialog.

And this is how you can invoke dialog macros within a macro-def, which uses dialog macros to create contact information in a receipt:

macro-def (receipt-contact-information) {
params {
param (receipt) {
type (Receipt)
min (Required) max (One)
}
}
content {
section {
title {macro (ContactInformation)}
content {
partitioned {
content {
cell-area {
slot2 {
content {
order (SecondaryPrimary)
secondary {
macro (Name)
}
primary {
template ("[#{value(receipt.buyer.firstName)} #{value(receipt.buyer.lastName)}]")
}
}
}
}
cell-area {
slot2 {
content {
order (SecondaryPrimary)
secondary {
macro (PhoneNumber)
}
primary {
template ("[#{value(receipt.buyer.phoneInfo.number)}]")
}
}
}
}
cell-area {
slot2 {
content {
order (SecondaryPrimary)
secondary {
macro (Email)
}
primary {
template ("[#{value(receipt.buyer.emailInfo.address)}]")
}
}
}
}
}
}
}
}
}
}

View master on GitHub

Macro Name-Spacing

Macros follow the same name-spacing rules that apply to model references. This means you must qualify macros that you import, but not those that are local to your capsule.

Take, for example, a capsule called example.capsule1 that defines a dialog macro template1. If you want to import template1 into another capsule called example.capsule2, you must fully qualify it as shown here:

macro(example.capsule1:template1)

However, if you want to use that same macro within example.capsule1 itself, you should use the unqualified notation:

macro(template1)

You can also use an alias to qualify template macros. For example, if example.capsule2 imports example.capsule1 as aliasedcapsule, you can then invoke a macro within it using the alias:

macro(aliasedcapsule:template1)

Why Use Macros

As mentioned before, dialog macros and macros in general are useful for reusing content in several places. It also allows you to compose complicated dialogs, as seen in previous examples.

It is also useful for localization and multiple devices. When a capsule supports multiple locales or multiple devices, you can factor out strings into macros in separate files.

For localization in particular, the strings in these separate macros can be translated by translation services. You can then place the translated versions in the appropriate resources locale folder. Similarly for multiple devices, you can tweak the dialog depending on the user experience, such as hands-free list navigation dialog versus a touch-based dialog or UI strings, and put them in the appropriate resources device folder. If you do so, ensure that the resulting composed strings work properly in the locales and devices you are targeting by testing your capsule with the Simulator.

Here is an example for a capsule in which you declare several dialog macros for contact information, which could easily be used for translation:

macro-def (ContactInformation) {
content {
template ("Contact information")
}
}

macro-def (Name) {
content {
template ("Name")
}
}

macro-def (PhoneNumber) {
content {
template ("Phone number")
}
}

macro-def (Email) {
content {
template ("Email")
}
}

View 1e25bcd on GitHub

For another example of using macros with dialog, see the Dialog Affirmations sample capsule.