ui.BoardUI

Table of contents

Methods

Properties

Methods

openPanel

openPanel(options): Promise<void>

Opens a panel on the current board.
The content displayed in the panel is fetched from the specified URL.

If you don't set a value for height, the panel height corresponds to the current viewport height.

  • Panel width: currently it's set to 368 dp, fixed, padding included.
    You should implement your app to adapt to content area width changes between 292 dp and 320 dp, and to accommodate a fixed panel width between 340 dp and 368 dp, padding included.
  • Left padding: 24 dp
  • Right padding: 24 dp

Example:

await miro.board.ui.openPanel({
  url: 'show-this-page-in-the-panel.html',
  height: 400,
});

// The panel is displayed on the board

The content that apps display on modals and panels opens inside iframes.
iframes can request access to the following permissions:

  • microphone:listen: access a user's microphone to record audio in an iframe.
  • screen:record: access a user's screen to record it in an iframe.
  • webcam:record: access a user's camera to record video.

See also:

Parameters

NameTypeDescription
optionsObject-
options.urlstringAbsolute or relative URL pointing to the content that you want to display in the panel.
If you specify a relative URL, the URL path resolves relative to the app URL.
The transport protocol must be HTTPS.
options.height?numberSets the height of the panel, in dp.
If you don't specify any height, the panel takes the height value of the current viewport.

Returns

Promise<void>


closePanel

closePanel(): Promise<void>

Closes an open panel on the current board.

The method doesn't take any arguments.

ℹ️ Note:

  • To close an open panel, closePanel must execute after openPanel.
  • The app that closes the panel with closePanel must be the same that opened it with openPanel.

Example:

// Open a panel
await miro.board.ui.openPanel({
  url: 'show-this-page-in-the-panel.html',
  height: 400,
});

// Close the open panel
await miro.board.ui.closePanel();

Returns

Promise<void>


openModal

openModal(options): Promise<void>

Opens a modal on the current board.
The content displayed in the modal is fetched from the specified URL.

The max. width and height of the modal correspond to the width and height of the current viewport.
The load timeout for the modal is 10 seconds.

Example:

await miro.board.ui.openModal({
  url: 'show-this-page-in-the-modal.html',
  width: 600,
  height: 400,
  fullscreen: false,
});

// The modal is displayed on the board

The content that apps display on modals and panels opens inside iframes.
iframes can request access to the following permissions:

  • microphone:listen: access a user's microphone to record audio in an iframe.
  • screen:record: access a user's screen to record it in an iframe.
  • webcam:record: access a user's camera to record video.

See also:

Parameters

NameTypeDescription
optionsObject-
options.urlstringAbsolute or relative URL pointing to the content that you want to display in the modal.
If you specify a relative URL, the URL path resolves relative to the app URL.
The transport protocol must be HTTPS.
options.height?numberSets the height of the modal, in dp.
The max. height of the modal corresponds to the height of the current viewport.
Default: 600
options.width?numberSets the width of the modal, in dp.
The max. width of the modal corresponds to the width of the current viewport.
Default: 800
options.fullscreen?booleanSet it to:
  • false to disallow full screen display for the modal.
  • true to override height and width, and to display the modal in full screen.
Default: false

Returns

Promise<void>


closeModal

closeModal(): Promise<void>

Closes an open modal on the current board.

The method doesn't take any arguments.

ℹ️ Note:

  • To close an open modal, closeModal must execute after openModal.
  • The app that closes the modal with closeModal must be the same that opened it with openModal.

Example:

// Open a modal
await miro.board.ui.openModal({
  url: 'show-this-page-in-the-modal.html',
  height: 400,
  width: 600,
  fullscreen: false,
});

// Close the open modal
await miro.board.ui.closeModal();

Returns

Promise<void>

Properties

on

on: (event: EventType, handler: (event: EventPayloads) => void) => void(event: "drop", handler: (event: DropEvent) => void) => void(event: "icon:click", handler: () => void) => void(event: "app_card:open", handler: (event: AppCardOpenEvent) => void) => void(event: "app_card:connect", handler: (event: AppCardConnectEvent) => void) => void(event: "selection:update", handler: (event: SelectionUpdateEvent) => void) => void

Type declaration

▸ (event, handler): void

on property

miro.board.ui.on(event, handler);

If you want your app to react to an event by executing a function, you can use the on property to subscribe to events.
The on property calls a handler function after an event has occurred.

To subscribe to an event and its handler, pass to the on property:

  • The event that your app should listen to.
  • The event handler that the app needs to call when the event fires.

💡 To unsubscribe from an event and its handler, use the off property.

Supported events
Event typeEvent handlerEvent fires when...
drop(event: DropEvent)An HTML element is dropped from an open panel to the board. See also Add drag and drop to your app.
icon:click()An app icon is clicked. See also Add clicking on an icon to your app.
app_card:open(event: AppCardOpenEvent)The app card status icon is connected, the icon is clicked, and it enables opening a modal with the app card detail view.
app_card:connect(event: AppCardConnectEvent)The app card status icon is disconnected, the icon is clicked, and it enables connecting an app card with a corresponding data source.
selection:update(event: SelectionUpdateEvent)An area on the board is selected.
Parameters
NameType
eventEventType
handler(event: EventPayloads) => void
Returns

void

▸ (event, handler): void

drop event

on(event: 'drop', handler: (event: DropEvent) => void): void

The event handler has the following properties:

PropertyTypeDescription
xNumberCoordinate that defines the horizontal position of the HTML element to drop on the board.
yNumberCoordinate that defines the vertical position of the HTML element to drop on the board.
targetElement interfaceThe HTML element that is the recipient of the drop event.

Example:

/** When the selected HTML element is dropped on the board:
 *  1. A sticky note is created.
 *  2. The text of the HTML element is assigned to the
 *     'content' property of sticky note.
 */
miro.board.ui.on('drop', async ({x, y, target}) => {
  await miro.board.createStickyNote({
    x,
    y,
    content: target.innerText,
  });
});
Parameters
NameType
event"drop"
handler(event: DropEvent) => void
Returns

void

▸ (event, handler): void

icon:click event

on(event: 'icon:click', handler: () => void) => void

icon:click registers click events on icons.
When a user clicks an icon, the icon:click event triggers, and any registered event handler is called.
Typically, icon:click is used to open a panel, or to display a modal.

Example:

/** When a user clicks the icon:
 *  1. The openPanel method is called
 *  2. The method opens the HTML page: `panel.html`
 */
miro.board.ui.on('icon:click', async () => {
  await miro.board.ui.openPanel({
    url: 'panel.html',
  });
});
Parameters
NameType
event"icon:click"
handler() => void
Returns

void

▸ (event, handler): void

app_card:open event

on(event: 'app_card:open', handler: (event: AppCardOpenEvent) => void): void;

app_card:open registers click events to open an app card from compact to detail view.
When a user clicks the icon to expand an app card to view it in detail, the app_card:open event triggers, and a registered event handler is called.
Typically, app_card:open is used to open a modal displaying the custom fields of the app card and their content.

Example:

/** When a user clicks the icon that expands an app card to view it in detail:
 *  1. The 'openModal' method is called
 *  2. The method opens a modal to display the specific app card content fetched from the URL
 */
// Listen to the 'app_card:open' event
miro.board.ui.on('app_card:open', (event) => {
  console.log('Subscribed to app card open event', event);
  const {appCard} = event;

  // Build a URL containing the app card ID.
  // You pass this URL with the 'openModal()' method below.
  // The code in the modal uses the 'appCardId' URL query parameter
  // to identify which app card was opened.
  const url = `https://my.app.example.com/modal.html?appCardId=${appCard.id}`;

  // Open the modal to display the content of the fetched app card
  miro.board.ui.openModal({
    url,
  });
});
Parameters
NameType
event"app_card:open"
handler(event: AppCardOpenEvent) => void
Returns

void

▸ (event, handler): void

app_card:connect event

on(event: 'app_card:connect', handler: (event: AppCardConnectEvent) => void): void;

By default, newly created app cards have a disconnected status, unless the app card constructor sets a different value.
To connect an app card to a corresponding data source in an external application, an app must listen to the app_card:connect event.

When an app listens to the app_card:connect event:

  • The disconnected icon App card status: disconnectedApp card status: disconnected is clickable.
  • On hovering over the icon, a tooltip is displayed to notify users that they can click the icon to connect the app card to a data source.
  • When users click the icon, the app_card:connect event fires.
  • The event handler needs to include at least the logic to:
    • Retrieve the data source that the app card maps to.
    • Sync data to populate the app card fields with any updated information.
    • Update the app card status from disconnected to connected.
    • sync() the app card to propagate the changes to the board.

If the app listens also to the app_card:open event, it can react to it; typically, by opening a modal to display the app card detail view.

Example:

/** In a typical flow:
 *  1. The app creates an app card.
 *     The 'disconnected' status icon is not clickable, yet.
 *  2. The app listens to the 'app_card:connect' event.
 *     The 'disconnected' status icon is clickable.
 *  3. The app listens to the 'app_card:open' event.
 *  4. When users click the 'disconnected' status icon, a tooltip prompts them to connect the app card to its data source.
 *  5. When the app card is connected, its status icon changes to 'connected'.
 *  6. Now the app can open a modal to display the app card detail view.
 */

// Create an app card
const appCard = await miro.board.createAppCard({
  title: 'This is the title of the app card',
  // Default status of new app cards
  status: 'disconnected',
});

// Listen to the 'app_card:connect' event
miro.board.ui.on('app_card:connect', (event) => {
  console.log('Connect the app card to its data source');
  const appcard = event.appCard;
  // Update the app card status to 'connected'
  appcard.status = 'connected';
  // Propagate the app card updates to the board
  appcard.sync();
});

// Listen to the 'app_card:open' event
miro.board.ui.on('app_card:open', (event) => {
  console.log('Subscribed to app card open event', event);
  // URL containing the app card ID.
  // The content is displayed inside the modal
  const url = `https://my.app.example.com/modal.html?appCardId=${appCard.id}`;
  // Open the modal to display the content of the fetched app card
  miro.board.ui.openModal({
    url,
  });
});


Figure 1. Newly created card, or duplicate app card through manual copying and pasting on the board UI. The app card status is disconnected. The tooltip notifies about the missing connection. The status icon isn't clickable.


Figure 2. The app card status is disconnected. The tooltip prompts to connect it to its data source. The status icon is clickable.


Figure 3. The app card status is connected. The app listens to the app_card:open event. When the icon is clicked, the event fires. Typically, it opens a modal to display the app card detail view.

Parameters
NameType
event"app_card:connect"
handler(event: AppCardConnectEvent) => void
Returns

void

▸ (event, handler): void

selection:update event

on(event: 'selection:update', handler: (event: SelectionUpdateEvent) => void): void;

selection:update is triggered when a user selects an area on the board. The event contains an array with the selected board items.
If the selected area doesn't include any board items, the array is empty.

You can add logic to perform actions on the selection, such as filtering specific item types, and then modifying them.

Example:

/** When a user clicks and selects multiple board items on a board:
 *  1. The 'selection:update' method logs the selection to the developer console
 *  2. A filter identifies sticky note items in the selection
 *  3. The color of the sticky notes is changed to 'cyan'
 */

// Listen to the 'selection:update' event
miro.board.ui.on('selection:update', async (event) => {
  console.log('Subscribed to selection update event', event);
  console.log(event.items);
  const selectedItems = event.items;

  // Filter sticky notes from the selected items
  const stickyNotes = selectedItems.filter((item) => item.type === 'sticky_note');

  // Change the fill color of the sticky notes
  for (const stickyNote of stickyNotes) {
    stickyNote.style.fillColor = 'cyan';
    await stickyNote.sync();
  }
});
Parameters
NameType
event"selection:update"
handler(event: SelectionUpdateEvent) => void
Returns

void


off

off: (event: EventType, handler: (event: EventPayloads) => void) => void(event: "drop", handler: (event: DropEvent) => void) => void(event: "icon:click", handler: () => void) => void(event: "app_card:open", handler: (event: AppCardOpenEvent) => void) => void(event: "app_card:connect", handler: (event: AppCardConnectEvent) => void) => void(event: "selection:update", handler: (event: SelectionUpdateEvent) => void) => void

Type declaration

▸ (event, handler): void

off property

miro.board.ui.off(event, handler);

When an app no longer needs to listen to an event to trigger an event handler, it can use the off property to unsubscribe from it.
To unsubscribe from an event and its handler, pass to the off property:

  • The event whose handler you want your app to unsubscribe from.
  • The event handler that you previously registered with the on property, and that your app no longer needs to listen to.

💡 To subscribe to an event and its handler, use the on property.

Supported events

See the supported events for the on property.

Parameters
NameType
eventEventType
handler(event: EventPayloads) => void
Returns

void

▸ (event, handler): void

drop unsubscribe

off(event: 'drop', handler: (event: DropEvent) => void): void

Enables unsubscribing from a drop event handler.
To unsubscribe, pass to the off property:

  • The drop event.
  • The event handler that you previously registered with the on property, and that your app no longer needs to listen to.

Example:

// Add a 'drop' event handler to drag and drop images.
const drop = async (event: DropEvent) => {
  const {x, y, target} = event;
  if (target instanceof HTMLImageElement) {
    const image = await miro.board.createImage({
      x,
      y,
      url: target.src,
    });
  }
};

// Register the 'drop' event, so that the app listens to it.
miro.board.ui.on('drop', drop);

// Unsubscribe from the 'drop' handler.
// The app no longer creates image items on drag and drop.
miro.board.ui.off('drop', drop);
Parameters
NameType
event"drop"
handler(event: DropEvent) => void
Returns

void

▸ (event, handler): void

icon:click unsubscribe

off(event: 'icon:click', handler: () => void) => void

Enables unsubscribing from an icon:click event handler.
To unsubscribe, pass to the off property:

  • The icon:click event.
  • The event handler that you previously registered with the on property, and that your app no longer needs to listen to.

Example:

// Add an 'iconClick' event handler to open a panel upon clicking an icon.
const iconClick = async () => {
  await miro.board.ui.openPanel({
    url: 'panel.html',
  });
};

// Register the 'icon:click' event, so that the app listens to it.
miro.board.ui.on('icon:click', iconClick);

// Unsubscribe from the 'icon:click' event handler.
// The app no longer enables opening a panel when clicking an icon.
miro.board.ui.off('icon:click', iconClick);
Parameters
NameType
event"icon:click"
handler() => void
Returns

void

▸ (event, handler): void

app_card:open unsubscribe

off(event: 'app_card:open', handler: (event: AppCardOpenEvent) => void): void;

Enables unsubscribing from an app_card:open event handler.
To unsubscribe, pass to the off property:

  • The app_card:open event.
  • The event handler that you previously registered with the on property, and that your app no longer needs to listen to.

Example:

// Create an app card.
const appCard = await miro.board.createAppCard({
  title: 'This is the title of the app card',
  status: 'disconnected',
});

// Add an 'appCardOpen' event handler for the 'app_card:open' event.
const appCardOpen = async (event: AppCardOpenEvent) => {
  const appcard = event.appCard;
  const url = `https://my.app.example.com/modal.html?appCardId=${appCard.id}`;
  miro.board.ui.openModal({
    url,
  });
};

// Register the 'app_card:open' event, so that the app listens to it.
miro.board.ui.on('app_card:open', appCardOpen);

// Unsubscribe from the 'app_card:open' event handler.
// The app no longer enables opening a modal with the detail view of an app card.
miro.board.ui.off('app_card:open', appCardOpen);
Parameters
NameType
event"app_card:open"
handler(event: AppCardOpenEvent) => void
Returns

void

▸ (event, handler): void

app_card:connect unsubscribe

off(event: 'app_card:connect', handler: (event: AppCardConnectEvent) => void): void;

Enables unsubscribing from the app_card:connect event and its handler.
To unsubscribe, pass to the off property:

  • The app_card:connect event.
  • The event handler that you previously registered with the on property, and that your app no longer needs to listen to.

Example:

// Create an app card.
const appCard = await miro.board.createAppCard({
  title: 'This is the title of the app card',
  status: 'disconnected',
});

// Add an 'appCardConnect' event handler for the 'app_card:connect' event.
const appCardConnect = async (event: AppCardConnectEvent) => {
  const appcard = event.appCard;
  appcard.status = 'connected';
  appcard.sync();
};

// Register the 'app_card:connect' event, so that the app listens to it.
miro.board.ui.on('app_card:connect', appCardConnect);

// Unsubscribe from the 'app_card:connect' event handler.
// The app no longer enables connecting an app card to a data source.
miro.board.ui.off('app_card:connect', appCardConnect);
Parameters
NameType
event"app_card:connect"
handler(event: AppCardConnectEvent) => void
Returns

void

▸ (event, handler): void

selection:update unsubscribe

off(event: 'selection:update', handler: (event: SelectionUpdateEvent) => void): void;

Enables unsubscribing from a selection:update event handler.
To unsubscribe, pass to the off property:

  • The selection:update event.
  • The event handler that you previously registered with the on property, and that your app no longer needs to listen to.

Example:

// Add a 'selectionUpdate' event handler to update the color of sticky notes included in a selection.
const selectionUpdate = async (event: SelectionUpdateEvent) => {
  const selectedItems = event.items;
  const stickyNotes = selectedItems.filter((item) => item.type === 'sticky_note');
  for (const stickyNote of stickyNotes) {
    stickyNote.style.fillColor = 'cyan';
    await stickyNote.sync();
  }
};

// Register the 'selection:update' event, so that the app listens to it.
miro.board.ui.on('selection:update', selectionUpdate);

// Unsubscribe from the 'selection:update' event handler.
// The app no longer enables updating the color of the sticky notes included in a selection to cyan.
miro.board.ui.off('selection:update', selectionUpdate);
Parameters
NameType
event"selection:update"
handler(event: SelectionUpdateEvent) => void
Returns

void


Did this page help you?