AccrueAdmin.DataTableNav (accrue_admin v1.5.0)

Copy Markdown View Source

Shared push_patch navigation for the admin DataTable SPA filter contract.

The DataTable LiveComponent renders the filter <form> with phx-change/ phx-submit="data_table_filter" (parent-targeted — no phx-target). Each list LiveView delegates that event here, which merges the submitted filter params into the table's canonical path and push_patches the result.

Why merge instead of append

socket.assigns.table_path already carries any pre-existing query string. In organization mode it is "/billing/customers?org=acme" (from each page's scoped_path/3). A naive path <> "?" <> URI.encode_query(params) would emit "/billing/customers?org=acme?q=foo" — a corrupting second ? that drops the org param and breaks owner-scoping on every apply/change/clear.

patch_with_filters/3 instead decodes the existing query, merges the filter params over it (filter params win for keys they set), drops blank/nil values so cleared fields disappear from the URL, and re-encodes a SINGLE query string. The pre-existing org (and any other) query param survives every apply/change/clear.

Summary

Functions

Builds the merged path string without touching a socket.

Merges params into path's existing query and push_patches the socket.

Functions

merge_query(path, params)

@spec merge_query(String.t(), map()) :: String.t()

Builds the merged path string without touching a socket.

Exposed for unit testing the merge/no-double-?/blank-drop/org-only behavior.

patch_with_filters(socket, path, params)

@spec patch_with_filters(Phoenix.LiveView.Socket.t(), String.t(), map()) ::
  Phoenix.LiveView.Socket.t()

Merges params into path's existing query and push_patches the socket.

  • decodes path's existing query string (e.g. org=acme)
  • merges params over it (filter params win)
  • drops nil/"" values so cleared fields leave the URL
  • re-encodes a single query string (no double ?)
  • push_patches to the resulting path (no trailing ? when empty)