# `Backpex.Filters.Range`
[🔗](https://github.com/naymspace/backpex/blob/0.18.3/lib/backpex/filters/range.ex#L1)

The range filter renders two input fields of the same type. Backpex offers the `:date`, `:datetime` and the `number` type.

See the following example for an implementation of a date range filter.

    defmodule MyAppWeb.Filters.DateRange do
      use Backpex.Filters.Range

      @impl Backpex.Filters.Range
      def type, do: :date

      @impl Backpex.Filter
      def label, do: "Date Range (begins at)"
    end

> #### Information {: .info}
>
> Note that the query function is already implemented via `Backpex.Filters.Range`.

> #### `use Backpex.Filters.Range` {: .info}
>
> When you `use Backpex.Filters.Range`, the `Backpex.Filters.Range` module will set `@behavior Backpex.Filters.Range`.
> In addition it will add a `render` and `render_form` function in order to display the corresponding filter.
> It will also implement the `Backpex.Filter.query` function to define a range query.

# `type`

```elixir
@callback type() :: :date | :datetime | :number
```

The type return value defines the rendered input fields of the range filter.

# `changeset`

Validates range filter values based on the filter type.

Validates that:
- Date values are valid ISO 8601 dates (for :date and :datetime types)
- Number values are valid integers or floats (for :number type)
- Start is not greater than end when both are provided

# `date?`

Checks if a string is a valid ISO 8601 date.

## Examples

    iex> Backpex.Filters.Range.date?("2024-01-01")
    true

    iex> Backpex.Filters.Range.date?("2023-12-31")
    true

    iex> Backpex.Filters.Range.date?("2000-06-15")
    true

    iex> Backpex.Filters.Range.date?("not-a-date")
    false

    iex> Backpex.Filters.Range.date?("2024-13-01")
    false

    iex> Backpex.Filters.Range.date?("2024-01-32")
    false

    iex> Backpex.Filters.Range.date?("")
    false

# `do_query`

# `maybe_parse`

Parses a single value based on the specified type.

The third parameter `is_end?` determines whether to treat the value as an end boundary
(which affects datetime parsing by adding 23:59:59 instead of 00:00:00).

## Examples

    iex> Backpex.Filters.Range.maybe_parse(:number, "")
    nil

    iex> Backpex.Filters.Range.maybe_parse(:date, "")
    nil

    iex> Backpex.Filters.Range.maybe_parse(:datetime, "")
    nil

    iex> Backpex.Filters.Range.maybe_parse(:date, "2024-06-15")
    "2024-06-15"

    iex> Backpex.Filters.Range.maybe_parse(:date, "not-a-date")
    nil

    iex> Backpex.Filters.Range.maybe_parse(:date, "2024-13-45")
    nil

    iex> Backpex.Filters.Range.maybe_parse(:datetime, "2024-01-01", false)
    "2024-01-01T00:00:00+00:00"

    iex> Backpex.Filters.Range.maybe_parse(:datetime, "2024-12-31", true)
    "2024-12-31T23:59:59+00:00"

    iex> Backpex.Filters.Range.maybe_parse(:datetime, "invalid")
    nil

# `maybe_parse_range`

Parses both start and end values for a range filter.

## Examples

    iex> Backpex.Filters.Range.maybe_parse_range(:number, "10", "100")
    {10, 100}

    iex> Backpex.Filters.Range.maybe_parse_range(:number, "", "100")
    {nil, 100}

    iex> Backpex.Filters.Range.maybe_parse_range(:number, "10", "")
    {10, nil}

    iex> Backpex.Filters.Range.maybe_parse_range(:date, "2024-01-01", "2024-12-31")
    {"2024-01-01", "2024-12-31"}

    iex> Backpex.Filters.Range.maybe_parse_range(:datetime, "2024-01-01", "2024-12-31")
    {"2024-01-01T00:00:00+00:00", "2024-12-31T23:59:59+00:00"}

# `parse_float_or_int`

Parses a string value as either an integer or float.

Prefers integer representation for whole numbers.

## Examples

    iex> Backpex.Filters.Range.parse_float_or_int("42")
    42

    iex> Backpex.Filters.Range.parse_float_or_int("-10")
    -10

    iex> Backpex.Filters.Range.parse_float_or_int("0")
    0

    iex> Backpex.Filters.Range.parse_float_or_int("3.14")
    3.14

    iex> Backpex.Filters.Range.parse_float_or_int("-2.5")
    -2.5

    iex> Backpex.Filters.Range.parse_float_or_int("0.0")
    0.0

    iex> Backpex.Filters.Range.parse_float_or_int("not-a-number")
    nil

    iex> Backpex.Filters.Range.parse_float_or_int("abc123")
    nil

    iex> Backpex.Filters.Range.parse_float_or_int("12abc")
    nil

    iex> Backpex.Filters.Range.parse_float_or_int("")
    nil

# `query`

# `range_input_set`

## Attributes

* `form` (`:any`) (required)
* `type` (`:atom`) (required)
* `value` (`:any`) (required)
* `live_resource` (`:atom`) (required)
* `errors` (`:list`) - Defaults to `[]`.

# `render`

## Attributes

* `value` (`:map`) (required)

# `render_form`

## Attributes

* `form` (`:any`) (required)
* `field` (`:atom`) (required)
* `value` (`:any`) (required)
* `type` (`:atom`) (required)
* `live_resource` (`:atom`) (required)
* `errors` (`:list`) - Defaults to `[]`.

# `render_type`

Returns the render type for form inputs.

Converts `:datetime` to `:date` since HTML date inputs are used for datetime filters.

## Examples

    iex> Backpex.Filters.Range.render_type(:datetime)
    :date

    iex> Backpex.Filters.Range.render_type(:date)
    :date

    iex> Backpex.Filters.Range.render_type(:number)
    :number

---

*Consult [api-reference.md](api-reference.md) for complete listing*
