Configuration Structure

Configuration structure allows you to define an expected shape of your configuration and Valence will handle creating the UI and getting values from users. It is mutually exclusive with using a custom Lightning component.

Each Valence interface relating to configuration has a method that asks for your “configuration structure”. You return null if you’re not using configuration structure, or a special JSON string if you are.

Valence will use the JSON you return from this method to dynamically instantiate a form for the user to fill out.

At the bottom of this page you’ll read about a helper class that can build this JSON for you, but let’s begin by exploring the JSON shape so you understand how it works.

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 Structure 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
            }
        }
    ]
}

Configuration Structure Builder

Valence comes with a fluent builder class to help you construct a configuration structure to return to Valence.

Definition

/**
 * Makes it easier to set up dynamic configurations for Valence extensions.
 */
global with sharing class DynamicUIConfigurationBuilder {

        global static DynamicUIConfigurationBuilder create(String description);

        global static DynamicField createField(String name);

        global DynamicUIConfigurationBuilder addField(DynamicField newField);

        global String finalize();

        global class DynamicField {

                global DynamicField addAttribute(String key, Object value);

                global DynamicField withComponentType(String componentType);
        }
}

Example Usage

public String getSourceConfigurationStructure(valence.LinkContext context) {

        return valence.DynamicUIConfigurationBuilder.create('This is a configuration that offers you some choices about how this adapter is going to prepare your breakfast.')
                .addField(
                        valence.DynamicUIConfigurationBuilder.createField('eggPreference')
                        .addAttribute('label', 'How do you like your eggs?')
                )
                .addField(
                        valence.DynamicUIConfigurationBuilder.createField('baconPreference')
                        .addAttribute('label', 'Do you want bacon on the side?')
                        .addAttribute('type', 'checkbox')
                        .addAttribute('checked', true)
                )
                .finalize();
}