Module: bajaux/spandrel

API Status: Development


(require("bajaux/spandrel"))(arg [, params])

The purpose of spandrel is to provide a reasonably pure-functional,
diffable method of defining a nested structure of bajaux Widgets and
supporting HTML. Rather than require Widget implementors to manually code
calls to initialize() or buildFor(), spandrel allows you to provide
your desired structure of HTML elements and their associated Widget
instances, and handle the work of updating the document as that structure
may change over time.

See Building Composite Widgets With spandrel for in-depth information.

Parameters:
Name Type Argument Default Description
arg module:bajaux/spandrel~SpandrelArg
params object <optional>
{}

params

Properties
Name Type Argument Description
extends function <optional>

optionally specify a Widget superclass to extend

manager module:bajaux/lifecycle/WidgetManager <optional>

optionally provide your own WidgetManager to manage Widget lifecycle

Since:
  • Niagara 4.10
Returns:

a Widget constructor

Type
function
Examples

Generate a static widget

const StaticWidget = spandrel([
  '<label>Name: </label>',
  '<input type="text" value="{{ props.name }}">',
  {
    dom: '<span></span>',
    value: false,
    properties: 'inherit'
  }
]);
return fe.buildFor({
  dom: $('#myStaticWidget'),
  type: StaticWidget,
  properties: { name: 'Logan', trueText: 'Good', falseText: 'Not So Good' }
});

Generate a dynamic widget with a field editor for each slot

const DynamicWidget = spandrel(comp => comp.getSlots().toArray().map(slot => ({
  dom: '<div class="componentSlot"/>',
  kids: [
    `<label>${ slot.getName() }: </label>`,
    { dom: '<span/>', complex: comp, slot: slot }
  ]
})));

return fe.buildFor({
  dom: $('#myDynamicWidget'),
  type: DynamicWidget,
  value: myComponent
});

Subclass an existing dynamic spandrel widget, making changes before rendering.

// our superclass will render a <label> element, with a background
// determined by a widget property.
const LabelWidget = spandrel((value, { properties }) => {
  const label = document.createElement('label');
  label.innerText = value;
  label.style.background = properties.background || '';
  return label;
});

const RedLabelWidget = spandrel((value, { renderSuper }) => {

  // renderSuper will call back to the superclass, allowing your subclass
  // to edit the data before spandrel renders it to the page.
  //
  // you can optionally pass a function to renderSuper that will tweak the
  // widget state before the superclass renders its data. if no tweaking is
  // desired, just renderSuper() is fine.
  //
  return renderSuper((state) => {
    state.properties.background = 'lightpink';

    // remember to return the new state.
    return state;
  })
    .then((label) => {
      // renderSuper will resolve the data exactly as rendered by the
      // superclass.
      label.style.color = 'red';
      return label;
    });
}, { extends: LabelWidget });

Members


<static> jsx

Use spandrel.jsx as your JSX pragma to convert your JSX into spandrel
config.

See: