@@ -7,14 +7,15 @@ building blocks for rendering those filters as a UI:
77 index pages: a turbo frame, a `BorderBox`, lazy loading, action buttons
88 (Apply / Close), and the filter rows themselves. Use this when you want
99 the standard OpenProject filter dropdown experience.
10- * **`Filters::FilterForm `** — just the filter rows plus the "Add filter"
11- select, rendered as a primer form object . Use this when you want filters
12- inside *your own* form (e.g. a configuration dialog) or when the
10+ * **`Filters::FilterFormComponent `** — just the filter rows plus the "Add
11+ filter" select, rendered as a ViewComponent . Use this when you want
12+ filters inside *your own* form (e.g. a configuration dialog) or when the
1313 surrounding chrome of `FilterComponent` doesn't fit.
1414
15- Internally `FilterComponent` delegates to `FilterForm`, so the two stay in
16- lockstep — `FilterForm` is the single source of truth for which inputs to
17- render, and `FilterComponent` adds the wrapping chrome on top.
15+ Internally `FilterComponent` delegates to `FilterFormComponent`, so the two
16+ stay in lockstep — `FilterFormComponent` is the single source of truth for
17+ which inputs to render, and `FilterComponent` adds the wrapping chrome on
18+ top.
1819
1920## Filter::FilterComponent
2021
@@ -50,17 +51,17 @@ rendering until the dropdown is opened (a skeleton is shown in the meantime).
5051
5152<%= embed OpenProject ::Filter ::FiltersComponentPreview , :default , panels : %i[ preview source ] %>
5253
53- ## Filters::FilterForm
54+ ## Filters::FilterFormComponent
5455
55- For everything that isn 't a standard filter dropdown, render `FilterForm`
56- inside any `primer_form_with` block. It accepts the parent's primer form
57- builder so its inputs sit at the top level of the surrounding form (field
58- names like `operator_< filter> ` and `< filter > _value` — same as
59- `FilterComponent`).
56+ For everything that isn 't a standard filter dropdown, render
57+ `FilterFormComponent` inside any `primer_form_with` block. It accepts the
58+ parent's primer form builder so its inputs sit at the top level of the
59+ surrounding form (field names like `operator_< filter> ` and `< filter > _value`
60+ — same as `FilterComponent`).
6061
6162### Default usage
6263
63- `wrap_with_controller: true` makes the form emit its own
64+ `wrap_with_controller: true` makes the component emit its own
6465`< div class ="op-filters-form -expanded " data-controller ="filter--filters-form "> `
6566wrapper. Use this in any standalone embed (a dialog body, a settings page,
6667etc.) where there's no surrounding sub-header attaching the controller for
@@ -78,11 +79,11 @@ hidden until the user picks them from the "Add filter" select.
7879
7980### Submitting via a hidden field
8081
81- By default the form relies on the Stimulus controller to redirect via
82+ By default the component relies on the Stimulus controller to redirect via
8283`sendForm` (the projects-index style). Inside a regular form you usually
8384want the filter state to ride along with a normal submit instead. Pass
84- `hidden_input_name:` and the form renders a hidden input whose value is
85- kept in sync with the serialized filter selections.
85+ `hidden_input_name:` and the component renders a hidden input whose value
86+ is kept in sync with the serialized filter selections.
8687
8788`output_format:` controls the serialization:
8889
@@ -97,25 +98,25 @@ The host server receives the canonical string in
9798
9899### Combining with non-filter inputs
99100
100- `FilterForm` is a regular primer form object, so it composes with other
101- forms via `Primer::Forms::FormList`. All children share the same builder
102- and therefore submit through the same `< form > `.
101+ `FilterFormComponent` composes with other forms via
102+ `Primer::Forms::FormList`. All children share the same builder and
103+ therefore submit through the same `< form > `.
103104
104105<%= embed OpenProject ::Filter ::FilterFormPreview , :combined_with_other_inputs , panels : %i[ preview source ] %>
105106
106107### Inside a clipping container (dialogs)
107108
108- ng-select dropdowns are positioned by their parent; if the form lives
109+ ng-select dropdowns are positioned by their parent; if the component lives
109110inside a Primer dialog or any other overflow-clipping container, the
110111dropdown gets cut off. Pass `autocomplete_append_to:` with a CSS selector
111112that ng-select can resolve (typically the dialog id, or `"body"`) — the
112- form forwards it as `appendTo` to every autocompleter it renders.
113+ component forwards it as `appendTo` to every autocompleter it renders.
113114
114115```erb
115116<%%= primer_form_with(...) do |f| %>
116117 <%%= render(
117- Filters::FilterForm .new(
118- f,
118+ Filters::FilterFormComponent .new(
119+ builder: f,
119120 query: @query,
120121 wrap_with_controller: true,
121122 hidden_input_name: "filters",
@@ -130,7 +131,7 @@ form forwards it as `appendTo` to every autocompleter it renders.
130131| You want… | Use |
131132|----------------------------------------------------------|---------------------------|
132133| The standard OpenProject filter panel on an index page | `Filter::FilterComponent` |
133- | Filters inside a dialog or a non-filter form | `Filters::FilterForm ` + `hidden_input_name:` |
134+ | Filters inside a dialog or a non-filter form | `Filters::FilterFormComponent ` + `hidden_input_name:` |
134135
135136## Stimulus controller placement
136137
@@ -148,26 +149,27 @@ to forget about:
148149That's why `Filter::FilterComponent` does *not* attach the controller
149150itself — the surrounding `IndexSubHeaderComponent` does, so quick filter
150151and advanced form share one. For standalone embeds without a co-located
151- quick filter, `FilterForm `'s `wrap_with_controller: true` is the right
152- default.
152+ quick filter, `FilterFormComponent `'s `wrap_with_controller: true` is the
153+ right default.
153154
154155## Compatibility with the legacy `Query` (work packages)
155156
156- `Filters::FilterForm` reads three things off the query: `available_advanced_filters`,
157- `filters`, and `find_active_filter(name)`. The first two come from the
158- `Queries::Filters::AvailableFilters` concern, which the legacy work-package
159- `Query` model also includes. `find_active_filter` is defined directly on
160- `Queries::BaseQuery` and used to live only there — `Query` now mirrors it
161- with the same signature, so passing a `Query` (or any of its subclasses)
162- to `FilterForm` works exactly like passing a `BaseQuery` subclass.
157+ `Filters::FilterFormComponent` reads three things off the query:
158+ `available_advanced_filters`, `filters`, and `find_active_filter(name)`.
159+ The first two come from the `Queries::Filters::AvailableFilters` concern,
160+ which the legacy work-package `Query` model also includes.
161+ `find_active_filter` is defined directly on `Queries::BaseQuery` and used
162+ to live only there — `Query` now mirrors it with the same signature, so
163+ passing a `Query` (or any of its subclasses) to `FilterFormComponent` works
164+ exactly like passing a `BaseQuery` subclass.
163165
164166<%= embed OpenProject ::Filter ::FilterFormPreview , :for_a_work_package_query , panels : %i[ preview source ] %>
165167
166- What `FilterForm ` does *not* do for you on the legacy side: parsing the
167- form submission back into a `Query#filters` collection. The work-package
168- filter pipeline still uses its own serialization (URL `filters=[...]`
169- JSON / YAML in the DB), so a controller receiving a `FilterForm` submit
170- either needs to use `hidden_input_name:` with a format the existing
171- parser understands, or translate the `operator_ < name > ` / ` < name > _value`
172- fields by hand. The form renders fine either way; what to do with the
173- submitted values is the caller's call.
168+ What `FilterFormComponent ` does *not* do for you on the legacy side:
169+ parsing the form submission back into a `Query#filters` collection. The
170+ work-package filter pipeline still uses its own serialization (URL
171+ `filters=[...]` JSON / YAML in the DB), so a controller receiving a
172+ `FilterFormComponent` submit either needs to use `hidden_input_name:` with
173+ a format the existing parser understands, or translate the
174+ `operator_ < name > ` / ` < name > _value` fields by hand. The component renders
175+ fine either way; what to do with the submitted values is the caller's call.
0 commit comments