Widgets#

Widgets allow you to customize how data of a certain DataType is entered into Arches, and further customize how that data is presented in Reports. You might have several Widgets for a given DataType, depending on how you want the Report to look or to match the context of a certain Resource.

Widgets are primarily a UI artifact, though they are closely tied to their underlying DataType.

To develop a custom Widget, you’ll need to write three separate files, and place them in the appropriate directories. For the appearance and behavior of the Widget, you’ll need a component made of a Django template and JavaScript file placed like so:

project_name/templates/views/components/widgets/sample-widget.htm project_name/media/js/views/components/widgets/sample-widget.js

To register and configure the Widget, you’ll need a JSON configuration file:

project_name/widgets/sample-widget.json

Configuring your Widget#

To start, here is a sample Widget JSON file:

{
    "name": "sample-widget",
    "component": "views/components/widgets/sample-widget",
    "defaultconfig": {
        "x_placeholder":"Longitude",
        "y_placeholder":"Latitude"
    },
    "helptext": null,
    "datatype": "sample-datatype"
}

The most important field here is the datatype field. This controls where your Widget will appear in the Arches Resource Designer. Nodes each have a DataType, and Widgets matching that DataType will be available when you’re designing your Cards. The value must match an existing DataType within Arches.

You can also populate the defaultconfig field with any configuration data you wish, to be used in your Widget’s front-end component.

Designing Your Widget#

Your Widget’s template needs to include three Django template “blocks” for rendering the Widget in different contexts within Arches. These blocks are called form, config_form, and report. As you might guess from their names, form is rendered when your Widget appears on a Card for business data entry, config_form is rendered when you configure the Widget on a card when designing a Resource, and report controls how data from your Widget is presented in a Report.

Here is an example:

{% extends "views/components/widgets/base.htm" %}
{% load i18n %}

{% block form %}
<div class="row widget-wrapper">
    <div class="form-group">
        <label class="control-label widget-input-label" for="" data-bind="text:label"></label>
        <div class="col-xs-12">
            <input type="number" data-bind="textInput: x_value, attr: {placeholder: x_placeholder}" class="form-control input-lg widget-input" style="margin-bottom: 5px">
        </div>
        <div class="col-xs-12">
            <input type="number" data-bind="textInput: y_value, attr: {placeholder: y_placeholder}" class="form-control input-lg widget-input" style="margin-bottom: 5px">
        </div>
        <div class="col-xs-12">
            <input type="text" data-bind="textInput: srid" class="form-control input-lg widget-input" style="margin-bottom: 5px">
        </div>
        <div class="col-xs-12">
            <label class="control-label widget-input-label" for="">Preview</label>
            <input disabled type="text" data-bind="textInput: preview" class="form-control input-lg widget-input">
        </div>
    </div>
</div>
{% endblock form %}

{% block config_form %}
<div class="control-label">
    {% trans "X Coordinate Placeholder" %}
</div>
<div class="col-xs-12 crud-widget-container">
    <input type="" placeholder="{% trans "Placeholder" %}" id="" class="form-control input-md widget-input" data-bind="textInput: x_placeholder">
</div>
<div class="control-label">
    {% trans "Y Coordinate Placeholder" %}
</div>
<div class="col-xs-12 crud-widget-container">
    <input type="" placeholder="{% trans "Placeholder" %}" id="" class="form-control input-md widget-input" data-bind="textInput: y_placeholder">
</div>
{% endblock config_form %}

{% block report %}
<dt data-bind="text: label"></dt>
<dd>
  <div style='margin-bottom:2px' data-bind="text: value"></div>
</dd>
{% endblock report %}

To pull it all together, you’ll need to write a complementary JavaScript file. The Arches UI uses Knockout.js, and the best way to develop your Widget in a compatible way is to write a Knockout component with a viewModel corresponding to your Widget’s view (the Django template).

Here is an example, continuing with our sample-widget:

define([
    'knockout',
    'underscore',
    'viewmodels/widget',
    'templates/views/components/widgets/sample-widget.htm'
], function (ko, _, WidgetViewModel, sampleWidgetTemplate) {
    /**
    * registers a text-widget component for use in forms
    * @function external:"ko.components".text-widget
    * @param {object} params
    * @param {string} params.value - the value being managed
    * @param {function} params.config - observable containing config object
    * @param {string} params.config().label - label to use alongside the text input
    * @param {string} params.config().placeholder - default text to show in the text input
    */
    return ko.components.register('sample-widget', {
        viewModel: function(params) {
            params.configKeys = ['x_placeholder','y_placeholder'];
            WidgetViewModel.apply(this, [params]);
            var self = this;
            if (this.value()) {
                var coords = this.value().split('POINT(')[1].replace(')','').split(' ')
                var srid = this.value().split(';')[0].split('=')[1]
                this.x_value = ko.observable(coords[0]);
                this.y_value = ko.observable(coords[1]);
                this.srid = ko.observable('4326');
            } else {
                this.x_value = ko.observable();
                this.y_value = ko.observable();
                this.srid = ko.observable('4326');
            };

            this.preview = ko.pureComputed(function() {
                var res = "SRID=" + this.srid() + ";POINT(" + this.x_value() + " " + this.y_value() + ")"
                this.value(res);
                return res;
            }, this);
        },
        template: sampleWidgetTemplate,
    });
});

Registering your Widget#

After placing your Django template and JavaScript files in their respective directories, you are now ready to register your Widget:

python manage.py widget register --source /Documents/projects/mynewproject/mynewproject/widgets/sample-widget.json

The command will confirm your Widget has been registered, and you can also see it with:

python manage.py widget list

If you make an update to your Widget, you can load the changes to Arches with:

python manage.py widget update --source /Documents/projects/mynewproject/mynewproject/widgets/sample-widget.json

All the Widget commands are detailed in Command Line Reference - Widget Commands.