Pluggable Widgets API

Last update: Edit

1 Introduction

Mendix comes with a wide variety of Widgets, but sometimes your app requires a widget outside of this set. To support a more advanced UI pattern or create project-specific interactions, you will need to make your own pluggable widget. Your new pluggable widget can be used while modeling pages alongside standard Mendix components. It can also be shared between multiple projects and distributed through the App Store.

You are in control of a pluggable widget’s appearance and behavior. Customize a pluggable widget by implementing a widget as a plain React component written in JavaScript or TypeScript. The component will be rendered in a Mendix app, and will be able to use APIs provided by Mendix to interact with that app.

Pluggable widgets, like core widgets, can have properties which a Mendix developer can (and sometimes must) configure every time the widget is used in Mendix Studio or Mendix Studio Pro. You can define these properties by making a widget definition XML file (for more information on widget definition XML files, see the Widget Definition XML File section below).

Pluggable widgets can also include a preview component for when they are rendered in Studio or previewed in Studio Pro’s Design mode.

2 Differences Between Pluggable and Custom Widgets

Pluggable widgets are the successor to Custom widgets. Pluggable widgets are based on a modern React framework, have access to better APIs in the client, and can use more advanced properties in Studio and Studio Pro. Therefore, pluggable widgets allow you to more easily implement existing front-end libraries, tools, and your own expertise. Pluggable widgets should be used instead of custom widgets whenever possible.

3 Client Component

The essential part of a pluggable widget is its client component: a React component rendered inside the end-user’s app. Creating this component requires some basic React knowledge. Read React’s tutorial if you have not worked with React before. Note that if you are building a widget to be used in Native Mobile apps, you should use React Native instead of React.

The client component is mainly focused on presentation and interaction with an end-user, while data fetching, validation, and updating are handled by the Mendix Platform. Mendix provides your component with APIs which follow a unidirectional data flow pattern, much like the Redux and Flux APIs. Mendix follows the “batteries included but removable” motto. You do not have to care about nuances if standard behavior suffices for you, but you can adjust behaviors when required.

A widget component is mounted and unmounted when a widget is shown or hidden — for example when a page is opened or due to conditional visibility. A component receives props which resemble properties described in its widget definition XML file. A prop’s key comes from the key attribute, and its value is based on the configuration of the property. Prop values are immutable, but the Mendix Platform re-renders the component passing new values when necessary.

A prop value is often not just a primitive value, but an object whose structure depends on the type of its widget’s property. A prop’s values can expose data, metadata, and associated actions — whatever is applicable for the property. Here is an example of one interface. It is a value for an action property, such as the type you would find in the On click property of an action button:

    export interface ActionValue {
        readonly canExecute: boolean;
        readonly isExecuting: boolean;
        execute(): void;
    }

The above interface could be used this way: a component uses a canExecute flag to decide whether it should be enabled, uses an isExecuting flag to show an inline progress indicator, and triggers execute() method in a reaction to user click. Normally, after execute() has been triggered, the component will be re-rendered with a new value that has the isExecuting flag set, and when an action, for example a microflow, completes, the component is re-rendered again without isExecuting.

4 Widget Package

A pluggable widget is distributed as single widget package file with an .mpk extension. This file should be placed in your project’s widgets directory. Mendix Studio Pro discovers all widgets in your project when you open your project, add a widget through the App Store, or click Project > Synchronize Project Directory.

Manually building a widget package can be difficult, so Mendix recommends you use scripts provided by the Mendix Pluggable Widget Generator. For more information on how to use a generator, see How To Build a Text Box Pluggable Widget: Part 1.

A widget package file is just a zip archive containing the following things:

  • A package.xml file describing the whole package
  • A widget definition XML file, preferably located in {widgetName}.xml where widdgetName is the last part of widget ID
  • A client component of a widget located, for example, in com/mendix/widget/MyProgressCircle.js for a widget with the ID com.mendix.widget.MyProgressCircle
  • Optionally, a widget rendering for Studio and Studio Pro’s Design mode located in {widgetDefinitionXmlName}.webmodeler.js
  • Optionally, some widget-related resources, preferably located next to the file which contains the client component
    • Note that all CSS files you add, except the one located in the lib sub-directory, will automatically be loaded in an app via the widget

Naming your widget package file after the widgetName is best practice. Also, a widget package can include multiple widgets by putting several of the above items in the same widget package. However, creating such packages is not recommended.

The package.xml file has the following structure:

	<?xml version="1.0" encoding="utf-8" ?>
	<package xmlns="http://www.mendix.com/package/1.0/">
		<clientModule name="{packageName}" version="{packageVersion}" xmlns="http://www.mendix.com/clientModule/1.0/">
			<widgetFiles>
				<widgetFile path="{widgetName}.xml"/>
			</widgetFiles>
		</clientModule>
	</package>

Both packageName and packageVersion should be aligned with the app’s information in the App Store if you wish to publish the package. It is best practice to use the widget ID as a packageName.

5 Widget Definition XML File

The widget definition XML file is an essential part of a widget because it describes that widget’s basic information and capabilities, such as if that widget can function offline. This file also contains a defined list of properties configurable in the widget. If you use the Mendix Pluggable Widget Generator, the contents of this file will be scaffolded for you.

A simple widget XML file might look like this:

    <?xml version="1.0" encoding="utf-8" ?>
    <widget [attibutes]>
        <name>{User friendly widget name}</name>
        <icon>{base64 encoded icon}</icon>
    
        <properties>
            [properties]
        </properties>
    </widget>

A widget XML file consists of three sections: widget attributes, widget description, and widget properties definition.

5.1 Widget Attributes

Here is an example of a widget’s attributes section:

    <widget
        id="com.mendix.widget.MyProgressCard"
        pluginWidget="true"
        offlineCapable="true"
        supportedPlatform="Web"
        [...]
    >

This section is generated based on options chosen while running the Mendix Pluggable Widget Generator. You will rarely need to modify it after it is generated. This sample widget features several widget attributes:

  • id — This the fully qualified name of the widget called widget ID. Using widget ID, the Mendix Platform distinguishes widgets from each other. Widget ID should never be changed after a widget is used in a project or is published in the App Store. Reverse domain-style names, as in example above, are recommended.
  • pluginWidget — This should always be set to true. This way, the Mendix Platform can distinguish between the newer pluggable widgets and the older custom widgets.
  • offlineCapable — This shows if a widget can work while an app is offline. For more information on offline apps, see the Offline-First guide. A widget that fetches information from a third-party API, for example a widget that fetches airline ticket prices, could not function without an internet connection. If a widget cannot work offline, Mendix Studio Pro and Studio will forbid its use on pages that must be available offline.
  • supportedPlatform — This shows the platforms a widget is compatible with. Web describes widgets that are only compatible with web and hybrid mobile apps. Native describes widgets that are compatible with native mobile apps.

5.2 Widget Description

After widget attributes, you will see a description of a widget that will be presented in Studio and Studio Pro. This description includes a widget name and its icon encoded as a base64 image:

	<name>My Progress Card</name>
	<icon>[image base64]</icon>

In Mendix Studio Pro, the widget described above would look like this:

basic widget

basic progress card

5.3 Widget Properties Definition

This section is represented by the properties tag in the widget XML file. It describes widget properties used in Studio and Studio Pro to configure the widget. Here is an example of a properties definition section for a widget which shows a progress card for a dashboard:

    <properties>
        <propertyGroup caption="General">
            <propertyGroup caption="Main">
                <property key="label" type="textTemplate">
                    <caption>Label</caption>
                    <description>Card label</description>
                </property>
                <property key="icon" type="icon" required="false">
                    <caption>Icon</caption>
                    <description>Card icon</description>
                </property>
                <property key="percentage" type="attribute">
                    <caption>Percentage</caption>
                    <description>Progress percentage</description>
                    <attributeTypes>
                        <attributeType name="Decimal"/>
                        <attributeType name="Integer"/>
                    </attributeTypes>
                </property>
            </propertyGroup>
            <propertyGroup caption="Action">
                <property key="showButton" type="boolean" defaultValue="false">
                    <caption>Show button</caption>
                    <description>Show button on the card</description>
                </property>
                <property key="buttonAction" type="action" required="false">
                    <caption>On click</caption>
                    <description>Action to be performed when button is clicked</description>
                </property>
                <systemProperty key="TabIndex"/>
            </propertyGroup>
        </propertyGroup>
        <propertyGroup caption="Visual">
            <propertyGroup caption="Progress bar">
                <property key="animateProgressBar" type="boolean" defaultValue="true">
                    <caption>Animate</caption>
                    <description>Show progress bar animation</description>
                </property>
                <property key="progressBarColor" type="expression" defaultValue="'red'">
                    <caption>Color</caption>
                    <description>Progress bar CSS color</description>
                    <returnType type="String" />
                </property>
            </propertyGroup>
        </propertyGroup>
    </properties>

6 Property Groups

Before examining properties themselves, it is useful to understand property groups. Property groups are formed by properties wrapped in a propertyGroup tag. Studio and Studio Pro use the property groups to render how the widget configuration UI appears in the Studios. Grouping can be used to help the modeling developer understand the configuration of a more complex widget. It is best practice to both use property groups and group properties in the Studios UI based on their purposes. The property groups from the code in Widget Properties Definition above forms the following structure:

    ├── General
    │   ├── Main
    │   │   ├── Label
    │   │   ├── Icon
    │   │   └── Percentage
    │   │
    │   └── Action
    │       ├── Show button
    │       ├── On click
    │       └── Tab index
    │
    └── Visual
        └── Progress bar
            ├── Animate
            └── Color

This is how the property group structure is represented in Studio Pro:

edit progress general

edit progress visual

properties widget

When properties are shown in a dialog box, first-level groups (General and Visual) are represented as tabs. Second-level groups (Main, Action and Progress bar) are represented as boxes. When properties are shown in a pane, first-level groups are ignored and second-level groups are shown as categories.

Note that the Common and Appearance tabs are added to your widget configuration automatically. These tabs contain properties applicable to all widgets: Name, Class, Style, and Design Properties.

7 Widget Property

Every property tag in the Widget Properties Definition has a shape similar to this:

    <property key="cardName" type="textTemplate">
        <caption>Card name</caption>
        <description>Name of the card</description>
    </property>

Some properties can or must have more attributes or tags. This depends on the type property. The following elements should be present for every property:

  • key — This element is a property’s unique, single-word identifier. The key elements are used internally to identify properties, so they should never change after a widget is used in a project or is published in the App Store. A key element also identifies a property value when it is passed to a pluggable widget’s client component.
  • type — This element is a property’s type. The type element defines which values can be configured for a property, which UI is used in the Mendix Studios, and what type of value a pluggable widget’s client component receives.
  • caption — This element is a short label identifying a property to a modeling developer. The first letter of a caption should be capitalized.
  • description — This element is a longer description of a property. A description should be capitalized and limited to one or two sentences.

Here is how a caption and description look in Studio Pro:

caption

description

8 Read More