Dynamic Dropdown Options

In this section you will learn how to make the dropdown options dynamic.

In addition to providing a fixed array of valid options in the code snippet, it is also possible to dynamically pick the options to be shown in the dropdown. These options will be retrieved when the user clicks a cell in the dropdown-controlled column and can be determined in any way. Rather than providing an array for the `validOptions` attribute, it’s also possible to provide a function. This function has the following signature:

(rowValues: (string | null)[]) => Promise<string[]>

The single argument, `rowValues`, contains all of the current user-provided and generated fields for the output row that the user has selected.

Here’s an example of a code snippet with two fields that builds upon the first. It uses the existing “Payment Type” field from above, but adds on an additional “Payment Provider” column that should contain the issuer of the credit or debit card if the purchase was made using a card:

{
 name: 'a',
 displayName: 'Payment Type',
 description:
   'The medium of payment which was used to complete the transaction',
 validOptions: ['cash', 'credit', 'debit', 'paypal'],
},
{
 name: 'b',
 displayName: 'Payment Provider',
 description:
   'If the payment was made using a credit or debit card, contains the provider of that card',
 validOptions: async (rowValues) => {
   const paymentType = rowValues[0];
 
   // If the user hasn't yet filled out the first column, do not let them populate this field yet
   if (!paymentType) {
     return [];
   }
 
   // If the payment wasn't made with a card, force the user to fill this field with "N/A"
   if (paymentType !== 'credit' && paymentType !== 'debit') {
     return ['N/A'];
   }
 
   // Allow the user to pick from the set of available card providers
   return [
     'Discover',
     'Visa',
     'MasterCard',
     'Chase',
     'American Express'
   ];
 },
 // If the card provider is other than the list we have available, allow the user to pick a custom option for this field and override the dropdown options we present them with
 allowCustomOptions: true,
}

In this scenario, the “Payment Type” column is dropdown controlled using the snippet above. Depending on the value the user enters (or the autocomplete engine synthesis) for the “Payment Type” column, the dropdown options available to the second “Payment Provider” will vary.

Following the logic provided in the custom `validOptions` provider function, the dropdown options for when “cash” is selected for “Payment Type” are limited to “N/A”:

When “credit” is entered for “Payment Type”, the various card providers are populated instead:

Using this pattern, it’s possible to construct complex logic to represent whatever kind of business rules may exist for your uploader. Since the function that can be provided to `validOptions` is asynchronous, it’s even possible to do things like make API requests, look things up in a database, or perform other external operations to determine what values to show to users.

An actual upload snippet with this example of a dropdown field may look like the JavaScript below:

<!-- Osmos File Upload Button -->
<!-- See this link for more docs. https://docs.osmos.io/osmos-uploader/webpage-integration -->
<script src="https://cdn.osmos.io/button/embed/v1/OsmosButton.js"></script>
<script>
  Osmos.configure({
  schema: {
    fields: [
      {
        name: "ProductID",
        displayName: "ProductID",
        description: "<Your field description here>"
      },
      {
        name: "FirstName",
        displayName: "FirstName",
        description: "<Your field description here>"
      },
      {
        name: "LastName",
        displayName: "LastName",
        description: "<Your field description here>"
      },
      {
       name: 'a',
       displayName: 'Payment Type',
       description:'The medium of payment which was used to complete the transaction',
       validOptions: ['cash', 'credit', 'debit', 'paypal'],
      },
      {
       name: 'b',
       displayName: 'Payment Provider',
       description:'If the payment was made using a credit or debit card, contains the provider of that card',
       validOptions: async (rowValues) => {
         const paymentType = rowValues[0];
 
         // If the user hasn't yet filled out the first column, do not let them populate this field yet
         if (!paymentType) {
           return [];
         }
 
         // If the payment wasn't made with a card, force the user to fill this field with "N/A"
         if (paymentType !== 'credit' && paymentType !== 'debit') {
           return ['N/A'];
         }
 
         // Allow the user to pick from the set of available card providers
         return [
           'Discover',
           'Visa',
           'MasterCard',
           'Chase',
           'American Express',
           ];
         },
       // If the card provider is other than the list we have available, allow the user to pick a custom option for this field and override the dropdown options we present them with
       allowCustomOptions: true,
      }
    ]
  },
  token: "example_some_uploader_token_uuid_example",
  uploadDescription: "<Include a description of your uploader upload here which will be shown to users that click the uploader>",
  

  // Set to false to show the schema for the destination connector in the uploader on the file upload screen.
  hideUploadSchema: true,

  // Set to false to show the uploader description on the file upload screen.
  hideUploadDescription: true,

  // Set to false to show the advanced version of the uploader, with formulas, SmartFill, and QuickFixes.
  disableAdvancedMode: true,

  // Maximum number of records displayed in the Uploader UI (User Interface).
  // This value is capped at 100,000 and higher values will default back to 100,000.
  // Can be lowered to increase UI performance when using expensive validators.
  // NOTE: Your file can have >100,000 rows and will be processed fully. There are no limits to how many records can be uploaded.
  //       This setting only limits the number of rows displayed in the UI.
  maxRecords: 100000,

  // Set to true to hide the preview pane screen for CSV files in the uploader.
  hideCSVPreviewPane: false,

});
</script>
<button class="ftl-button" onclick="Osmos.handleClick('w9ziodyyfx4mq6wl2tw1y6dpp6tctfardjeuqsl_n0i-gtsbb')">
  Upload Your Data
</button>
<!-- End Osmos File Upload Button -->

Last updated