# Custom Inspector Fields

The Inspector widget in the Designer UI provides built-in types such as `text`, `number`, `toggle`, `select` and others (See the [Properties section of the Component Manifest](../component-definition/manifest/properties) for details). However, thanks to the modular design of the Designer UI, customized installations of the Appmixer system allows to extend the set of Inspector fields by custom types.

![Custom Inspector Field for Polygon Selection in Google Maps](https://3844357853-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-M-Eo3tKKp8l76mPR3gV%2F-M-EoyPJ7ZBGazR7yQRV%2Fam-inspector-field-google-map.png?alt=media\&token=885dd16f-d762-496c-8c38-84a327a159d1)

![Custom Inspector Field with Rich Text Editor](https://3844357853-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-M-Eo3tKKp8l76mPR3gV%2F-M-Ep2gIDv5tJJfHDp9S%2Fam-inspector-field-rich-text-editor.png?alt=media\&token=31a529cf-f472-4810-a88d-beb2cbd1def4)

![Custom Inspector Field with Price Calculator](https://3844357853-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-M-Eo3tKKp8l76mPR3gV%2F-M-Ep7m_KHMsJsWi8meH%2Fam-inspector-field-calculator.png?alt=media\&token=2853f54e-166b-4405-a92c-93ef156f656a)

## Defining Custom Inspector Fields

To define your custom inspector field, use the Appmixer JavaScript SDK `appmixer.registerInspectorField(type, definition, options)` method. To style your inspector field, just use regular CSS. `definition` is a [Vue JS component](https://vuejs.org/v2/api/#Vue-component). The component must call the `change(value)` method to tell the SDK to change the value of the inspector field and save the flow. The componet additionally adds `this.value` which stores the current value of the field in the flow descriptor. Therefore, calling `change(newValue)` will also change `this.value`.  `options` are additional options that control the behaviour of the inline editor that replaces your inspector field when the user selects a variable from the variable picker. Available options are:

| Option           | Default value | Description                                                                                                                                         |
| ---------------- | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `readOnly`       | `false`       | Set read only mode on the inline editor. Available values are `true`, `false`, `"nocursor"` (similar to `true` but no cursor is blinking).          |
| `singleVariable` | `false`       | Allow only a single variable to be selected in the variable picker, i.e. selecting another variable will replace the current inline editor content. |
| `clearButton`    | `true`        | Show clear button at the right edge of the inline editor allowing the user to switch back to your custom field.                                     |

{% hint style="info" %}
Note that the `definition` is an Appmixer specific wrapper around a Vue JS component. The basic functions and properties you can use are:

* Template and Render function: [https://vuejs.org/v2/api/#template](https://vuejs.org/v2/api/#template), [https://vuejs.org/v2/api/#render](https://vuejs.org/v2/api/#render)
* Data objects: [https://vuejs.org/v2/api/#data](https://vuejs.org/v2/api/#data), [https://vuejs.org/v2/api/#computed](https://vuejs.org/v2/api/#computed), [https://vuejs.org/v2/api/#methods](https://vuejs.org/v2/api/#methods), [https://vuejs.org/v2/api/#watch](https://vuejs.org/v2/api/#watch)
* Livecycle hooks: [https://vuejs.org/v2/api/#Options-Lifecycle-Hooks](https://vuejs.org/v2/api/#Options-Lifecycle-Hooks)
* `this.invalid` computed property is a boolean value that tells the field whether its value is valid or not. An example is a required field that is empty. In that case `this.invalid` will be `true`.
* Properties propagated by Appmixer are (properties that can be accessed via `this` keyword, e.g. `this.value`): &#x20;

`props: {`\
&#x20;  `context: { type: Object },`\
&#x20;  `value: { type: null, required: false },`\
&#x20;  `errors: { type: Array, default: () => ([]) },`\
&#x20;  `disabled: { type: Boolean, default: false }`\
`}`

The context object contains contextual data from the component and the current input. It has the following structure:\
\
`context: {` \
&#x20;  `componentId: { type: String },` \
&#x20;  `inputManifest: { type: Object },` \
&#x20;  `componentManifest: { type: Object },` \
&#x20;  `descriptorPath: { type: String },` \
&#x20;  `variables: { type: Object }` \
`}`
{% endhint %}

### Basic example

Here's a very basic example of a custom inspector field with just one HTML input element. Note how we use the Vue JS template definition. Also note that we need to call the `change()` method to propagate the value back to the flow descriptor (i.e. to save the flow with the new value of the field when the user makes a change):

```javascript
appmixer.registerInspectorField('your-custom-text-input', {
    template: `
        <div class="your-custom-text-input">
            <label>Name</label>
            <input :value="value" @change="change($event.target.value)">
        </div>
    `
});
```

### Advanced example

Here's another example of a custom inspector field that accepts a value that represents first and last name of a person in one string. The inspector field renders two HTML inputs, one for first name and one for last name. The returned value (the one stored back to the flow descriptor) is again one string. Note how we call `this.change(value)` to propagate value of the inspector field to the flow descriptor (i.e. to save the flow with a new value for this field):

```javascript
appmixer.registerInspectorField('your-custom-input-type', {
    template: `
        <div class="your-custom-input-field">
            <label>Firstname</label>
            <input v-model="firstname" @change="onChange">
            <label>Lastname</label>
            <input v-model="lastname" @change="onChange">
        </div>
    `,
    watch: {
        value: {
            immediate: true,
            handler(value = '') {
                this.firstname = value.split(' ')[0] || '';
                this.lastname = value.split(' ')[1] || '';
            },
        },
    },
    data() {
        return {
            firstname: '',
            lastname: '',
        };
    },
    methods: {
        onChange() {
            const name = [
                this.firstname.trim(),
                this.lastname.trim(),
            ].join(' ');
            this.change(name);
        },
    },
});

```

To style your inspector field, just use regular CSS in your application, e.g:

```css
.your-custom-input-field {
    font: 14px 'Segoe UI', Verdana, sans-serif;
}
.your-custom-input-field label {
    display: block;
    margin: 10px 0 5px;
    color: #888;
}
.your-custom-input-field input {
    display: block;
    padding: 0.5em;
    border: solid 1px #e8e8e8;
    border-radius: 5px;
}
```

