MxBlog

Howto - A simple Mendix 5 widget

A quick example of a simple custom widget for Mendix. Mendix widgets are built on top of the Dojo framework, so for more background you can check the Dojo manuals.

This post shows two example widgets:

To create a custom widget you need to open your Mendix project in some editor other than the Mendix Modeler. You can use a regular text editor or some (Javascript) IDE.

The following screenshots shows the project opened in IntelliJ.

Mendix project opened in Intellij

The project contains a number of folders, widgets go into the widgets folder. This folder contains a number of packaged widgets, .mpk files. It also contains a number of source folders for the widgets.

You create your widget by creating the required folder structure, and then packaging them into a .mpk file using a zip tool. At the end of this post an example powershell script illustrates how you can create the .mpk file.

Package.xml

The first thing you need to create is package.xml file, specifying which widget files exist in your project. The following example contains two entries, one for the static html fragment, and one for the dynamic html fragment widget.

<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://www.mendix.com/package/1.0/">
    <clientModule name="HtmlFragment" version="0.1" xmlns="http://www.mendix.com/clientModule/1.0/">
        <widgetFiles>
            <widgetFile path="HtmlFragment/HtmlFragment.xml"></widgetFile>
            <widgetFile path="HtmlFragment/StaticHtmlFragment.xml"></widgetFile>
        </widgetFiles>
        <files>
            <file path="HtmlFragment/"/>
        </files>
    </clientModule>
</package>

Static content widget

Every widget needs an xml file specifying some parameters of the widget, for example name and description.

The attribute needEntityContext specifies if the widget uses data from an entity. In this case it doesn't need any data, as we'll just fill in the required html in the property editor in the Mendix Modeler.

Finally there's a properties section where you specify the parameters for your widgets that can the user will see in the properties sheet. In this case the property name is htmlContent, and the type of the property is a string.

<?xml version="1.0" encoding="utf-8"?>
<widget xmlns="http://www.mendix.com/widget/1.0/"
        id="HtmlFragment.widget.StaticHtmlFragment"
        needsEntityContext="false">
    <name>StaticHtmlFragment</name>
    <description>StaticHtmlFragment</description>
    <icon></icon>
    <properties>
        <property key="htmlContent" type="string">
            <caption>HtmlContent</caption>
            <category>HtmlFragment</category>
            <description>Html content</description>
        </property>
    </properties>
</widget>

Next the actual javascript code of the widget. The first parameter of dojo.declare should be the same as the widget id in the previous xml file. In the postCreate method, the input parameter htmlContent is set as the html inside the domnode of your widget.

console.log("StaticHtmlFragment.js");
dojo.declare("HtmlFragment.widget.StaticHtmlFragment", mxui.widget._WidgetBase, {
        inputargs: {
            htmlContent: "",
        },
        postCreate: function () {
            console.log("StaticHtmlFragment.js - postCreate");
            this.domNode.innerHTML= this.htmlContent;
            this.actLoaded();
        },
});
console.log("StaticHtmlFragment.js - init done");

Dynamic content widget

The dynamic widget, which will put the value of an entity attribute in your page, differs only slightly from the static widget. First you need to set needsEntityContext to true. The property htmlContent should contain an attribute name that refers to the attribute of entity from which the data should be used, so the type of the property is attribute.

<?xml version="1.0" encoding="utf-8"?>
<widget xmlns="http://www.mendix.com/widget/1.0/"
        id="HtmlFragment.widget.HtmlFragment"
        needsEntityContext="true">
    <name>HtmlFragment</name>
    <description>HtmlFragment</description>
    <icon></icon>
    <properties>
        <property key="htmlContent" type="attribute">
            <caption>HtmlContent</caption>
            <category>HtmlFragment</category>
            <description>Html content</description>
            <attributeTypes>
                <attributeType name="String"/>
            </attributeTypes>
        </property>
    </properties>
</widget>

The javascript for this widget contains an additional method, update, which is called after the value of the entity has changed, meaning the widget needs to update the data it is displaying.

The update method receives the entity as its first parameter, we can get the value of an attribute of the entity using the get method. Once we have this data, we insert it into the dom element as before.

console.log("HtmlFragment.js");
dojo.declare("HtmlFragment.widget.HtmlFragment", mxui.widget._WidgetBase, {
        inputargs: {
            htmlContent: "",
        },
        postCreate: function () {
            console.log("HtmlFragment.js - postCreate");
            this.actLoaded();
        },
        update: function(obj, callback){
            console.log("HtmlFragment.js - update");
            content = obj.get(this.htmlContent);
            this.domNode.innerHTML= content;
            callback && callback();
        },
    });
console.log("HtmlFragment.js - init done");

building the package

Now that we have all the source files we need to build the mpk file. This is a zip file, so you can automate this process using the following script:

& rm -Force ..\HtmlFragment.mpk
& "c:\Program Files\7-Zip\7z.exe" -tzip a ..\HtmlFragment.mpk .\* .\*.xml

Using the widget in the Mendix Modeler

Now you can start using the widgets in the Mendix modeler. Press F4 to reload the widget file. If your widget package is ok, you'll see the widget in the Add-on menu in the page editor. You can select the widget and place it on your page. Fill in the properties and you're done.

Form editor

If you need more examples you can download existing widgets from the Mendix app-store. Also, more documentation can be found in the reference guide.