Using Dynamic Configurations in your Extension

In certain places in Valence we allow you to define a configuration schema that Valence parses and uses to render a UI for the user to do the configuration.

Typically, you have three levels of configurability available to your custom adapters and filters, listed below from least sophisticated to most sophisticated:

  1. No configuration necessary.
  2. Configuration schema defined, automatically turned into a UI by Valence with the user-defined values stored and sent back to your extension when Links are running.
  3. Custom UI component delivered by your extension and embedded inside the Valence app; configuration obtained from your UI by Valence, stored and sent back to your extension when Links are running.

By default extensions are not configurable. You can change this (and indicate that your extension can be configured) by implementing one of these interfaces:

Adapter interfaces:

Filter interfaces:

Note

No matter which configuration option you pick, you do not have to manage any kind of interaction with the data store. Your configuration data will be passed back and forth between you and the Valence framework, and Valence will take care of serializing configurations and giving them back to you again later at the appropriate time.

Configuration Schema

Configuration Schema allows you to define an expected shape of your configuration and Valence will handle creating the UI and getting values from users.

Warning

Configuration Schema and Custom UI Component are mutually exclusive. Either you are responsible for the UI, or Valence is. If you go with Configuration Schema you will return a value from getConfigurationStructure() and return null from getConfigurationLightningComponent().

Valence will expect a serialized JSON string to be returned by getConfigurationStructure(). The framework uses this structure to dynamically instantiate a form for the user to fill out.

Expected Structure

The shape Valence expects has two properties:

{
    "description" : "A description for the user to read about how to go about configuring your extension. Shown at the top of the screen.",
    "fields" : [
        { ... a field object ... },
        { ... another field object ... }
    ]
}

description [required]

Instructions that will be shown to the User alongside a form. These instructions should explain overall what the User needs to do to fill out the configuration fields appropriately, and anything else they might need to know or be aware of.

fields [required]

An array of fields, each one representing a value that a User could potentially fill in.

Field Shape

A field object represents a single value that the user might set.

{
    "name" : "short name for your field",
    "attributes" : {
        "maxlength" : 15
    },
    "componentType" : "lightning:input"
}

name [required]

The field name for this value. This is important, and required. This is the name we will serialize as the key against whatever value the user provides.

attributes (optional)

These are injected straight into the component when it is instantiated. Any attributes that are defined on the componentType can be set here (with the exception of value). For example, you could set a maxlength or perhaps some validation. Using this in combination with componentType lets you use any base or custom component you might need, and send appropriate settings to that component.

componentType (optional)

By default we will render a lightning:input base component for the user to interact with. You can override this value and render some other base component, or even custom components if you really wanted to.

Configuration Schema Example

Here’s an example of a schema configuration you could return to Valence.

{
    "description" : "This is a configuration that offers you some choices about how this adapter is going to prepare your breakfast.",
    "fields" : [
        {
            "name" : "eggPreference",
            "attributes" : {
                "label" : "How do you like your eggs?"
            }
        },
        {
            "name" : "baconPreference",
            "attributes" : {
                "label" : "Do you want bacon on the side?",
                "type" : "checkbox",
                "checked" : true
            }
        }
    ]
}

Custom UI Component

If you would like to use your own custom Lightning component to render a user experience to configure your extension, return the fully qualified name of your component from the getConfigurationLightningComponent() method.

Warning

Configuration Schema and Custom UI Component are mutually exclusive. Either you are responsible for the UI, or Valence is. If you go with Custom UI Component you will return a fully qualified Lightning component name from getConfigurationLightningComponent() and return null from getConfigurationStructure().

Example

public String getConfigurationLightningComponent() {
    return 'yourPackageNamespace:SomeLightningConfigurator';
}

Your Lightning component must implement a Lightning Interface called “valence:Configurator”.

valence:Configurator Interface

<aura:interface description="Implementors of this interface can be instantiated in the Valence UI so Users can configure their adapters, filters, etc.">
    <aura:attribute name="link" type="Object" description="Information about the Link that may prove useful during configuration." />
    <aura:attribute name="configuration" type="Object" description="The configuration object. Valence will load and persist this for you." />
    <aura:attribute name="isValid" type="Boolean" description="A flag to indicate if the configuration is allowed to be saved." />
    <aura:attribute name="isDirty" type="Boolean" description="A flag to indicate if the configuration has been modified." />
</aura:interface>

All four of these attributes will be passed to your component when it is instantiated. Here’s how they work:

Configuration

This is your configuration that will be stored in the database and given to your extension during Link runtime. Valence serializes this object as a JSON string and that string is what you are given in the setConfiguration() Apex method during Link execution.

For the purposes of your custom UI, you do not have to worry about getting an existing configuration out of the database, or persisting a new or updated one back to the database. This is all handled by Valence. If an existing configuration exists, it will be passed to your component at instantiation inside this attribute, otherwise you’ll be given an empty object. Modify this object to your heart’s content, and when the user eventually clicks the Save button your configuration will be serialized and stored.

isValid

Use this third attribute to control the user’s ability to save the configuration. As long as it is set to false, the user’s Save button that they see in the top right corner will be disabled. Set this to true whenever the user has done whatever you feel is necessary to get your configuration into a valid state. Don’t hesitate to toggle this on and off as the user makes changes.

isDirty

Use this fourth attribute to control the user’s ability to save the configuration. As long as it is set to false, no action buttons (Save/Discard) will be shown to the User. Set this to true whenever the User makes changes to the configuration that cause it to be different than what they started with. Don’t hesitate to toggle this on and off as the user makes changes.