Getting Started - MyFirstWidget

In this first tutorial, we're going to create a new Niagara Module with a very
simple Widget that simply displays the value of a Ramp Component from the
kitControl palette. This View will render seamlessly in both Workbench and Hx.

Outline

Our new Niagara Module will have the following directory structure:

+- myFirstModule
   +- myFirstModule-ux
      +- src
      |  +- com
      |  |  +- companyname
      |  |     +- myFirstModule
      |  |        +- ux
      |  |           +- BMyFirstWidget.java
      |  +- rc
      |     +- MyFirstWidget.js
      +- module-include.xml
      +- myFirstModule-ux.gradle
  • All of the code for a bajaux Widget goes into the -ux module subdirectory.
    (Workbench and Hx Views belong in -wb)

    • BMyFirstWidget.java: a Java class to register our JavaScript with the
      Niagara Framework.
    • MyFirstWidget.js: the JavaScript bajaux Widget.
    • module-include.xml: declares type information and registers the Widget as
      a View on kitControl's Ramp Component.
    • myFirstModule-ux.gradle: used to build the JAR file.

MyFirstWidget.js

/**
 * A module defining `MyFirstWidget`.
 *
 * @module nmodule/myFirstModule/rc/MyFirstWidget
 */
define(['bajaux/mixin/subscriberMixIn',
        'bajaux/Widget'], function (
        subscriberMixIn,
        Widget) {

  'use strict';

  /**
   * An editor for working with `kitControl:Ramp` instances. 
   *
   * @class
   * @extends module:bajaux/Widget
   * @alias module:nmodule/myFirstModule/rc/MyFirstWidget
   */
  var MyFirstWidget = function () {
    Widget.apply(this, arguments);
    subscriberMixIn(this);
  };

  // Extend and set up prototype chain
  MyFirstWidget.prototype = Object.create(Widget.prototype);
  MyFirstWidget.prototype.constructor = MyFirstWidget;

  /**
   * Describe how your `Widget` does its initial setup of the DOM.
   * 
   * @param {jQuery} dom - The DOM element into which to load this `Widget`
   */
  MyFirstWidget.prototype.doInitialize = function (dom) {
    dom.html('<input type="text" value="value goes here" />');
  };

  /**
   * Describe how your `Widget` loads in a value.
   * 
   * Thanks to `subscriberMixIn`, we can subscribe to changes to the Ramp
   * component to ensure that the DOM is always kept up to date.
   *
   * @param {baja.Component} ramp - an instance of `kitControl:Ramp`.
   */
  MyFirstWidget.prototype.doLoad = function (ramp) {
    var input = this.jq().find('input');

    function update() {
      input.val(ramp.getOut().getValueDisplay());
    }

    // Call update whenever a Property changes
    this.getSubscriber().attach('changed', update);

    // Call update for the first time.
    update();
  };

  return MyFirstWidget;
});

Even if you're new to JavaScript, this code shouldn't look too strange to you.
It simply loads a Niagara value into a JavaScript Widget...

  • The JavaScript code is wrapped in a 'define' function. This is how we write
    modular JavaScript code.

  • The JavaScript defines a new MyFirstWidget constructor that extends from
    Widget.

  • doInitialize injects some HTML when the Widget is created.

    • The dom object being passed in is a DOM element embedded in a
      jQuery wrapper.
  • doLoad updates the HTML when the ramp is passed into the Widget.

    • The value is a subscribed BajaScript proxy Component of the Ramp that sits
      in the Station. It's already subscribed because the Widget uses a
      SubscriberMixIn.
    • The value will be automatically unsubscribed when the Widget is destroyed.
    • The SubscriberMixIn automatically adds the
      getSubscriber method to the Widget. This is used to attach a listener for
      changed events.
    • Every time a property on the Ramp Component changes, the update method
      will be called to update the user interface.

BMyFirstWidget.java

package com.mycompany.myFirstModule.ux;

import javax.baja.naming.BOrd;
import javax.baja.sys.BSingleton;
import javax.baja.sys.Context;
import javax.baja.sys.Sys;
import javax.baja.sys.Type;
import javax.baja.web.BIFormFactorMax;
import javax.baja.web.js.BIJavaScript;
import javax.baja.web.js.JsInfo;

public final class BMyFirstWidget
    extends BSingleton
    implements BIJavaScript, BIFormFactorMax
{
  private BMyFirstWidget() {}
  public static final BMyFirstWidget INSTANCE = new BMyFirstWidget();

  @Override
  public Type getType() { return TYPE; }
  public static final Type TYPE = Sys.loadType(BMyFirstWidget.class);

  public JsInfo getJsInfo(Context cx) { return jsInfo; }

  private static final JsInfo jsInfo =
      JsInfo.make(BOrd.make("module://myFirstModule/rc/MyFirstWidget.js"));
}
  • This Java class is used just to inject the MyFirstWidget.js JavaScript
    Widget into Niagara. The Widget itself is all written in JavaScript.

  • The class implements javax.baja.web.js.BIJavaScript that marks the class up
    as one that has JavaScript associated with it.

  • The class implements javax.baja.web.BIFormFactorMax so it renders as a View
    in Workbench and Hx.

  • The class extends javax.baja.sys.BSingleton so a new instance of it doesn't
    need to be created each time.

module-include.xml

Declare BMyFirstWidget as an agent on kitControl:Ramp to register the
Widget as a View on the Ramp Component.

<types>
  <type class="com.companyname.myFirstModule.ux.BMyFirstWidget" name="MyFirstWidget">
    <agent>
      <on type="kitControl:Ramp"/>
    </agent>
  </type>
</types>

myFirstModule-ux.gradle

Add the following to the gradle file to ensure all relevant JavaScript files
are included in the built module...

jar {
  from('src') {
    include 'rc/**/*.js'
    exclude 'rc/**/*.built.js'
    include 'rc/**/*.hbs'
    include 'rc/**/*.css'
  }
}

Results

Building this module will result in the Ramp Component having a new pure HTML5
View available in both Workbench and Hx...

  • The same code is used in both Workbench and Hx environments.
  • As it's a View, it can be accessed directly or added to a Px page.
  • The code for the Widget is embedded in a distributable JAR file.

Next

See our Saving Modifications to Station
tutorial.