---
title: "Dynamic Filter Range Filters Guide"
slug: "dynamic-filter-range-filters-guide"
description: "Guia avancado de ranges no filtro dinamico, cobrindo variantes inline, shapes aceitos no payload, normalizacao backend e semantica das operacoes."
doc_type: "reference"
document_kind: "host-guide"
component: "table"
category: "data-crud"
audience:
  - "host"
  - "frontend"
  - "backend"
  - "architect"
level: "enterprise"
status: "active"
owner: "praxis-ui"
tags:
  - "range"
  - "date-range"
  - "time-range"
  - "price-range"
  - "dynamic-filter"
order: 28
icon: "swap_horiz"
toc: true
sidebar: true
search_boost: 1.25
reading_time: 20
estimated_setup_time: 45
version: "1.0"
related_docs:
  - "dynamic-filter-architecture-overview"
  - "dynamic-filter-payload-contract"
  - "dynamic-fields-inline-components-guide"
  - "dynamic-fields-inline-filter-runtime-contract"
  - "dynamic-fields-inline-filter-catalog"
  - "table-overview"
keywords:
  - "BETWEEN"
  - "BETWEEN_EXCLUSIVE"
  - "OUTSIDE_RANGE"
  - "minPrice"
  - "startDate"
source_of_truth:
  - "projects/praxis-table/src/lib/components/praxis-filter/praxis-filter.component.ts"
  - "projects/praxis-table/src/lib/components/praxis-filter/praxis-filter.component.spec.ts"
  - "projects/praxis-table/src/lib/filter-settings/filter-settings.component.ts"
  - "projects/praxis-dynamic-fields/docs/dynamic-fields-inline-components-guide.md"
  - "../praxis-metadata-starter/src/main/java/org/praxisplatform/uischema/extension/CustomOpenApiResolver.java"
  - "../praxis-metadata-starter/src/main/java/org/praxisplatform/uischema/filter/range/RangePayloadNormalizer.java"
  - "../praxis-metadata-starter/src/main/java/org/praxisplatform/uischema/filter/range/RangeBoundAliasRegistry.java"
  - "../praxis-metadata-starter/src/main/java/org/praxisplatform/uischema/filter/specification/GenericSpecificationsBuilder.java"
  - "../praxis-metadata-starter/docs/examples/filter-dto.md"
last_updated: "2026-03-07"
---

# Dynamic Filter Range Filters Guide

## Objetivo

Documentar com precisão enterprise como funcionam os filtros de faixa no ecossistema Praxis, da escolha do `controlType` até a predicate final aplicada no backend.

Nota de trilha:

- este guia cobre a semantica de range da feature
- a implementacao dos inline range components fica na suite especializada de `praxis-dynamic-fields`

## Pré-requisitos

- Familiaridade com `PraxisFilter`, `dynamic-fields` e `GenericFilterDTO`.
- Conhecimento básico de `priceRange`, `rangeSlider`, `dateRange` e `timeRange`.
- Backend configurado com `@Filterable` para operações de range.

## Quando usar

Use este guia quando precisar:

- modelar filtros monetários, numéricos, de data ou de hora;
- entender como a UI envia ranges;
- decidir entre formatos canônicos de payload;
- explicar por que `BETWEEN_EXCLUSIVE` e `OUTSIDE_RANGE` não se comportam como `BETWEEN`.

## Tipos de range cobertos

No runtime Angular, os cenários principais são:

- `rangeSlider` / `inlineRange`
- `priceRange` / `inlineCurrencyRange`
- `dateRange` / `inlineDateRange`
- `timeRange` / `inlineTimeRange`

Além disso, controles especializados como `inlineRating`, `inlineDistanceRadius` e `inlineScorePriority` também reutilizam semântica de faixa.

## Como a UI resolve ranges

### Toolbar compacta

O `PraxisFilter` converte `controlType` genérico em variante inline por padrão quando existe equivalente dedicado. As flags abaixo funcionam como opt-out:

- `useInlineRangeVariant`
- `useInlineDateRangeVariant`
- `useInlineTimeRangeVariant`

Para monetário, `priceRange` já aponta para a experiência compacta específica do filtro.

### Formulario avancado

No formulario avancado, ranges compostos devem ocupar a linha completa. A regra
evita comparar verticalmente um controle com duas entradas internas contra um
campo simples, preserva leitura de label/hint e mantem espaco suficiente para
`Min`/`Max`, icones e sufixos.

### Filter settings

`filter-settings.component.ts` participa da história porque ele controla:

- quais tipos aparecem como opção no editor;
- como o host promove um campo para a toolbar compacta.

### Regra de UX importante

Range vazio não deve virar critério ativo.

Esse comportamento precisa aparecer na doc porque já existe proteção no runtime e em teste para ignorar objeto vazio no `advanced change payload`.

## Shapes aceitos no payload

### Lista canônica

Para operações não exclusivas, o backend aceita:

- `[min]`
- `[min, max]`
- `[null, max]`

Exemplo:

```json
{
  "salaryRange": [6500, 15000]
}
```

### Objeto canônico

Também são aceitos objetos descritivos, especialmente úteis para clareza na UI e no host:

```json
{
  "salaryRange": {
    "minPrice": 6500,
    "maxPrice": 15000,
    "currency": "BRL"
  }
}
```

```json
{
  "scoreRange": {
    "min": 10,
    "max": 20
  }
}
```

```json
{
  "admissionPeriod": {
    "startDate": "2026-03-01",
    "endDate": "2026-03-31"
  }
}
```

## Bounds aceitos pelo backend

O `RangeBoundAliasRegistry` reconhece nomes de bounds publicados pela plataforma para clareza por domínio.

Exemplos relevantes:

- datas: `startDate`, `fromDate`, `start`, `from`, `endDate`, `toDate`, `end`, `to`
- monetário: `minPrice`, `valorMin`, `min`, `from`, `start`, `maxPrice`, `valorMax`, `max`, `to`, `end`

Regra editorial:

- use nomes canônicos em novos contratos: `{ min, max }`, `{ minPrice, maxPrice }` ou `{ startDate, endDate }`.

## Operações suportadas

### `BETWEEN`

Semântica:

- com dois limites: intervalo inclusivo;
- com um limite inferior: `>=`;
- com um limite superior: `<=`.

### `BETWEEN_EXCLUSIVE`

Semântica:

- exige exatamente dois limites não nulos;
- aplica `>` no lower bound e `<` no upper bound.

Consequência prática:

- não aceite payload parcial;
- não documente `[null, max]` nem `[min]` para essa operação.

### `NOT_BETWEEN`

Semântica:

- com dois limites: negação do intervalo;
- com limite único: transforma a operação em comparação simples oposta.

### `OUTSIDE_RANGE`

Semântica:

- com dois limites: `< lower OR > upper`;
- com limite único: segue comparação unilateral fora da faixa.

## Regras de normalização que precisam estar na doc

1. Payload escalar é inválido.

```json
{ "salaryRange": 1500 }
```

Não há flag canônica no starter para preservar payload escalar em operações de range.

2. Bounds invertidos podem ser normalizados.

Se o usuário enviar `min > max`, o normalizador pode fazer swap para preservar semântica consistente.

3. Upper-only deve preservar nulidade explícita do lower.

```json
{ "salaryRange": [null, 15000] }
```

4. Objeto sem bound efetivo é inválido.

```json
{ "salaryRange": { "minPrice": null, "maxPrice": null } }
```

5. Fontes conflitantes para o mesmo range devem falhar.

Não misture duas origens diferentes para o mesmo campo.

## Regras por domínio

### Numérico genérico

Use `rangeSlider` quando o intervalo for numérico puro e houver benefício em slider/preset.

### Monetário

Use `priceRange` ou `inlineCurrencyRange` quando precisar:

- máscara monetária;
- formatação por locale;
- resumo de faixa monetária;
- combinação de slider e inputs numéricos.

### Data

Use `dateRange` ou `inlineDateRange` quando o campo representar período calendárico.

No backend, `LocalDate` exige atenção especial: algumas predicates trabalham com início do dia e início do próximo dia para manter semântica correta.

### Hora

Use `timeRange` ou `inlineTimeRange` quando a busca depender de faixa horária pura, sem necessidade de data.

## O que documentar para hosts

Em qualquer doc host-facing de range, explique sempre:

- qual `controlType` foi adotado;
- se o host manteve o padrão inline ou aplicou opt-out explícito;
- qual payload o host deve enviar;
- qual operação backend está associada;
- quais formatos inválidos geram `400`.

## Boas práticas finais

1. Prefira objeto canônico na documentação funcional e lista canônica na explicação de normalização.
2. Não publique payload escalar como exemplo de operação de range.
3. Relacione sempre a UI de range com a operação `@Filterable` correspondente.
4. Documente claramente diferença entre `BETWEEN`, `BETWEEN_EXCLUSIVE`, `NOT_BETWEEN` e `OUTSIDE_RANGE`.
5. Em casos críticos, cite explicitamente que o `praxis-metadata-starter` é quem canonicaliza o range antes da specification.
