For the complete documentation index, see llms.txt. This page is also available as Markdown.

UI Integration

How an App and the ERP talk to each other inside the iframe — postMessage protocol, dialogs, height, widgets.

Your App runs in an iframe inside the ERP. The manifest declares where it appears; this page describes how the two sides talk once it is there.

Everything goes through postMessage, wrapped in two helpers:

import { sendMain, receiveMain } from '@vario-software/vario-app-framework-frontend/script/communication.js';

sendMain({ height: 640 });

const stop = receiveMain({
  updateComponents: () => reload(),
  route: route => console.log(route.name),
});

sendMain automatically adds your appIdentifier and integrationId to every message — the ERP uses both to route it back to the right frame.

The ERP must hear from you within 15 seconds

The host waits for a first valid message as a loaded-handshake. If none arrives within 15 seconds, your App is replaced by an "app not available" message.

The designated signal for this is:

sendMain({ ready: true });

The framework sends it for you from secureIntegration(), which runs on DOMContentLoaded. That function does two things: it verifies your page is really embedded in a VARIO Cloud frame (by checking the referrer against the *.vario.cloud hosts and localhost), and then reports readiness.

The host does not insist on that specific key — it treats the first valid message as the handshake, whatever it contains. So an App that immediately reports its height is also fine. ready is simply the explicit, guaranteed way to do it.

Don't confuse it with customActivity, which is unrelated: that one resets the ERP's idle timer during long interactions so the user isn't logged out.

Sizing the frame

An iframe cannot grow with its content. There is no height: auto that means "as tall as the page inside" — the browser gives the frame a fixed box, and anything taller simply scrolls inside it. The result is the thing users complain about: a second scrollbar within the ERP page, and your content cut off at an arbitrary line.

The ERP cannot fix this on its own either. Your App is served from your own domain, so the host is not allowed to measure the document inside the frame. Only you know how tall your content is.

Hence the contract: you measure, the host applies.

Send it once the content is rendered, and again whenever it changes — after loading data, expanding a section, opening a form. The framework can do this continuously for you via initHeightTransfer(), which watches the body and re-sends on every change.

Once the host owns the height — in full-height mode, in a dialog, or in a dashboard widget — your own height messages are ignored. Inside a dialog use sendMain({ dialog: { fullHeight: true } }) instead.

Dialogs

Your App can open another of its own integrations as a modal, and get a value back.

Open it (the integrationId must be declared in your manifest, typically without a pointOfIntegration):

Close it and return a value — this is what the dialog's own code sends:

Receive the result in the opener:

If the user dismisses the dialog with the close button instead, no result is sent at alldialogOk/dialogResult never arrive. That is what updateComponentsAfterDismiss is for: it makes the ERP refresh its components anyway. Note it sits on dialog, not inside dialog.open.

Inside a dialog you can also send dialog.disablePadding and stickynavButtons (rendered into the dialog header).

Using the ERP's own dialogs

You don't have to build pickers. Ask the host to open its own and send you the result:

Send
Get back

searchDialog

searchDialog-<key>{ selected }

datepicker

datepicker-<key> — JSON string of { date, to }

cron

cron-<key> — JSON string of { value }

colorpicker

colorpicker-<key> — JSON string of { value }

confirmation

confimation{ key, values }

Each accepts an optional key so you can tell several instances apart; without it the reply key ends in -result.

Integrating into the ERP shell

Message
Effect

ready

Confirms your integration has loaded — the handshake described above

updateComponents

Tells the ERP to refresh its datagrids and badges

notify

Shows an ERP toast; route adds an open-in-new-tab action

badge

Puts a badge on your tab

backlink

Custom back link; clicking it sends you back

stickynavButtons

Buttons in the sticky nav; a click sends you button-<key>

stickynavTabs

Sub-tabs bound to the route; the host rewrites the URL rather than reloading you

editmode

Register, enter or leave the ERP's edit mode; you then receive edit, save, cancel

documentTitle

Sets the browser tab title

copyToClipboard

Copies text and shows a confirmation

customActivity

Resets the idle timer, preventing auto-logout during long interactions

minWidth

Minimum width for your frame

openInNewTab / openInSameTab

Navigate the ERP (see below)

updateSettings

Change a shared setting — only the level-of-detail and UI-mode keys are accepted

Some of these are vetoed by the host depending on where you are embedded: stickynavButtons, backlink and editmode are ignored inside dialogs and widgets.

What the host sends you

Key
Meaning

height

New frame height (CSS string) in full-height mode

updateComponents

Something changed in the ERP; refresh

changeLanguageCode

The user switched language

route + routeChanged

The ERP route changed

submit

An ERP form is submitting — see below

dialogOk / dialogResult

Your dialog resolved

back

Your custom backlink was clicked

appToken

A refreshed App token

edit / save / cancel

Edit-mode actions

button-<key>

One of your sticky-nav buttons was clicked

beforeUnmount

Your integration is being torn down

Answering a submit

When the ERP submits a form that contains your integration, it asks you to confirm:

The target is a standard vue-router location, so name must be a route the ERP actually has.

Route names are not listed here — there are many and they change per release. The ERP's route definitions are the source of truth; the names follow the visible hierarchy (documents-sales.index, accounts.detail.tabs.masterdata, settings.general.users.index). App integrations get generated names of the form apps.<appIdentifier>.<integrationId>.

openInSameTab navigates the ERP window itself and is deliberately restricted — a string target is only accepted for VARIO Cloud hosts.

Parameters you receive

The host puts context on your integration URL. The framework exposes the common ones:

appIdentifier, integrationId, language, supportMode, myCompanyId, uimode, detailDatagridTable, superUser, permissions, additionalPayload

Also on the URL but not exposed by the framework — read them from the query string yourself: userId, detailDatagrid, routeName, and every parameter of the current ERP route.

Dashboard widgets

A widget is an integration mounted at one of the dashboard.* integration points. Its title and icon come from the manifest; the grid fixes the minimum size.

Settings are exchanged, not stored by you. Announce your defaults, and the host sends back the user's saved settings merged over them:

When the user changes something, report it and the dashboard persists it:

To follow the ERP's own edit mode, report your state with sendMain({ widget: { editmode: { active } } }).

Reusing the ERP's look

The framework ships CSS only — no JavaScript components. Link the stylesheet and write plain markup with v-* classes:

Controls rely on structure. A checkbox needs a wrapper, and the input must come immediately before its label, because the checked state is expressed with an adjacent-sibling selector:

Put anything between the input and the label and nothing renders. v-toggle has the same structure for switches.

Dark mode and responsive breakpoints are applied by initSharedSettings() and initScreenSize(), which set classes on body.

Last updated

Was this helpful?