# Filters

Filters allow you to better scope the index queries for records you are looking for.

Each filter is configured in a class with a few dedicated [methods and options](#filter-options). To use a filter on a resource you must [register it](#register-filters) and it will be displayed on the <Index /> view.

## Filter options

<Option name="`self.name`">

`self.name` is what is going to be displayed to the user in the filters panel.

```ruby
self.name = "User names filter"
```

<VersionReq version="3.14.0" />

```ruby
self.name = -> { I18n.t("avo.filter.name") }
```
Within this block, you gain access to all attributes of `Avo::ExecutionContext` along with the `arguments`.

</Option>

<Option name="`self.button_label`">

The value of `self.button_label` is the label displayed on the button that applies the filter.

```ruby
self.button_label = "Filter by user names"
```

<VersionReq version="3.14.0" />

```ruby
self.button_label = -> { I18n.t("avo.filter.button_label") }
```
Within this block, you gain access to all attributes of `Avo::ExecutionContext` along with the `arguments`.

</Option>

<Option name="`self.visible`">

You may want to show/hide the filter in some scenarios. You can do that using the `self.visible` attribute.

Inside the visible block you can acces the following variables and you should return a boolean (`true`/`false`).

```ruby
  self.visible = -> do
    #   You have access to:
    #   block
    #   context
    #   current_user
    #   params
    #   parent_model
    #   parent_resource
    #   resource
    #   view
    #   view_context
    true
  end
```
</Option>

<Option name="`self.empty_message`">

There might be times when you will want to show a message to the user when you're not returning any options.

More on this in the [Empty message guide](#empty-message-text).
</Option>
<Option name="`options`">

Some filters allow you to pass options to the user. For example on the [select filter](#select_filter) you can set the options in the dropdown, and on the [boolean filter](#boolean_filter) you may set the checkbox values.
Each filter type has their own `options` configuration explained below.

In the `options` method you have access to the `request`, `params`, `context`, `view_context`, and `current_user` objects.
</Option>

<Option name="`apply`">

The `apply` method is what is going to be run when Avo fetches the records on the <Index /> view.

It recieves the `request` form which you can get all the `params` if you need them, it gets the `query` which is the query Avo made to fetch the records. It's a regular [Active Record](https://guides.rubyonrails.org/active_record_querying.html) which you can manipulate.

It also receives the `values` variable which holds the actual choices the user made on the front-end for the [options](#options) you set.
</Option>

<Option name="`default`">

You may set default values for the `options` you set. For example you may set which option to be selected for the [select filter](#select_filter) and which checkboxes to be set for the [boolean filter](#boolean_filter).

In the `default` method you have access to the `request`, `params`, `context`, `view_context`, and `current_user` objects.
</Option>

<Option name="`react`">

This is a hook in which you can change the value of the filter based on what other filters have for values.

More on this in the [React to filters guide](#react-to-filters)
</Option>

## Register filters

In order to use a filter you must register it on a `Resource` using the `filter` method inside the `filters` method.

```ruby{9}
class Avo::Resources::Post < Avo::BaseResource
  self.title = :name

  def fields
    field :id, as: :id
  end

  def filters
    filter Avo::Filters::Published
  end
end
```

## Filter types

Avo has several types of filters available [Boolean filter](#Boolean%20Filter), [Select filter](#Select%20Filter), [Multiple select filter](#Multiple%20select%20filter), [Text filter](#Text%20Filter) and since version <Version version="3.11.8" /> [Date time filter](#Date%20time%20Filter).

<Image src="/assets/img/filters.png" width="404" height="727" alt="Avo filters" />

### Filter values

Because the filters get serialized back and forth, the final `value`/`values` in the `apply` method will be stringified or have the stringified keys if they are hashes. You can declare them as regular hashes in the `options` method, but they will get stringified.

<Option name="Boolean Filter">

The boolean filter is a filter where the user can filter the records using one or more checkboxes.

To generate one run:

```bash
bin/rails generate avo:filter featured
```
or
```bash
bin/rails generate avo:filter featured --type boolean
```

Here's a sample filter

```ruby
class Avo::Filters::Featured < Avo::Filters::BooleanFilter
  self.name = 'Featured filter'

  # `values` comes as a hash with stringified keys
  # Eg:
  # {
  #   'is_featured': true
  # }
  def apply(request, query, values)
    return query if values['is_featured'] && values['is_unfeatured']

    if values['is_featured']
      query = query.where(is_featured: true)
    elsif values['is_unfeatured']
      query = query.where(is_featured: false)
    end

    query
  end

  def options
    {
      is_featured: "Featured",
      is_unfeatured: "Unfeatured"
    }
  end

  # Optional method to set the default state.
  # def default
  #   {
  #     is_featured: true
  #   }
  # end
end
```

Each filter file comes with a `name`, `apply`, and `options` methods.

The `name` method lets you set the name of the filter.

The `apply` method is responsible for filtering out the records by giving you access to modify the `query` object. The `apply` method also gives you access to the current `request` object and the passed `values`. The `values` object is a `Hash` containing all the configured `options` with the option name as the key and `true`/`false` as the value.

```ruby