# Settings

Widgets can have settings that users can change while selecting or editing a widget. This allows you to add some initial variables to your widgets.

<pre class="language-json" data-title="widget.compose.json"><code class="lang-json"><strong>{
</strong>  "name": {
    "en": "My Widget"
  },
  "settings": [
    {
      "id": "text",
      "type": "text",
      "title": {
        "en": "Text"
      },
      "hint": {
        "en": "Your number"
      }
    },
    {
      "id": "number",
      "type": "number",
      "title": {
        "en": "Number"
      },
      "hint": {
        "en": "Your number"
      }
    }
  ]
}
</code></pre>

## Defining Settings

Every setting has a `type` property that determines what values it can have and how it is presented to the user. The `value` property of each setting is the initial value of the setting. The following setting types are supported:

### Text

`string | null`

This is a single line text input whose value is a string. You can optionally validate the value using a regex pattern by adding a `pattern` property.

```json
{
  "id": "text",
  "type": "text",
  "title": { "en": "Text" },
  "value": "My initial value",
  "hint": { "en": "My text hint." },
  "pattern": "[a-zA-Z]"
}
```

### Textarea

`string | null`

This setting type allows users to input multi-line text.

```json
{
  "id": "description",
  "type": "textarea",
  "title": { "en": "Textarea" },
  "value": "Enter your description here.",
  "hint": { "en": "Provide a detailed description." },
  "pattern": "[a-zA-Z]"
}
```

### Number

`number | null`

This setting type allows users to input numerical values. The `min` and `max` properties are optional and can be used to define the acceptable range of values.

```json
{
  "id": "age",
  "type": "number",
  "title": { "en": "Age" },
  "value": 25,
  "hint": { "en": "Your age." },
  "min": 0,
  "max": 120
}
```

### Dropdown

`string | null`

This setting type allows users to select a value from a predefined list.

```json
{
  "id": "dropdown",
  "type": "dropdown",
  "title": {
    "en": "Dropdown",
    "nl": "Dropdown"
  },
  "value": "heating",
  "values": [
    {
      "id": "heating",
      "title": {
        "en": "Heating"
      }
    },
    {
      "id": "cooling",
      "title": {
        "en": "Cooling"
      }
    }
  ]
}
```

### Checkbox

`boolean | null`

This setting type allows users to enable or disable a feature.

```json
{
  "id": "checkbox",
  "type": "checkbox",
  "value": true,
  "title": {
    "en": "Checkbox",
    "nl": "Checkbox"
  }
}
```

### Autocomplete

`object | null`

This setting type provides an input that suggests options as the user types.

```json
{
  "id": "composer",
  "type": "autocomplete",
  "title": {
    "en": "Composer"
  }
}
```

{% tabs %}
{% tab title="JavaScript" %}

```javascript
'use strict';

const Homey = require('homey');

class MyApp extends Homey.App {

  async onInit() {
    const widget = this.homey.dashboards.getWidget('my-widget')

    widget.registerSettingAutocompleteListener('composer', async (query, settings) => {
      return [
        {
          name: "Mozart",
          // Optionally provide the following properties.
          description: "...",
          image: "https://some.url/",

          // You can freely add additional properties
          // that you can access in Homey.getSettings()['mySettingId'].
          id: "mozart",
        },
        {
          name: "Amadeus",

          // You can freely add additional properties
          // that you can access in Homey.getSettings()['mySettingId'].
          id: "amadeus",
        },
      ].filter((item) => item.name.toLowerCase().includes(query.toLowerCase()));
    });
  }
}

module.exports = MyApp;
```

{% endtab %}

{% tab title="TypeScript" %}

```mts
import Homey, { Widget } from "homey";

export default class App extends Homey.App {
  async onInit(): Promise<void> {
    const widget = this.homey.dashboards.getWidget("my-widget");

    widget.registerSettingAutocompleteListener(
      "composer",
      async (query: string, settings): Promise<Widget.SettingAutocompleteResults> => {
        return [
          {
            name: "Mozart",
            // Optionally provide the following properties.
            description: "...",
            image: "https://some.url/",

            // You can freely add additional properties
            // that you can access in Homey.getSettings()['mySettingId'].
            id: "mozart",
          },
          {
            name: "Amadeus",

            // You can freely add additional properties
            // that you can access in Homey.getSettings()['mySettingId'].
            id: "amadeus",
          },
        ].filter(item => item.name.toLowerCase().includes(query.toLowerCase()));
      },
    );
  }
}

```

{% endtab %}

{% tab title="Python" %}

```python
from homey import app
from homey.widget import SettingAutocompleteResult


class App(app.App):
    async def on_init(self) -> None:
        widget = self.homey.dashboards.get_widget("my-widget")

        async def autocomplete_listener(
            query, settings
        ) -> list[SettingAutocompleteResult]:
            results: list[SettingAutocompleteResult] = [
                {
                    "name": "Mozart",
                    # Optionally provide the following properties.
                    "description": "...",
                    "image": "https://some.url/",
                    "data": {
                        # You can freely add additional properties
                        # that you can access in Homey.getSettings()['mySettingId'].data
                        "id": "mozart",
                    },
                },
                {
                    "name": "Amadeus",
                    "data": {
                        # You can freely add additional properties
                        # that you can access in Homey.getSettings()['mySettingId'].data
                        "id": "amadeus",
                    },
                },
            ]

            return [
                result for result in results if query.lower() in result["name"].lower()
            ]

        widget.register_setting_autocomplete_listener("artist", autocomplete_listener)


homey_export = App

```

{% endtab %}
{% endtabs %}

## Accessing Settings

{% code title="index.html" %}

```html
<html>

<head>
...
</head>

<body>
  <script type="text/javascript">
    function onHomeyReady(Homey) {
      Homey.ready();
    
      for (const [settingId, settingValue] of Object.entries(Homey.getSettings())) {
        // Do something with the settings...
      }
    }
  </script>
</body>

</html>
```

{% endcode %}

## Devices

Many widgets are designed to display content based on specific Homey devices. To simplify this, a dedicated `devices` setting is provided, allowing users to select one or more devices. Once selected, your widget can access their IDs using `Homey.getDeviceIds()`.

**Configuration Options**

The `devices` setting includes the following required properties:

* **`singular` (boolean, required)** – Determines whether users can select multiple devices:
  * `false` – Allows selecting multiple devices.
  * `true` – Restricts selection to a single device.
* **`type` (string, required)** – Defines the scope of selectable devices:
  * `"app"` – Limits selection to devices belonging to your app.
  * `"global"` – Allows selection from all Homey devices, only makes sense if the app has the necessary `homey:manager:api` permission.

Additionally, an **optional** `filter` property can be used to limit the selection to specific devices:

* **`filter` (object, optional)** – Defines selection criteria:
  * **`class` (string, optional)** – Filters devices by their device class (e.g., `"socket"`, `"light"`, `"sensor"`).
    * Supports multiple values using a **pipe (`|`)** as an **OR** separator (e.g., `"socket|light"` allows selecting both sockets and lights).
  * **`capabilities` (string, optional)** – Filters devices based on required capabilities (e.g., `"onoff"`).
    * Supports:
      * **OR (`|`)**: `"onoff|dim"` → Devices must have **at least one** of these capabilities.
      * **AND (`,`)**: `"onoff,dim"` → Devices must have **all** these capabilities.
      * **Combination (`|` and `,`)**: `"onoff,dim|light_mode"` → Devices must have **both** `onoff` and `dim` capabilities **OR** the `light_mode` capability.

Additionally, users can reorder selected devices via drag-and-drop.

<pre class="language-json" data-title="widget.compose.json"><code class="lang-json"><strong>{
</strong>  "name": {
    "en": "My Widget"
  },
  "devices": {
    "type": "global",
    "singular": false,
    "filter": {
      "class": "socket",
      "capabilities": "onoff"
    }
  },
  "settings": [
    {
      "id": "text",
      "type": "text",
      "title": {
        "en": "Text"
      },
      "hint": {
        "en": "Your number"
      }
    },
    {
      "id": "number",
      "type": "number",
      "title": {
        "en": "Number"
      },
      "hint": {
        "en": "Your number"
      }
    }
  ]
}
</code></pre>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://apps.developer.homey.app/the-basics/widgets/settings.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
