# properties

The configuration properties of the component. Note that unlike properties specified on input ports (described later on in the documentation), these properties cannot be configured by the user to use data coming from the components back in the chain of connected components. In other words, these properties can only use data that is known before the flow runs.

![Component Configuration](https://3013747694-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-L_wafleSA7oup24f2Rm%2F-L_waiJsX3XykxpTKJiP%2FScreenshot%202019-03-14%20at%2015.28.24.png?alt=media\&token=227bfe62-f3f3-48f0-bdc7-403f667ca5ab)

Configuration properties are defined using two objects `schema` and `inspector`.

## properties.schema

`schema` is a JSON Schema definition ([http://json-schema.org](http://json-schema.org)) of the properties, their types and whether they are required or not. An example looks like this:

```
{
    "properties": {
        "schema": {
            "properties": {
                "interval": {
                    "type": "integer",
                    "minimum": 5,
                    "maximum": 35000
                }
            },
            "required": [
                "interval"
            ]
        }
}
```

The JSON Schema gives you enough flexibility to describe your property types and the required format, possibly using regular expressions or other mechanisms. When the user fills in the forms in the Designer UI inspector to configure their components, the Designer automatically validates all inputs using the schema. If any of the properties are invalid, the Designer UI gives an immediate feedback to the user that they should correct their configuration:

![Invalid Inspector field](https://3013747694-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-L_wafleSA7oup24f2Rm%2F-L_wb3SCt3j399NLibhb%2FScreenshot%202019-03-14%20at%2015.30.00.png?alt=media\&token=934e87e4-4364-4f7c-af1b-77de995c4a7b)

![Configuration Overview](https://3013747694-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-L_wafleSA7oup24f2Rm%2F-L_wb8zhnz5cwvj43-n8%2FScreenshot%202019-03-14%20at%2015.30.22.png?alt=media\&token=d73cf776-7961-48b4-8642-c175dd481303)

## properties.inspector

`inspector` tells the Designer UI how the input fields should be rendered. The format of this definition uses the [Rappid Inspector definition format](https://resources.jointjs.com/docs/rappid/v2.2/ui.html#ui.Inspector). Example:

```
{
    "properties: {
        "inspector": {
            "inputs": {
                "interval": {
                    "type": "number",
                    "group": "config",
                    "label": "Interval (in minutes, min 5, max 35000)"
                }
            },
            "groups": {
                "config": {
                    "label": "Configuration",
                    "index": 1
                }
            }
        }
    }
}
```

As you can see, fields (e.g. `interval` in this case) are nested inside the `inputs` object and have the following properties:

* `type` can be any of the built-in types. See below for more details. (Custom inspector fields are also possible for on-prem installations. See the Custom Inspector Fields page for more details.)
* `group` is an identifier of an Inspector group this field belongs to. As you can see in the example above, you can have one or more custom groups (like `config` in this case) that you can define in the `groups` object. Groups will render in the Inspector UI in an accordion-like fashion. This is handy to organize your fields.
* `label` is a short text that appears above your input field. This is a great place to tell your users what your field is.

### Inspector built-in types:

#### text

A single line input field.

![](https://3013747694-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-LATDkr7Z9HspTfvbiBo%2F-LATDq2OzXRf4RxKIFPk%2Finspector%20text%20field.png?generation=1524146870096497\&alt=media)

```
{
    "type": "text",
    "label": "Text message."
}
```

#### textarea

A multi-line text input field.

![](https://3013747694-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-LATDkr7Z9HspTfvbiBo%2F-LATDq4QxkmyI1pdv0ab%2Finspector%20textarea%20field.png?generation=1524146868546255\&alt=media)

```
{
    "type": "textarea",
    "label": "A multi-line text message."
}
```

#### number

A numerical input field. Additional configuration includes _min_, _max_ and _step_ numbers.

![](https://3013747694-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-LATDkr7Z9HspTfvbiBo%2F-LATDq7rg1OIw_Fz4Sol%2Finspector%20number%20field.png?generation=1524146868079352\&alt=media)

```
{
    "type": "number",
    "label": "A numerical input.",
    "min": 1,
    "max": 10,
    "step": 1
}
```

#### select

A menu of options. Options are defined in the `options` array each item having `content` and `value` properties. Note that `content` can be HTML. You can optionally provide `placeholder` that is displayed if no option is selected. Default values can be defined with `defaultValue`. If you need one of the items to clear the value of the select input field, use `{ "clearItem": true, "content": "Clear" }` as one of the objects in the `options` array.

![](https://3013747694-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-LATDkr7Z9HspTfvbiBo%2F-LATDqD-lMCOHwI8Y9PO%2Finspector%20select%20field.png?generation=1524146868029349\&alt=media)

#### multiselect

Similar to `select` type, multiselect defines options the user can choose from. The difference is that with multiselect, the user can select multiple options, not only one. The value stored in the flow descriptor is an array of values the user selected. Supported options are `options` and `placeholder.`

```
{
    "type": "multiselect",
    "options": [
        { "content": "one", "value": 1 },
        { "content": "two", "value": 2 },
        { "content": "three", "value": 3 }
    ],
    "placeholder": "-- Select something --",
    "label": "Multi Select box"
}
```

#### date-time

A date-time input field allows the user to select a date/time using a special date/time picker interface. The date-time input field can be configured to support different type of formats or modes (only date or date-time combination). The configuration is stored in the "config" object. The following table shows list of all the available options:

| Option          | Description                                                                                                                                                                                                                             |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `format`        | String representing the format of the date/time. Please see the moment.js library documentation for all the available tokens: [https://momentjs.com/docs/#/parsing/string-format/](https://momentjs.com/docs/#/parsing/string-format/). |
| `enableTime`    | Boolean. Enables time picker.                                                                                                                                                                                                           |
| `enableSeconds` | Boolean. Enables seconds in the time picker.                                                                                                                                                                                            |
| `maxDate`       | String representing the maximum date that a user can pick to (inclusive).                                                                                                                                                               |
| `minDate`       | String representing the minimum date that a user can pick to (inclusive).                                                                                                                                                               |
| `mode`          | Mode of the date/time picker. Possible values are `"single"`, `"multiple"`, or `"range"`.                                                                                                                                               |
| `time_24hr`     | Boolean. Displays time picker in 24 hour mode without AM/PM selection when enabled.                                                                                                                                                     |
| `weekNumbers`   | Boolean. Enables display of week numbers in calendar.                                                                                                                                                                                   |

![](https://3013747694-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-LATDkr7Z9HspTfvbiBo%2F-LATDqGWLzxCQ2r09y7G%2Finspector%20date-time%20field.png?generation=1524146870049357\&alt=media)

```
{
    "type": "date-time",
    "label": "Date",
    "config": {
        "enableTime": true
    }
}
```

#### toggle

A toggle input field allows the user to switch between true/false values.

![](https://3013747694-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-LATDkr7Z9HspTfvbiBo%2F-LATDqJS7RS7uKJgVqkt%2Finspector%20toggle%20field.png?generation=1524146868124706\&alt=media)

```
{
    "type": "toggle",
    "label": "Toggle field"
}
```

#### color-palette

A menu of colors. Colors are defined in the `options` array each item having `content` and `value` properties, where `values` must be a color in any of the [CSS color formats](https://developer.mozilla.org/en-US/docs/Web/CSS/color) (named-color, hex-color, rgb() or hsl()).

![](https://3013747694-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-LATDkr7Z9HspTfvbiBo%2F-LATDqQVvdKKSkH98xaS%2Finspector%20color-palette%20field.png?generation=1524146868512521\&alt=media)

```
{
    "type": "color-palette",
    "label": "Color palette",
    "options": [
        { "value": "green", "content": "Green" },
        { "value": "yellow", "content": "Yellow" },
        { "value": "orange", "content": "Orange" },
        { "value": "red", "content": "Red" },
        { "value": "purple", "content": "Purple" }
    ]
}
```

#### select-button-group

A group of toggle buttons. Both single and multiple selection is allowed (can be controlled with the `multi` flag). Buttons are defined in the `options` array each item having `value`, `content` and `icon` properties.

![](https://3013747694-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-LATDkr7Z9HspTfvbiBo%2F-LATDqZS5y2v3QvZn6Ys%2Fselect-button-group.png?generation=1524146872074344\&alt=media)

```
{
    "type": "select-button-group",
    "label": "Select button group",
    "options": [
        { "value": "line-through", "content": "<span style=\"text-decoration: line-through\">S</span>" },
        { "value": "underline", "content": "<span style=\"text-decoration: underline\">U</span>" },
        { "value": "italic", "content": "<span style=\"font-style: italic\">I</span>" },
        { "value": "bold", "content": "<span style=\"font-weight: bold\">B</span>" }
    ]
}
```

![](https://3013747694-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-LATDkr7Z9HspTfvbiBo%2F-LATDqd48FrG3HugUE_D%2Fselect-button-group%20multi.png?generation=1524146870622316\&alt=media)

```
{
    "type": "select-button-group",
    "label": "Select button group",
    "multi": true,
    "options": [
        { "value": "line-through", "content": "<span style=\"text-decoration: line-through\">S</span>" },
        { "value": "underline", "content": "<span style=\"text-decoration: underline\">U</span>" },
        { "value": "italic", "content": "<span style=\"font-style: italic\">I</span>" },
        { "value": "bold", "content": "<span style=\"font-weight: bold\">B</span>" }
    ]
}
```

![](https://3013747694-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-LATDkr7Z9HspTfvbiBo%2F-LATDqiciBsQT1Es8XZd%2Fselect-button-group%20icons.png?generation=1524146872148652\&alt=media)

```
{
    "type": "select-button-group",
    "label": "Select button group with icons",
    "multi": true,
    "options": [
        { "value": "cloud", "icon": "data:image/png;base64,iVBORw0KGgoAA..." },
        { "value": "diamond", "icon": "data:image/png;base64,iVBORw0KGgoAAAA..." },
        { "value": "oval", "icon": "data:image/png;base64,iVBORw0KGgoAAAANSUh..." },
        { "value": "line", "icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUg..." },
        { "value": "ellipse", "icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEU..." }
    ]
}
```

#### expression

A multi-field type  field that allows for definition of logical expressions (OR/AND) or dynamic field definitions. This field accepts a list of other inspector field types (text, textarea, number, toggle, ....) and renders a "field builder" UI that enables the user to dynamically create nested fields.

![](https://3013747694-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-LATDkr7Z9HspTfvbiBo%2F-LATDqryk0yaeMkhimxK%2Finspector-expression-field.png?generation=1524146872786939\&alt=media)

```
{
      "type": "expression",
      "label": "Filter expression",
      "levels": ["OR", "AND"],
      "exclusiveFields": ["myText"]
      "fields": {
          "myText": {
              "type": "text",
              "label": "Column",
              "required": true,
              "index": 1
          },
          "mySelect": {
              "type": "select",
              "label": "Filter action",
              "variables": false,
              "required": true,
              "options": [
                  { "content": "Equals", "value": "equals" },
                  { "content": "Not Equals", "value": "notEquals" }
              ],
              "index": 2
          },
          "myAnotherText": {
              "label": "Filter value",
              "type": "text",
              "defaultValue": "My Filter",
              "index": 3
          }
      ]
}
```

The value of this field has the following structure:

```
{
    "OR": [
        {
            "AND": [
                { "myText": "My column name", "mySelect": "My filter action", "myAnotherText": "My filter value" },
                { "myText": "Another column name", "mySelect": "Another filter action", "myAnotherText": "Another filter value" }
            ]
        },
        {
            "AND": [
                { "myText": "Alternative column", "mySelect": "Alternative action", "myAnotherText": "Alternative value" }
            ]
        }
    ]
}
```

Note that by specifying the `levels` option, you can define the nesting. Currently, maximum of 2 levels of nesting is supported. The common use case is to use just one level. In that case, set e.g. `"levels": ["ADD"]`.

The `exclusiveFields` is an optional property which defines the fields that will use variables in an exclusive way. For example let's say that the component has `variableA` and `variableB` available for use in its fields. Now if the `myText` field is in `exclusiveFields` array that means that you can use each variable once across all the fields inside the expression groups. To clarify this further, imagine the following scenario configuring an expression type:

1. Click the `ADD` button to create a second group
2. Select `variableA` on the `myText` field inside the first group using the variables picker
3. When opening the variables picker in `myText` field inside the second group, only `variableB` will be available, because `variableA` is already been used

#### filepicker

An input that allows selecting and uploading files from the user's computer. When clicked, it will open the browser's file selector, and the file selected will be uploaded to Appmixer and referenced on the input.

![](https://3013747694-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-MOCl_r8u5ZRBklo17ss%2F-MOCnY79aJIhTUFDF3WU%2Fproperties_-_Appmixer.png?alt=media\&token=fef650d6-1e34-49aa-aa9a-bcc16ff6b290)

```
"inputs": {
    "fileId": {
        "type": "filepicker",
        "label": "Select file",
        "index": 1,
        "tooltip": "Pick a CSV file to import into the flow"
    }
}
```

#### googlepicker

Similar to the _filepicker_ input, this one allows users to select files or folders on their Google Drive accounts. When clicked a Google Drive file picker is opened, showing the user's Google Drive content. When selecting a folder/file, the input value becomes an object which includes the Id of the folder/file which should be used on Google API calls to reference that asset.

![](https://3013747694-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-MOCl_r8u5ZRBklo17ss%2F-MOCoQHQiRNAAcYbcEJ8%2FAppmixer.png?alt=media\&token=224ede90-baad-482a-847f-4d898a75828e)

```
"inputs": {
    "file": {
        "type": "googlepicker",
        "index": 1,
        "label": "File",
        "placeholder": "Choose a file...",
        "tooltip": "Choose a file to export."
    }
}
```

You can use _googlepicker_ to pick folders instead of files:

```
"inputs": {
    "file": {
        "type": "googlepicker",
        "index": 1,
        "label": "Folder",
        "placeholder": "Choose a folder...",
        "tooltip": "Choose a folder.",
        "view": "FOLDERS"
    }
}
```

This input type needs`appmixer.google.drive.GooglePicker` component to be installed.

#### onedrivepicker

Similar to the _googlepicker_, this one allows users to select files or folders from their OneDrive accounts.  When clicked, an OneDrive file picker is opened, showing the user's OneDrive content. When selecting a folder/file, the input value becomes an object which includes the id of the folder/file which should be used on OneDrive API calls to reference that asset.

```
"input": {
    "folder": {
        "type": "onedrivepicker",
        "index": 1,
        "label": "Folder",
        "placeholder": "Choose a folder...",
        "tooltip": "Choose a folder to upload the file to.",
        "view": "folders"
    }
}
```

The view property works similar to the same property on googlepicker. It can be used to determine what is shown on the picker. You can use 3 values: `files`, `folder`, `all`. As their names indicate, if select `files`, only files will be shown, if you select `folder` it will show only your folders and if you select `all` it will show both. This input type needs `appmixer.microsoft.onedrive.OneDrivePicker` component to be installed.

### Conditional fields

There are some cases when you want to show input fields depending on other values in the inspector. This allows to a better UX for component configuration. For this we use the `when`property in the field we want to be conditional:

```
"inputs": {
    "field1": {
        "type": "toggle",
        "label": "This input controls rendering of field2",
        "index": 1
    },
    "field2": {
        "when": { "eq": { "field1": true }}
        "type": "text",
        "label": "This field will be only rendered if field1 is set to true",
        "index": 2
    }
}
```

The when field has the following structure: `{ op: { field: comparisonValue }}`.&#x20;

* **op:** Is the operand that will be used to determine if the condition holds true or false. The following operands are supported:
  * **`eq`:** Equality between the values.
  * **`equal`:** Equality between the values by deep comparison. Used for objects and arrays.
  * **`ne`:** Values are not equal.
  * **`regex`:** Check if the value in given `field` matches the regex in the `comparisonValue`.
  * **`text`:** Check if the value in the given `field` contains the string in the `comparisonValue`.
  * **`lt`:** Check if the value in the given `field` is less than the `comparisonValue`.
  * **`lte`:** Check if the value in the given `field` is less or equal than the `comparisonValue`.
  * **`gt`:** Check if the value in the given `field` is greater than the `comparisonValue`.
  * **`gte`:** Check if the value in the given `field` is greater or equal than the `comparisonValue`.
  * **`in`:** Check if the value in the given `field` is included on the given `comparisonValue` array.
  * **`nin`:** Check if the value in the given path is not included in the given `comparisonValue`.
* **field:** The field that is used for comparison, there are several ways to reference the field:
  * **`field`:** The same form presented in the example. It will search the given fields in current input port fields.
  * **`properties/someProperty`:** Refer to a property inside component properties.
  * **`./field`:** It will refer to sibling fields of the current field. Specially useful when working with expression types.
* **comparisonValue:** The value used to compare the field against.

As it was mentioned, conditional fields also work with expression types, allowing to control the field rendering inside those expressions:

```
{
      "type": "expression",
      "label": "Filter expression",
      "levels": ["OR", "AND"],
      "fields": {
          "myText": {
              "type": "text",
              "label": "Column",
              "required": true,
              "index": 1
          },
          "conditionalField": {
              "when": { "eq": { "./myText": "Render" }}
              "type": "select",
              "label": "Filter action",
              "variables": false,
              "required": true,
              "options": [
                  { "content": "Equals", "value": "equals" },
                  { "content": "Not Equals", "value": "notEquals" }
              ],
              "index": 2
          }
      ]
}
```

## properties.source

Sometimes the structure of the inspector is not known in advance and it cannot be hardcoded in the manifest. Instead, the inspector fields are composed dynamically based on the data received from an API. A good example is the _google.spreadsheets.CreateRow_ component where the inspector renders fields representing columns fetched from the actual worksheet. For this to work, we can define the `source` property in the manifest that calls a component of our choosing in a so called "static" mode. For example:

```
{
       "source": {
           "url": "/component/appmixer/google/spreadsheets/ListColumns?outPort=out",
           "data": {
               "messages": {
                   "in": 1
               },
               "properties": {
                   "sheetId": "properties/sheetId",
                   "worksheet": "properties/worksheet"
               },
               "transform": "./transformers#columnsToInspector"
           }
       }
}
```

In the example above, we call the _ListColumns_ component and we're interested in the output coming from the output port `out`.Since this is just a normal component, we need to transform the result into the inspector-like object, i.e.:

```
{
    inputs: { ... },
    groups: { ... }
}
```

We need to tell Appmixer where it can find the transformation function. For this we use the `transform` property which tells Appmixer to look for the `transformers.js` file inside the `ListColumns/` directory. The transformer must return an object with a function named `columnsToInspector` that can look like this:

```
module.exports.columnsToInspector = (columns) => {

    let inspector = {
        inputs: {},
        groups: {
            columns: { label: 'Columns', index: 1 }
        }
    };

    if (Array.isArray(columns) && columns.length > 0) {
        columns.forEach((column, index) => {
            inspector.inputs[column[0]] = {
                type: 'text',
                group: 'columns',
                index: index + 1
            };
        });
    }
    return inspector;
};
```

### properties.source.url

A special URL that identifies a component that should be called in a "static" mode. It has to be of the form `/component/[vendor]/[service]/[module]/[component]`. It should also contain `outPort` in the query string that point to the output port in which we're interested to receive data from. Example:

```
"/component/appmixer/google/spreadsheets/ListColumns?outPort=out"
```

### properties.source.data.messages

Messages that will be sent to the input port of the component referenced by the `properties.source.url`. Keys in the object represent input port names and values are any objects that will be passed to the input port as messages.

### properties.source.data.properties

Properties that will be used in the target component referenced by the `properties.source.url`. The target component must have these properties defined in its manifest file. The values in the object are references to the properties of the component that calls the target component in the static mode. For example:

```
{
    "properties": {
        "targetComponentProperty": "properties/myProperty"
    }
}
```

### properties.source.data.transform

The transformation function used to transform the output of the target component. It should return an inspector-like object, i.e.:

```
{
    inputs: { ... },
    groups: { ... }
}
```

Example:

```
{
    "transform": "./transformers#columnsToInspector"
}
```

The transform function is pointed to be a special format `[module_path]#[function]`, where the transformation module path is relative to the target component directory.
