# Dynamic filters for data sources and dynamic pages **Prerequisites** The below articles should be read before starting this article: - [Developing a data source extension](/frontend-development/developing-a-data-source-extension.md) - [Developing a dynamic page extension](/frontend-development/developing-a-dynamic-page-extension.md) - [Developing an action extension](/frontend-development/developing-an-action-extension.md) The schema language (which is used for Frontend component schemas, data source schemas, and so on) allows you to define input forms for configuration in the Studio. It can become challenging to keep up with your schema over time if the fields are frequently changed. To solve this, commercetools Frontend supports the `dynamic-filter` field type. A field of type `dynamic-filter` allows you to instruct the Studio to load a schema definition from a given API endpoint. Instead of just rendering a static form, the Studio will call the endpoint specified by the `dynamic-filter` field and present a list of filters to the user, which they can add. A typical scenario for `dynamic-filter` is fetching searchable attributes from a backend system like a commerce product search, content search, or similar from a commerce backend system. Using a `dynamic-filter`, you can fetch the supported attributes directly from the backend and expose them to the Studio as filter fields. In this scenario, you typically use `dynamic-filter` in the schema of a data source extension, but it's also possible to use it in any other schema. ## The dynamic-filter field in a schema To use the power of dynamic filters, you need to add a field of this type to a schema. In this example, we're using a data source schema: ```json title="schema.json" { "customDataSourceType": "example/star-wars-character", "name": "Star wars character", "category": "Content", "icon": "source", "schema": [ { "name": "Character search", "fields": [ { "label": "Filters", "field": "characterFilters", "type": "dynamic-filter", "dynamicFilterEndpoint": "/frontastic/action/star-wars/filters" } ] } ] } ``` In the following example, we're using a dynamic page schema: ```json title="schema.json" { "dynamicPageType": "example/star-wars-character-page", "name": "Star wars character page", "category": "Content", "icon": "source", "dataSourceType": "example/star-wars-character", "isMultiple": true, "pageMatchingPayloadSchema": [ { "label": "Filters", "field": "characterFilters", "type": "dynamic-filter", "dynamicFilterEndpoint": "/frontastic/action/star-wars/filters" } ] } ``` Before uploading your schema to the Studio, you need to deploy the action first to your production API hub instance. See the next section for how to do this. The `dynamic-filter` field type carries an additional field attribute which references a URL on the API hub of the product. Since you can implement arbitrary API hub endpoints as part of an `action` extension, this extension type is used for implementing the actual fetching. You can identify the action extension by looking at the path mentioned in `dynamicFiltersEndpoint`. This one starts with `/frontastic/action`, which is the URL base path for such extensions. Find more in the [developing an action extension article](/frontend-development/developing-an-action-extension.md). ## Implement the action to fetch the filters ```typescript export default { actions: { 'star-wars': { filters: (request: Request, actionContext: ActionContext): Response => { return { statusCode: 200, body: JSON.stringify([ { field: 'textSearch', label: 'Text search', type: 'text', translatable: false, }, { field: 'lightSideOnly', label: 'Only light side?', type: 'boolean', }, ]), }; }, }, }, }; ``` Action registration works as with every action through the `index.ts` export. In this example, the action code doesn't fetch dynamic attributes from a backend but instead returns static JSON defining 2 fields (`textSearch` and `lightSaberOnly`). The action can return any filter fields of any [schemas](/frontend-development/schemas.md) including (for example) `enum` or `translatable` fields. **You need to ensure that each `field` name is unique within a single dynamic filter set.** A `dynamic-filter` action underlies the usual timeout constraints of Studio and should so not take more than 100ms to run. In addition, it's important not to flood the Studio with a huge number of fields or `enum`-values. We recommend no more than 30 fields overall and 20 values for an `enum`. ## Test dynamic filters in the Studio To test dynamic filters in the Studio, upload the data source schema you created and then create a data source configuration within a page folder. Then you'll be able to add filters dynamically, as shown in the following gif for a data source: ![Button for adding a data source filter](https://docs.commercetools.com/frontend-development/images/migrated/601938e-dynamic_filter.gif) For dynamic pages, after uploading the created dynamic page schema, you can test the dynamic filters in the Studio. To do so, create a dynamic page rule and select the corresponding field in **Page rule criteria > Select criterion**. ## Configuration received from dynamic filters In the data source implementation, you'll receive the configured dynamic filters in the following format: ```json { "streamId": "515869c1-d45d-4ef5-b213-5c48879a43c8", "type": "example/star-wars-character", "name": "Star wars character", "configuration": { "characterFilters": { "filters": [ { "field": "textSearch", "type": "text" }, { "field": "lightSideOnly", "type": "boolean" } ], "values": { "textSearch": "luke", "lightSideOnly": true } } } } ``` The `characterFilters` field (which is of type `dynamic-filter` contains a hashmap of `values` that reflects the actual values entered by the user in the Studio. It also contains a stripped-down list of the filter definitions used to provide you: a) with the correct order of the filters b) with the types you assigned the filters Both might be relevant for translating them back into queries towards your backend system. ## Related pages - [Area overview page with navigation](/frontend-development.md) - [Previous page: Dynamic configuration from the browser](/frontend-development/dynamic-configuration-from-the-browser.md) - [Next page: Using a session](/frontend-development/using-a-session.md)