MishkaGervaz.Table.Web.UrlSync (MishkaGervaz v0.0.1-alpha.2)

Copy Markdown View Source

URL state synchronization for bookmarkable table views.

Syncs table state (filters, sort, page, search) to URL query params, allowing users to bookmark or share specific table views.

Configuration

Enable URL sync in domain table config:

mishka_gervaz do
  table do
    url_sync do
      enabled true
      params [:filters, :sort, :page]
      prefix "table"
    end
  end
end

Usage in LiveView

In your parent LiveView, handle URL params:

def handle_params(params, _uri, socket) do
  url_state = MishkaGervaz.Table.Web.UrlSync.decode(params, "table")

  {:noreply,
    socket
    |> assign(:url_state, url_state)}
end

Pass to the component:

<.live_component
  module={MishkaGervaz.Table.Web.Live}
  id="posts-table"
  resource={MyApp.Post}
  url_state={@url_state}
/>

Param Format

  • Filters: ?table_filter_status=active&table_filter_category=1
  • Sort: ?table_sort=name:asc or ?table_sort=inserted_at:desc
  • Page: ?table_page=2
  • Search: ?table_search=hello
  • Template: ?table_template=grid

See MishkaGervaz.Table.Web.State, MishkaGervaz.Table.Web.State.UrlSync (the in-state sub-builder), MishkaGervaz.Table.Dsl.UrlSync (resource-level DSL section), MishkaGervaz.Table.Dsl.Defaults (domain-level defaults).

Summary

Functions

Apply URL state to existing table state.

Build URL path with encoded state params.

Check if URL sync is enabled in config.

Check if url_state matches current table state.

Types

decode_opts()

@type decode_opts() :: [
  allowed_params: [atom()],
  allowed_filters: [atom()],
  max_filter_length: non_neg_integer()
]

url_state()

@type url_state() :: %{
  filters: map(),
  sort: [{atom(), :asc | :desc}],
  page: integer(),
  page_size: pos_integer() | nil,
  search: String.t() | nil,
  template: atom() | nil,
  path: String.t() | nil,
  path_params: map(),
  preserved_params: map()
}

Functions

apply_url_state(state, url_state)

@spec apply_url_state(map(), url_state()) :: map()

Apply URL state to existing table state.

Merges decoded URL state with default table state.

build_path(base_path, state, config)

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

Build URL path with encoded state params.

Takes current path and state, returns path with query string.

decode(params, uri, resource, opts)

@spec decode(map(), String.t(), module(), decode_opts()) :: url_state() | nil

enabled?(config)

@spec enabled?(map()) :: boolean()

Check if URL sync is enabled in config.

encode(state, config \\ %{enabled: false, params: [:filters, :sort, :page], prefix: nil})

@spec encode(map(), map()) :: map()

Encode table state to URL query params.

Examples

iex> state = %{filters: %{status: "active"}, sort: [{:name, :asc}], page: 2}
iex> UrlSync.encode(state, %{params: [:filters, :sort, :page], prefix: "t"})
%{"t_filter_status" => "active", "t_sort" => "name:asc", "t_page" => "2"}

matches_state?(url_state, state)

@spec matches_state?(url_state() | nil, map()) :: boolean()

Check if url_state matches current table state.

Used to detect if incoming url_state is from our own push_patch (to avoid duplicate data reload).