# Using dynamic_filter method
dynamic_filter :tags,
  suggestions: -> {
    [
      {
        value: 1,
        label: 'one', # or params[:something]
        avatar: 'https://images.unsplash.com/photo-1560363199-a1264d4ea5fc?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&w=256&h=256&fit=crop',
      },
      # ...
    ]
  }
```
:::

</Option>

<Option name="`fetch_values_from`">

<VersionReq version="3.13" />

:::warning
This option is compatible **only** with `tags` filters.
:::

In some cases, you may need to retrieve values dynamically from an API. The `fetch_values_from` option allows you to provide a URL from which the filter will suggest values, functioning similarly to the `fetch_values_from` option in the tags field.

When a user searches for a record, the filter's input will send a request to the server to fetch records that match the query.

##### Default value

`nil`

:::info
If you're using a `filterable` field the `fetch_values_from` are fetched from the field.

```ruby
field :tags, as: :tags,
  fetch_values_from: -> { "/avo-filters/resources/cities/tags" }
  filterable: true
```
:::

#### Possible values

- String
```ruby
fetch_values_from: "/avo-filters/resources/cities/tags"
```

- Proc that evaluates to a string.
```ruby
fetch_values_from: -> { "/avo-filters/resources/cities/tags" }
```

The endpoint should handle two different scenarios:

1. **Search functionality**: When a user types in the filter input, the endpoint receives the user input as `q` in the params (`params["q"]`)
2. **Initial load**: When the filter already has selected values (like on page load), the endpoint receives an array of values in `params[:value]` to fetch the corresponding labels

The endpoint should return an array of objects with the keys `value`, `label` and optionally `avatar`.

::: code-group
```ruby{3-33} [app/controllers/avo/cities_controller.rb]
class Avo::CitiesController < Avo::ResourcesController
  def tags
    if params[:value].present?
      # Handle initial load: return labels for selected values
      # params[:value] contains an array of selected values
      selected_cities = City.where(id: params[:value])
      render json: selected_cities.map do |city|
        {
          value: city.id,
          label: city.name,
          avatar: city.avatar_url
        }
      end
    elsif params["q"].present?
      # Handle search: return cities matching the query
      cities = City.where("name ILIKE ?", "%#{params["q"]}%").limit(10)
      render json: cities.map do |city|
        {
          value: city.id,
          label: city.name,
          avatar: city.avatar_url
        }
      end
    else
      # Handle empty state: return some default suggestions
      render json: [
        {
          value: 1,
          label: "New York",
          avatar: "https://images.unsplash.com/photo-1560363199-a1264d4ea5fc?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&w=256&h=256&fit=crop"
        }
      ]
    end
  end
end
```

```ruby{5-11} [config/routes.rb]
Rails.application.routes.draw do
  # your routes...
end

if defined? ::Avo
  Avo::Engine.routes.draw do
    scope :resources do
      get "cities/tags", to: "cities#tags"
    end
  end
end
```
:::

</Option>

<Option name="`options`">

<VersionReq version="3.10.10" />

Customize the options **for select type filters**. **This is available only for select type filters** and determines the options visible in the select dropdown.

##### Default value

Fetched from field if bond to a field or `[]`

#### Possible values

An array or hash where the key-value pairs represent the options.

- If a hash is provided, the key is the option label and the value is the option value.
- If an array is provided, the array elements are used as both the option value and the option label.

##### Usage examples
###### Array
```ruby{3}
dynamic_filter :version,
  type: :select,
  options: ["Label 1", "Label 2"]
```

###### Hash (with invert)
```ruby{3-6}
dynamic_filter :version,
  type: :select,
  options: {
    value_1: "Label 1",
    value_2: "Label 2"
  }.invert
```

###### Hash (without invert)
```ruby{3-6}
dynamic_filter :version,
  type: :select,
  options: {
    "Label 1" => :value_1,
    "Label 2" => :value_2
  }
```
</Option>

<Option name="`render_apply_button`">

Controls whether the "Apply" button should be rendered in the filter interface.

##### Default value

`true`

#### Possible values

Boolean value (`true` or `false`).

When set to `false`, the apply button will be hidden from the filter interface. This is particularly useful when combined with `apply_on_select: true` to create an immediate filtering experience.

##### Usage examples

```ruby{3}
dynamic_filter :status,
  type: :select,
  render_apply_button: false
```

```ruby{4-5}
field :status,
  as: :select,
  filterable: {
    render_apply_button: false,
    apply_on_select: true,
    options: ["active", "inactive", "pending"]
  }
```

</Option>

<Option name="`apply_on_select`">

Controls whether the filter should be applied immediately when the selected value changes, without requiring the user to click the "Apply" button.

##### Default value

`false`

#### Possible values

Boolean value (`true` or `false`).

When set to `true`, the filter will automatically apply as soon as the user selects or changes a value. This creates a more responsive user experience, especially when combined with `render_apply_button: false`.

##### Usage examples

```ruby{3-4}
dynamic_filter :category,
  type: :select,
  apply_on_select: true,
  render_apply_button: false
```

```ruby{4-5}
field :priority,
  as: :select,
  filterable: {
    apply_on_select: true,
    render_apply_button: false,
    options: ["high", "medium", "low"]
  }
```

</Option>

<Option name="`humanized_value`">

Allows you to customize how filter values are displayed in the filter interface by providing humanized, user-friendly representations of the internal filter values.

##### Default value

`value` - The filter will display the raw filter values.

#### Possible values

A lambda/proc that returns a string representing the humanized value. Within the function, you have access to the `value` and `filter` object which contains the current filter's condition, as well as all attributes of `Avo::ExecutionContext`. Additionally `parent_record` (when the filter is applied to an association) is available.

##### Usage examples

```ruby{4-11}
field :is_capital,
  as: :boolean,
  filterable: {
    humanized_value: -> {
      case filter.condition
      when "is_true"
        "yes"
      when "is_false"
        "no"
      end
    }
  }
```

```ruby{4-8}
    dynamic_filter label: "Tags with fetch_values_from",
      type: :tags,
      fetch_values_from: -> { "/avo-filters/resources/cities/tags" },
      humanized_value: -> {
        City.controller_suggestions.select do |suggestion|
          suggestion[:value].to_s.in?(value.split(","))
        end.map { _1[:label] }.join(", ")
      }
```

</Option>

<Option name="`humanized_condition`">

<VersionReq version="3.24.0" />

Allows you to customize how filter conditions are displayed in the filter's pill interface by providing humanized, user-friendly representations of the internal filter conditions.

##### Default value

`condition` - The filter will display the auto-generated label for the filter condition.

#### Possible values

A lambda/proc that returns a string representing the humanized value. Within the function, you have access to the `condition` and `filter` object which contains the current filter's condition, as well as all attributes of `Avo::ExecutionContext`. Additionally `parent_record` (when the filter is applied to an association) is available.

##### Usage examples

```ruby{5-7}
dynamic_filter :author,
  type: :tags,
  icon: "heroicons/outline/users",
  conditions: {},
  humanized_condition: -> {
    (filter.value.split(",").count > 1) ? "are" : "is"
  },
  query: -> {
    query.where(author_id: filter_param.value.split(","))
  }
```
</Option>

## Guides & Tutorials

<Option name="How to filter associations">

Learn how to effectively filter records based on their associations in Avo. This video tutorial demonstrates how to set up and use dynamic filters to query records through the attributes of their associations, enabling powerful and flexible data filtering capabilities.

<div style="position: relative; padding-bottom: 56.25%; height: 0;"><iframe src="https://www.loom.com/embed/d8bd49086d014d77a3013796c8480339?sid=aaaec555-b19f-429b-b0a7-e998a2d2128e" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"></iframe></div>

#### `belongs_to` example

```ruby{5-11,16-18}