Stepped Configuration

Stepped configuration allows a connector to dynamically populate the connector configuration based on user-provided answers. For example, populating a "City" dropdown after a "State" dropdown is selected.

Using stepped config

Requirements

This guide assumes you are already familiar with Community Connector configurations. See define configuration via getConfig for a refresher.

Overview

Stepped configuration consists of Data Studio calling getConfig() multiple times, and your connector returning more configuration questions each time. Each call to getConfig() will include the user's answers to the last getConfig() response. This process is continued as long as you return a response with setIsSteppedConfig(true).

Guidelines

Set setIsSteppedConfig(true) until the configuration is complete
Data Studio will repeatedly call getConfig() as long as setIsSteppedConfig(true) is set.Once configuration is complete, the final getConfig() response should set setIsSteppedConfig(false).
Set isDynamic(true) for configuration questions that determine later questions
If a field marked isDynamic is modified by the user, subsequent configuration entries will be cleared in the UI, and the user will need to configure all subsequent steps. This helps ensure users don't send you an invalid configuration.
User-provided answers will be passed via request.configParams.

request.configParams will be undefined for the first getConfig() request to your connector. Subsequent requests will include the user-provided answers as an object keyed by the configuration ids or undefined if the user doesn't provide any answers.

Example:

{
  state: 'CA',
  city: 'mountain_view'
}
Configurations are additive

New configuration questions should be added after existing ones.

Configurations cannot be mutated

If a configuration question was asked previously, it should be present for all subsequent calls. For example, if configuration question A was asked in the first call to getConfig(), A should be included in all future responses.

Configurations are idempotent

Calls to getConfig() with the same configParams should return the same configuration.

Dynamic parameters cannot be overridable

Data Studio will not allow dynamic configuration parameters to be overridden.

Example configurations

Dynamic dropdowns

This first question prompts a user to select a state, then dynamically provides a city dropdown based on the selected state.

var cc = DataStudioApp.createCommunityConnector();

function optionsForState(state) {
  switch (state) {
    case "IL": {
      return [["Chicago", "chicago"], ["Springfield", "springfield"]];
    }
    case "CA": {
      return [["Mountain View", "mountain_view"], ["Los Angeles", "los_angeles"]];
    }
    default: {
      cc.newUserError()
          .setText('You must either select "IL" or "CA"')
          .throwException();
    }
  }
}

function getConfig(request) {
  var configParams = request.configParams;
  var isFirstRequest = configParams === undefined;
  var config = cc.getConfig();
  if (isFirstRequest) {
    config.setIsSteppedConfig(true);
  }

  config.newSelectSingle()
      .setId("state")
      .setName("State")
  // Set isDynamic to true so any changes to State will clear the city
  // selections.
      .setIsDynamic(true)
      .addOption(config.newOptionBuilder().setLabel("Illinois").setValue("IL"))
      .addOption(config.newOptionBuilder().setLabel("California").setValue("CA"));

  if (!isFirstRequest) {
    var city = config.newSelectSingle()
        .setId("city")
        .setName("City");
    var cityOptions = optionsForState(configParams.state);
    cityOptions.forEach(function(labelAndValue) {
      var cityLabel = labelAndValue[0];
      var cityValue = labelAndValue[1];
      city.addOption(config.newOptionBuilder().setLabel(cityLabel).setValue(cityValue));
    });
  }
  return config.build();
}

Branching Paths

This will ask an additional question if the selected "Country" is "USA".

var cc = DataStudioApp.createCommunityConnector();

function getConfig(request) {
  var configParams = request.configParams;
  var isFirstRequest = configParams === undefined;
  var config = cc.getConfig();
  if (isFirstRequest) {
    config.setIsSteppedConfig(true);
  }

  config
      .newSelectSingle()
      .setId('country')
      .setName('Country')
  // Set isDynamic to true so any changes to Country will clear the state
  // selections.
      .setIsDynamic(true)
      .addOption(config.newOptionBuilder().setLabel('United States').setValue('USA'))
      .addOption(config.newOptionBuilder().setLabel('Canada').setValue('CA'));

  if (!isFirstRequest) {
    // validate a valid value was selected for configParams.country
    if (configParams.country === undefined) {
      cc.newUserError().setText('You must choose a country.').throwException();
    }
    switch (configParams.country) {
      case 'USA': {
        config
            .newSelectSingle()
            .setId('state')
            .setName('State')
            .addOption(config.newOptionBuilder().setLabel('New York').setValue('NY'))
            .addOption(config.newOptionBuilder().setLabel('Calfornia').setValue('CA'));
        break;
      }
      case 'CA': {
        // No additional configuration is needed for Canada.
        break;
      }
      default: {
        cc.newUserError()
            .setText('You must either select "CA" or "USA"')
            .throwException();
      }
    }
  }
  return config.build();
}