Table filters: a filter the page was loaded with cannot be changed or cleared from its column header #622
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
performance
security
tier
1
tier
2
tier
3
tier/4
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Postulo/postulo#622
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found on 2026-09-29 in a read-only review of postulo at
95348908d, reading the table filter templates andTable.given, then driving Companies in headless Chromium with every request answered in-process by the test client.Checked again on 2026-10-01 against
mainat0a5cad587: still present.Every column filter is drawn twice and both copies are posted under the same name: once in the column header and once in the phone block Narrow.
Table.giventakes the first non-empty value, on the assumption that "the copy nobody typed in narrows nothing". That only holds while the untouched copy is empty. The Narrow block sits inside the filter form, outside the region a live filter swaps, so it keeps the value the page was rendered with, and it comes first in the form's element order. So once a page has been loaded with a filter in its address, the header box for that filter no longer does anything: clearing it or typing something else leaves the table filtered by the old value. Only Clear gets out.core/tables.py:551-558,Table.given:return next((value.strip() for value in self.params.getlist(name) if value.strip()), "").templates/partials/table/narrow.html:15-33, the second copy, included inside the filter form attemplates/jobs/company_list.html:89(form#company-filters,:77-90, before the swapped{% partial table %}at:92),templates/jobs/listing_list.html:154andtemplates/applications/partials/filters.html:45.templates/cotton/table/filter.html:31-41: the header copy,hx-include="#{{ form_id }}", so every live request posts the whole form, Narrow block included.cotton/table/filter.html:16-18,partials/table/narrow.html:7-9,cotton/table/head.html:55-56./jobs/companies/?name=acme(a saved view, a bookmark, a reload after filtering, or Back, which reloads from the server since #226). Both copies are rendered withacme; in the form's elements the Narrow copy (filter-name-narrow) comes before the header copy (filter-name).?q=&name=acme&…&name=&…: the Narrow copy first.given("name")answersacme, and the table still shows only Acme while the box says nothing.gloin the same box. The request is?…&name=acme&…&name=glo&…, and the table still shows Acme.The same happens with scripts off (the Apply button posts both copies in the same order), and the other way round on a phone: a field changed in Narrow is overridden by the header copy if that one was filled when the page loaded. Companies, Listings and Applications are all affected.
cotton/table/head.html:47-56), sonarrow.htmlcan become a list of the filterable columns that opens the matching header disclosure, rather than a second set of inputs. If two sets of inputs must stay, they cannot share a name: give the Narrow copies their own names (for examplenarrow-<name>), read them only when the request came from the Narrow block's own Apply button, and read the header names otherwise. Either way, correct the three comments above. #313 and #314 rework these forms; this should land with them or before them.Done when
tests/test_tables.pyrenders Companies, Listings and Applications with a filter in the address and asserts that each filter name is posted by one control only.tests/e2e/test_saved_views.py) loads/jobs/companies/?name=…, clears the Name header box and sees the whole list, then types another name and sees that company.