MicroStrategy ONE

Advanced Functionality: Implement a Middle Layer for the React Format Panel

This feature is available starting in MicroStrategy 2021 Update 3.

Custom visualizations can be created by just using the default property access API to cover most uses. However, you can also define customized query and apply functions to provide extra logic when handling property access. This is called the middle layer, because it sits between react and mojo, but it's basically just two functions:

  • function query(key)
    The query function, invoked when a component needs to query a value for specific key.

  • function apply(key, value)

    The apply callback, invoked when interaction happens within a component that bonds to the key.

The main workflow within the two functions is just a switch (key) statement, so each key is handled separately. The code sample below defines the code template to implement the two functions.

Copy
function getQuery(host, editorModel) { // return query function
    return function (prop) {
        switch (prop) {
        case 'prop1':
            break;
        case 'prop2':
            break;
        default:
            return { value: host.readProperty(prop), };
        }
    };
}

function getApply(host, editorModel) { // return onChange callback
    return function (prop, value) {
        switch (prop) {
        case 'prop1':
            break;
        case 'prop2':
            break;
        default:
            host.setProperty(prop, value);
        }
    };
}

Customized query and apply functions are also supported for imported visualizations. Here is the corresponding template code for config.js:

Copy
// config object
const config = {
  tagName: 'Button',
  key: 'helloButton',
};

// properties array
const properties = ['helloButton'];

// the query function
const query = (host, key) => {
  // default values
  let value = null;
  let enable = true;
  let visible = true;

  // special handling when reading each key
  switch (key) {
  case 'helloButton':
      value = 'Hello world';
      break;
  // default handling of ordinary key
  default:
      value = host.getProperty(key);
  }

  return { value, enable, visible };
}

// the apply function
const apply = (host, key, value) => {
  // auto refresh by default
  let autoRefresh = {
      suppressData: true,
      callback: () => host.refresh();
  }
  // auto persist by default
  let autoPersist = true;

  // special handling when writing each key
  switch (key) {
  case 'helloButton':
      console.log('property write: ', key, value);
      autoRefresh = null; // don't want to auto refresh
      autoPersist = false; // don't want to auto persist
      break;
  }

  if (autoPersist) {
    host.savePropertyAndUpdateWidget(key, value, autoRefresh);
  }
}

export { config, properties, query, apply };

Inside the query and apply functions, you can implement your own read/write logic. There are two APIs provided by the framework that you can use:

  • host.getProperty(propertyName)

    Used to read the propertyName value from the metadata.

  • host.savePropertyAndUpdateWidget(propertyName, value, autoRefresh)
    Used to write the propertyName value to the metadata.