Skip to content

Reset & Apply

The library keeps two pieces of state separate:

  • An internal URLSearchParams that tracks what the form currently shows. It is updated on every change event automatically.
  • The actual URL (location.search). It is only written by setFiltersToUrl() and resetUrl(), never by change events.

That split is what lets you batch many field edits into a single history entry. To commit the internal state to the URL you call setFiltersToUrl — typically from an Apply button.

Apply

ts
const filter = new Filter({
  formAttr: 'data-filter-form="search"',
  filterAttr: 'data-filter',
});

filter.init();

document.querySelector('[data-filter-apply]')?.addEventListener('click', () => {
  filter.setFiltersToUrl(new URL(window.location.href));
});

setFiltersToUrl performs a single history.pushState from the current form state, so only one history entry is created no matter how many fields the user changed.

Reset

A native <button type="reset"> inside the form clears the inputs. Pair it with filter.resetUrl() to clear the URL params at the same time:

ts
document.querySelector('[data-filter-reset]')?.addEventListener('click', () => {
  filter.resetUrl();
});

Or call both explicitly if you don't have a native reset button:

ts
filter.resetDom();
filter.resetUrl();

Auto-apply on every change

If you want the URL to update on every change instead of only on Apply, listen for change yourself and call setFiltersToUrl:

ts
$form.addEventListener('change', () => {
  filter.setFiltersToUrl(new URL(window.location.href));
});

Each change becomes its own history entry. Sensible for small forms; bad for forms with many fields where each keystroke or scrub would create a useless entry.

Helper methods

MethodEffect
resetDom()form.reset() — clears the inputs but leaves the URL alone
resetUrl()Removes every known filter param from the URL via pushState
updateDom()Re-reads the URL and pushes it into the form (use after URL writes from outside the library)
getFilters()Returns the parsed { [type]: string[] } snapshot of the internal state
destroy()Removes all change and popstate listeners added by init() — call on component teardown

Combining with data fetching

The library does not fetch data. Wire your loader to popstate plus your own commit point (Apply click, or every change if you went auto-apply), and call it with filter.getFilters():

ts
const load = () => fetchResults(filter.getFilters());

window.addEventListener('popstate', load);
document.querySelector('[data-filter-apply]')!.addEventListener('click', load);

load();

Released under the MIT License.