Single state struct for MishkaGervaz table.
Instead of scattered assigns, all table state is managed in this struct. This provides:
- Clear state structure
- Easy state updates
- Type safety
- Single source of truth
Performance Optimization
State is split into two parts:
static- Configuration that never changes (same reference for O(1) comparison)- Dynamic fields - User interaction state that triggers re-renders
This separation allows LiveView to skip re-rendering static parts (columns, filters, etc.) when only dynamic state (page, filter_values, etc.) changes.
Sub-builders
State initialization is composed of sub-builders that can be overridden:
ColumnBuilder- Builds columns from DSL and resourceFilterBuilder- Builds filters from DSL and resourceActionBuilder- Builds row/bulk actionsPresentation- Resolves UI adapter and templatesUrlSync- Handles URL state synchronizationAccess- Handles access control
User Override
Override the entire state module:
defmodule MyApp.Table.State do
use MishkaGervaz.Table.Web.State
def init(id, resource, user) do
state = super(id, resource, user)
%{state | custom_field: :value}
end
endOverride specific sub-builders:
defmodule MyApp.Table.State do
use MishkaGervaz.Table.Web.State,
column: MyApp.Table.ColumnBuilder,
filter: MyApp.Table.FilterBuilder
endOr override via DSL:
mishka_gervaz do
table do
state do
column MyApp.Table.ColumnBuilder
filter MyApp.Table.FilterBuilder
end
end
endOverride entire state module via DSL:
mishka_gervaz do
table do
state module: MyApp.Table.CustomState
end
endHelper Functions
Helper functions are available in MishkaGervaz.Table.Web.State.Helpers and can be
used when overriding state functions:
defmodule MyApp.Table.State do
use MishkaGervaz.Table.Web.State
alias MishkaGervaz.Table.Web.State.Helpers, as: StateHelpers
def hydrate_relation_filter_labels(state) do
# Use helpers in your override
StateHelpers.hydrate_filter(filter, acc, state)
end
endSee MishkaGervaz.Table.Web.State.Helpers,
MishkaGervaz.Table.Web.State.ColumnBuilder,
MishkaGervaz.Table.Web.State.FilterBuilder,
MishkaGervaz.Table.Web.State.ActionBuilder,
MishkaGervaz.Table.Web.State.Presentation,
MishkaGervaz.Table.Web.State.UrlSync,
MishkaGervaz.Table.Web.State.Access,
MishkaGervaz.Table.Web.AutoState,
MishkaGervaz.Table.Web.Refresh,
MishkaGervaz.Table.Web.UrlSync.
Summary
Functions
See MishkaGervaz.Table.Web.State.Default.apply_url_state/2.
See MishkaGervaz.Table.Web.State.Default.bidirectional_url_sync?/1.
See MishkaGervaz.Table.Web.State.Default.can_modify_record?/2.
See MishkaGervaz.Table.Web.State.Default.default_init/3.
See MishkaGervaz.Table.Web.State.Default.get_action/2.
See MishkaGervaz.Table.Web.State.Default.get_preloads/1.
Hydrate relation filter state with labels for selected values from URL
See MishkaGervaz.Table.Web.State.Default.init/3.
See MishkaGervaz.Table.Web.State.Default.record_visible?/2.
See MishkaGervaz.Table.Web.State.Default.switch_template/2.
See MishkaGervaz.Table.Web.State.Default.template_switching_enabled?/1.
See MishkaGervaz.Table.Web.State.Default.update/2.
Types
@type archive_status() :: :active | :archived
@type loading_status() :: :initial | :loading | :loaded | :error
@type loading_type() :: :initial | :reset | :more
@type t() :: %MishkaGervaz.Table.Web.State{ archive_status: archive_status(), base_path: String.t() | nil, current_page_size: pos_integer() | nil, current_user: map() | nil, dismissed_notices: MapSet.t(), excluded_ids: MapSet.t(any()), expanded_data: struct() | nil, expanded_id: String.t() | nil, filter_values: map(), has_initial_data?: boolean(), has_more?: boolean(), loading: loading_status(), loading_type: loading_type(), master_user?: boolean(), page: integer(), path_params: map(), preload_aliases: %{required(atom()) => atom()}, preserved_params: map(), records_result: struct(), relation_filter_state: %{required(atom()) => map()}, saved_active_state: map() | nil, saved_archived_state: map() | nil, select_all?: boolean(), selected_ids: MapSet.t(any()), sort_fields: [{atom(), :asc | :desc}], static: MishkaGervaz.Table.Web.State.Static.t(), supports_archive: boolean(), template: module(), total_count: integer() | nil, total_pages: integer() | nil }
Functions
See MishkaGervaz.Table.Web.State.Default.apply_url_state/2.
See MishkaGervaz.Table.Web.State.Default.bidirectional_url_sync?/1.
See MishkaGervaz.Table.Web.State.Default.can_modify_record?/2.
See MishkaGervaz.Table.Web.State.Default.default_init/3.
See MishkaGervaz.Table.Web.State.Default.get_action/2.
See MishkaGervaz.Table.Web.State.Default.get_preloads/1.
Hydrate relation filter state with labels for selected values from URL
See MishkaGervaz.Table.Web.State.Default.init/3.
See MishkaGervaz.Table.Web.State.Default.record_visible?/2.
See MishkaGervaz.Table.Web.State.Default.switch_template/2.
See MishkaGervaz.Table.Web.State.Default.template_switching_enabled?/1.
See MishkaGervaz.Table.Web.State.Default.update/2.