Help! Accessing Multiple Wb View Bindings On Web Widget

Has anyone had experience accessing multiple Wb View Bindings on a web widget? By default, doLoad() has access to the first Wb View Binding. I found this post on the Niagara Community where option 3, described by JJ, sounds like what I’m after. However, I’m struggling to figure out how this pieces together.

I’ve started with the most basic example MyFirstWidget from the Tridium tutorial.

This is the code before any changes:

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

  'use strict';

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

    /**
     * Describe how your `Widget` does its initial setup of the DOM.
     *
     * @param {JQuery} dom - The DOM element into which to initialize this `Widget`
     */
    doInitialize(dom) {
      const initialValue = 'value goes here';

      // when building HTML directly, remember to perform proper escaping to prevent XSS vulnerabilities.
      // _.escape() is only one of many ways to do this. Calling .text() instead of .html() on a
      // jQuery object is another.
      dom.html(`<input type="text" value="${ _.escape(initialValue) }" >`);
    }

    /**
     * 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`.
     */
    doLoad(ramp) {
      const update = () => {
        this.jq().children('input').val(ramp.getOut().getValueDisplay());
      };

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

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

Big thanks to @Rosenthaler who put this solution together.

The main point being the implementation of BICollectionSupport.


package com.jstest.jstest.ux;

import com.tridium.web.BICollectionSupport;

import javax.baja.naming.BOrd;
import javax.baja.nre.annotations.NiagaraSingleton;
import javax.baja.nre.annotations.NiagaraType;
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;

@NiagaraType
@NiagaraSingleton
public class BJsTestWidget  extends BSingleton implements BIJavaScript, BIFormFactorMax, BICollectionSupport
{
//region /*+ ------------ BEGIN BAJA AUTO GENERATED CODE ------------ +*/
//@formatter:off
/*@ $com.jstest.jstest.ux.BJsTestWidget(2747097003)1.0$ @*/
/* Generated Mon Aug 19 22:46:02 CEST 2024 by Slot-o-Matic (c) Tridium, Inc. 2012-2024 */

  public static final BJsTestWidget INSTANCE = new BJsTestWidget();

  //region Type

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

  //endregion Type

//@formatter:on
//endregion /*+ ------------ END BAJA AUTO GENERATED CODE -------------- +*/



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

    private static final JsInfo jsInfo =
            JsInfo.make(BOrd.make("module://jsTest/rc/JsTestWidget.js"));

}


/**
 * A module defining `JsTestWidget`.
 *
 * @module nmodule/jsTest/rc/JsTestWidget
 */
define([ 'bajaux/Widget', 'jquery', 'Promise', 'nmodule/webEditors/rc/wb/util/ICollectionSupport' ], 
function (Widget, $, Promise, ICollectionSupport) {

  'use strict';

  /**
   * Description of your widget.
   *
   * @class
   * @extends module:bajaux/Widget
   * @alias module:nmodule/jsTest/rc/JsTestWidget1
   */
  var JsTestWidget = function JsTestWidget(params) {
    var that = this,
      options;
    Widget.call(that, {
      params: params
    });
    ICollectionSupport(this);
    that.$firstOrd = null;
    that.$lastOrd = null;
  };

  //extend and set up prototype chain
  JsTestWidget.prototype = Object.create(Widget.prototype);
  JsTestWidget.prototype.constructor = JsTestWidget;

  /**
   * Describe how your widget does its initial setup of the DOM.
   *
   * @param {jQuery} element the DOM element into which to load this widget
   */
  JsTestWidget.prototype.doInitialize = function (dom) {
    dom.html(`
        <div>
            <label>Binding 1:</label>
            <input type="text" class="binding-value1" placeholder="Binding 1">
        </div>
        <div>
            <label>Binding 2:</label>
            <input type="text" class="binding-value2" placeholder="Binding 222">
        </div>
    `);
    console.log('Initialized');
  };

  /**
   * Describe how your widget loads in a value.
   *
   * @param value description of the value to be loaded into this widget
   */
  JsTestWidget.prototype.doLoad = function (value) {
    this.jq().find('.binding-value1').val(String(this.$firstOrd));
    this.jq().find('.binding-value2').val(String(this.$lastOrd));
  };

  /**
   * Resolve the data to something useful.
   * 
   * @param {String|baja.Ord} data The data to resolve
   * 
   * @returns {Promise}
   */
  JsTestWidget.prototype.resolve = function (data, resolveParams) {
    var that = this,
        dataAsString = String(data);
    that.$lastOrd = dataAsString;

    if (!that.$firstOrd) {
      that.$firstOrd = dataAsString;
    } // Check whether we need to skip ORD resolution in that particular case.

    return Widget.prototype.resolve.apply(that, arguments);
  };

  /**
   * Describe what kind of data you can read out of this widget.
   *
   * @returns {Promise} promise to be resolved with the current value
   */
  JsTestWidget.prototype.doRead = function () {
    return Promise.resolve(this.jq().find('input').val());
  };

  return JsTestWidget;
});

1 Like