### Install Backpex Plugin
Source: https://github.com/naymspace/backpex/blob/develop/guides/ai_development/ai-development.md
Installs the Backpex plugin from the registered marketplace. Run /reload-plugins afterwards to activate it.
```bash
/plugin install backpex@naymspace-backpex
```
--------------------------------
### Start Backpex Development Environment
Source: https://github.com/naymspace/backpex/blob/develop/guides/about/contribute-to-backpex.md
Run this command in the project's root directory to start the PostgreSQL database and the demo application. The application will be accessible at http://localhost:4000.
```bash
docker compose up
```
--------------------------------
### Configure LiveResource with Adapter Pattern (Before)
Source: https://github.com/naymspace/backpex/blob/develop/guides/upgrading/v0.8.md
Example of `Backpex.LiveResource` configuration before the introduction of the adapter pattern.
```elixir
use Backpex.LiveResource,
layout: {DemoWeb.Layouts, :admin},
schema: Demo.User,
repo: Demo.Repo,
update_changeset: &Demo.User.changeset/3,
create_changeset: &Demo.User.changeset/3,
pubsub: Demo.PubSub,
topic: "users",
event_prefix: "user_"
```
--------------------------------
### Complete LiveResource Pagination Configuration
Source: https://github.com/naymspace/backpex/blob/develop/guides/live_resource/pagination.md
Example of a complete LiveResource configuration including pagination settings.
```elixir
defmodule MyAppWeb.PostLive do
use Backpex.LiveResource,
adapter_config: [
schema: MyApp.Post,
repo: MyApp.Repo,
update_changeset: &MyApp.Post.changeset/3,
create_changeset: &MyApp.Post.changeset/3
],
layout: {MyAppWeb.Layouts, :admin},
per_page_default: 25,
per_page_options: [10, 25, 50, 100]
# ... rest of your LiveResource
end
```
--------------------------------
### Configure Router for LiveResources
Source: https://github.com/naymspace/backpex/blob/develop/skills/create-live-resource/SKILL.md
Integrate LiveResources into your application's router using `backpex_routes()` and `live_resources/3`. This example shows basic setup and route restrictions.
```elixir
import Backpex.Router
scope "/admin", MyAppWeb do
pipe_through :browser
backpex_routes()
live_session :admin, on_mount: Backpex.InitAssigns do
live_resources "/posts", PostLive
live_resources "/users", UserLive
live_resources "/categories", CategoryLive, only: [:index, :show]
end
end
```
--------------------------------
### Render Heroicon Component
Source: https://github.com/naymspace/backpex/blob/develop/guides/get_started/installation.md
Example of how to use the Backpex.HTML.CoreComponents.icon component to render a heroicon with specified name and CSS classes.
```heex
```
--------------------------------
### Set up Backpex Development Environment
Source: https://github.com/naymspace/backpex/blob/develop/guides/about/contribute-to-backpex.md
Create a .env file in the demo directory with necessary keys. Copy values from the example file for development purposes.
```bash
SECRET_KEY_BASE=
LIVE_VIEW_SIGNING_SALT=
```
--------------------------------
### Start DynamicSupervisor Child
Source: https://github.com/naymspace/backpex/blob/develop/usage_rules.md
Use DynamicSupervisor primitives by providing a name in the child spec and then using DynamicSupervisor.start_child with that name.
```elixir
{DynamicSupervisor, name: MyApp.MyDynamicSup}
```
```elixir
DynamicSupervisor.start_child(MyApp.MyDynamicSup, child_spec)
```
--------------------------------
### Configure LiveResource with Adapter Pattern (After)
Source: https://github.com/naymspace/backpex/blob/develop/guides/upgrading/v0.8.md
Example of `Backpex.LiveResource` configuration after adopting the adapter pattern, moving adapter-specific configurations into `adapter_config` and restructuring `pubsub`.
```elixir
use Backpex.LiveResource,
adapter: Backpex.Adapters.Ecto,
adapter_config: [
schema: Demo.User,
repo: Demo.Repo,
update_changeset: &Demo.User.changeset/3,
create_changeset: &Demo.User.changeset/3,
],
layout: {DemoWeb.Layouts, :admin},
pubsub: [
name: Demo.PubSub,
topic: "users",
event_prefix: "user_"
]
```
--------------------------------
### Phoenix LiveView Hook Example
Source: https://github.com/naymspace/backpex/blob/develop/AGENTS.md
Example of creating a client hook for Phoenix LiveView using the `phx-hook` attribute. Hooks should be created in the `assets/js` directory and exported in `assets/js/index.js`.
```javascript
const Hooks = {
MyHook: {
mounted() {
console.log("MyHook mounted");
},
// ... other hook callbacks
}
};
export default Hooks;
```
--------------------------------
### LiveResource `handle_event` Example (Before)
Source: https://github.com/naymspace/backpex/blob/develop/guides/upgrading/v0.13.md
Illustrates the previous method of defining `handle_event` directly within a LiveResource module before the refactoring.
```elixir
use Backpex.LiveResource,
...
@impl Phoenix.LiveView
def handle_event(_params, _url, socket) do
# Do stuff
{:cont, socket}
end
```
--------------------------------
### Default Topic Generation Example
Source: https://github.com/naymspace/backpex/blob/develop/guides/live_resource/listen-to-pubsub-events.md
Demonstrates how Backpex generates the default PubSub topic from a LiveResource module name.
```elixir
iex(1)> to_string(DemoWeb.UserLive)
"Elixir.DemoWeb.UserLive"
```
--------------------------------
### Check Backpex Dependency Version
Source: https://github.com/naymspace/backpex/blob/develop/skills/upgrade/SKILL.md
Inspect your `mix.exs` file to determine the currently installed Backpex version.
```elixir
{:backpex, "~> 0.17.0"}
```
--------------------------------
### Configure Field with Placeholder Option
Source: https://github.com/naymspace/backpex/blob/develop/guides/fields/what-is-a-field.md
Extend field configuration by adding type-specific options. This example demonstrates setting a `placeholder` for a text field to guide user input.
```elixir
@impl Backpex.LiveResource
def fields do
[
username: %{
module: Backpex.Fields.Text,
label: "Username",
placeholder: "Enter your username"
}
]
end
```
--------------------------------
### Implement render_resource_slot for Custom Templates
Source: https://github.com/naymspace/backpex/blob/develop/guides/live_resource/templates.md
Implement the `render_resource_slot/3` callback in your resource configuration to add custom templates. This example shows how to render 'Hello World!' before the main content on the index view.
```elixir
# in your resource configuration file
@impl Backpex.LiveResource
def render_resource_slot(assigns, :index, :before_main), do: ~H"Hello World!"
```
--------------------------------
### Select Filter Example
Source: https://github.com/naymspace/backpex/blob/develop/skills/create-filter/SKILL.md
Implement a single-value dropdown filter. Requires `Backpex.Filters.Select` and defines `prompt/0` and `options/1` to return tuples.
```elixir
defmodule MyAppWeb.Filters.PostCategorySelect do
use Backpex.Filters.Select
import Ecto.Query
alias MyApp.Repo
@impl Backpex.Filter
def label, do: "Category"
@impl Backpex.Filters.Select
def prompt, do: "Select category ..."
@impl Backpex.Filters.Select
def options(_assigns) do
from(c in MyApp.Category, select: {c.name, c.id}, order_by: c.name) |> Repo.all()
end
end
```
--------------------------------
### Backpex Demo Application Directory Structure
Source: https://github.com/naymspace/backpex/blob/develop/CLAUDE.md
This shows the directory structure of the demo Phoenix application, including example domain logic, LiveResource implementations, custom filters, and actions.
```elixir
demo/
├── lib/
│ ├── demo/
│ │ └── helpdesk/
│ └── demo_web/
│ ├── components/
│ ├── live/
│ │ ├── user_live.ex
│ │ ├── post_live.ex
│ │ ├── product_live.ex
│ │ └── ...
│ ├── filters/
│ ├── item_actions/
│ └── resource_actions/
│ └── router.ex
├── priv/
│ ├── repo/
│ └── static/
├── test/
└── assets/
```
--------------------------------
### Configure Item Actions in Resource
Source: https://github.com/naymspace/backpex/blob/develop/guides/actions/item-actions.md
Implement the `item_actions/1` callback in your resource configuration module to define or replace default item actions. This example adds a 'show' item action and replaces all others.
```elixir
# in your resource configuration file
@impl Backpex.LiveResource
def item_actions([_show, _edit, _delete]) do
[
show: %{
module: DemoWeb.ItemAction.Show
}
]
end
```
--------------------------------
### Configure daisyUI Themes
Source: https://github.com/naymspace/backpex/blob/develop/guides/get_started/installation.md
Add daisyUI themes to your application's stylesheet using the @plugin directive. This example includes 'dark' and 'cyberpunk' themes.
```css
@plugin "daisyui" {
themes: dark, cyberpunk;
}
```
```css
@plugin "daisyui/theme" {
name: "light";
--color-primary: #1d4ed8;
--color-primary-content: white;
--color-secondary: #f39325;
--color-secondary-content: white;
}
```
--------------------------------
### Implement a Custom Item Action Module
Source: https://github.com/naymspace/backpex/blob/develop/guides/actions/item-actions.md
Define a module using `BackpexWeb.item_action` to create a custom item action. This example implements a 'Show' item action that navigates to a user's show view.
```elixir
defmodule DemoWeb.ItemAction.Show do
use BackpexWeb, :item_action
@impl Backpex.ItemAction
def icon(assigns, _item) do
~H"""
"""
end
@impl Backpex.ItemAction
def label(_assigns, _item), do: "Show"
@impl Backpex.ItemAction
def handle(socket, [item | _items], _data) do
path = Router.get_path(socket, socket.assigns.live_resource, socket.assigns.params, :show, item)
{:ok, Phoenix.LiveView.push_patch(socket, to: path)}
end
end
```
--------------------------------
### Add Backpex Plugin Marketplace
Source: https://github.com/naymspace/backpex/blob/develop/guides/ai_development/ai-development.md
Registers the Backpex marketplace in Claude Code to enable browsing and installing Backpex plugins.
```bash
/plugin marketplace add naymspace/backpex
```
--------------------------------
### Define Panels with `panels/0` Callback
Source: https://github.com/naymspace/backpex/blob/develop/guides/live_resource/panels.md
Implement the `panels/0` callback in your resource configuration to define panels. It returns a keyword list where keys are panel identifiers and values are their labels. This setup is required to create custom panels.
```elixir
# in your resource configuration file
@impl Backpex.LiveResource
def panels do
[
contact: "Contact"
]
end
```
--------------------------------
### Define Basic Resource Fields
Source: https://github.com/naymspace/backpex/blob/develop/guides/fields/what-is-a-field.md
Implement the `fields/0` callback in your resource module to define fields. This example shows how to configure `username` and `age` fields using built-in text and number types.
```elixir
@impl Backpex.LiveResource
def fields do
[
username: %{
module: Backpex.Fields.Text,
label: "Username"
},
age: %{
module: Backpex.Fields.Number,
label: "Age"
}
]
end
```
--------------------------------
### Define a Select Filter Module
Source: https://github.com/naymspace/backpex/blob/develop/guides/filter/how-to-add-a-filter.md
Implement a filter module for a select filter to filter posts by category. This example uses `Backpex.Filters.Select` and defines options by querying the database.
```elixir
defmodule MyAppWeb.Filters.PostCategorySelect do
use Backpex.Filters.Select
alias MyApp.Category
alias MyApp.Post
alias MyApp.Repo
@impl Backpex.Filter
def label, do: "Category"
@impl Backpex.Filters.Select
def prompt, do: "Select category ..."
@impl Backpex.Filters.Select
def options(_assigns) do
query =
from p in Post,
join: c in Category,
on: p.category_id == c.id,
distinct: c.name,
select: {c.name, c.id}
Repo.all(query)
end
end
```
--------------------------------
### Complete Custom Filter: Price Range
Source: https://github.com/naymspace/backpex/blob/develop/guides/filter/filter-validation.md
This example demonstrates a full custom filter implementation for a price range, including validation logic for minimum and maximum prices, and Ecto query generation.
```elixir
defmodule MyAppWeb.Filters.PriceRange do
use BackpexWeb, :filter
import Ecto.Query
@impl Backpex.Filter
def label, do: "Price Range"
@impl Backpex.Filter
def type(_assigns), do: :map
@impl Backpex.Filter
def changeset(changeset, field, _assigns) do
Ecto.Changeset.validate_change(changeset, field, fn _field, value ->
validate_price_range(value, field)
end)
end
defp validate_price_range(%{"min" => min_str, "max" => max_str}, field) do
errors = []
min = parse_price(min_str)
max = parse_price(max_str)
errors = if min_str != "" and is_nil(min) do
[{field, "minimum price is invalid"}]
else
errors
end
errors = if max_str != "" and is_nil(max) do
[{field, "maximum price is invalid"} | errors]
else
errors
end
errors = if min && max && min > max do
[{field, "minimum cannot exceed maximum"} | errors]
else
errors
end
errors
end
defp validate_price_range(_value, _field), do: []
defp parse_price(""), do: nil
defp parse_price(str) do
case Float.parse(str) do
{value, ""} when value >= 0 -> value
_ -> nil
end
end
@impl Backpex.Filter
def query(query, attribute, %{"min" => min, "max" => max}, _assigns) do
query
|> maybe_filter_min(attribute, parse_price(min))
|> maybe_filter_max(attribute, parse_price(max))
end
def query(query, _attribute, _value, _assigns), do: query
defp maybe_filter_min(query, _attr, nil), do: query
defp maybe_filter_min(query, attr, min), do: where(query, [x], field(x, ^attr) >= ^min)
defp maybe_filter_max(query, _attr, nil), do: query
defp maybe_filter_max(query, attr, max), do: where(query, [x], field(x, ^attr) <= ^max)
@impl Backpex.Filter
def render(assigns) do
min = assigns.value["min"]
max = assigns.value["max"]
~H"""
≥ <%= min %>≤ <%= max %><%= min %> — <%= max %>
"""
end
@impl Backpex.Filter
def render_form(assigns) do
~H"""
<.error :for={msg <- @errors} class="mt-1">{msg}
"""
end
end
```
--------------------------------
### Full-Text Search Configuration with PostgreSQL
Source: https://context7.com/naymspace/backpex/llms.txt
Enables full-text search by configuring `Backpex.LiveResource` with the `full_text_search` option pointing to a `tsvector` column. Includes a migration example to add and populate the `search_vector` column.
```elixir
use Backpex.LiveResource,
adapter_config: [...],
full_text_search: :search_vector # the tsvector column name
# Migration example
def up do
alter table(:posts) do
add :search_vector, :tsvector
end
execute """
CREATE INDEX posts_search_vector_idx ON posts USING gin(search_vector);
"""
execute """
UPDATE posts SET search_vector =
to_tsvector('english', coalesce(title,'') || ' ' || coalesce(body,''));
"""
end
```
--------------------------------
### Update Resource and Adapter Function Signatures
Source: https://github.com/naymspace/backpex/blob/develop/guides/upgrading/v0.15.md
Functions in `Backpex.Resource` and adapter modules now accept `fields` as an additional parameter. Update calls to `list/3`, `count/3`, `get/3`, and `get!/3` accordingly.
```elixir
# before
Resource.get(primary_value, socket.assigns, live_resource)
# after
Resource.get(primary_value, fields, socket.assigns, live_resource)
```
--------------------------------
### LiveView Stream Template Structure
Source: https://github.com/naymspace/backpex/blob/develop/usage_rules.md
Example of a LiveView template structure for consuming streams. The parent div must have an id and `phx-update="stream"`, and child elements should use the stream's id.
```html
{msg.text}
```
--------------------------------
### Place Item Actions on Index Table Rows
Source: https://github.com/naymspace/backpex/blob/develop/guides/actions/item-actions.md
Configure the placement of an item action using the `only` or `except` keys within the `item_actions/1` callback. This example places the 'show' item action exclusively on the index table rows.
```elixir
# Example of placement configuration (code not provided in source, only description)
# This would typically be within the item_actions callback
# For instance:
# [show: %{module: DemoWeb.ItemAction.Show, only: [:row]}]
```
--------------------------------
### Demo Application Project Structure
Source: https://github.com/naymspace/backpex/blob/develop/AGENTS.md
Overview of the directory structure for the Backpex demo application, illustrating its components and organization.
```text
demo/
├── lib/
│ ├── demo/
│ │ └── helpdesk/
│ └── demo_web/
│ ├── components/
│ ├── live/
│ │ ├── user_live.ex
│ │ ├── post_live.ex
│ │ ├── product_live.ex
│ │ └── ...
│ ├── filters/
│ ├── item_actions/
│ ├── resource_actions/
│ └── router.ex
├── priv/
│ ├── repo/
│ └── static/
├── test/
└── assets/
```
--------------------------------
### Configure PubSub Server
Source: https://context7.com/naymspace/backpex/llms.txt
Configure the PubSub server for Backpex in `config/config.exs`.
```elixir
config :backpex, :pubsub_server, MyApp.PubSub
```
--------------------------------
### Backpex LiveResource for Product
Source: https://github.com/naymspace/backpex/blob/develop/skills/create-live-resource/SKILL.md
Defines a Live Resource for the 'Product' entity. Configure adapter settings, default pagination, initial ordering, and callbacks for layout, naming, panels, fields, and custom permissions.
```elixir
defmodule MyAppWeb.ProductLive do
use Backpex.LiveResource,
adapter_config: [
schema: MyApp.Product,
repo: MyApp.Repo,
update_changeset: &MyApp.Product.changeset/3,
create_changeset: &MyApp.Product.changeset/3,
item_query: &__MODULE__.item_query/3
],
per_page_default: 25,
init_order: %{by: :inserted_at, direction: :desc}
import Ecto.Query
@impl Backpex.LiveResource
def layout(_assigns), do: {MyAppWeb.Layouts, :admin}
@impl Backpex.LiveResource
def singular_name, do: "Product"
@impl Backpex.LiveResource
def plural_name, do: "Products"
@impl Backpex.LiveResource
def panels do
[details: "Details", metadata: "Metadata"]
end
@impl Backpex.LiveResource
def fields do
[
name: %{
module: Backpex.Fields.Text,
label: "Name",
searchable: true,
panel: :details
},
price: %{
module: Backpex.Fields.Currency,
label: "Price",
panel: :details
},
category: %{
module: Backpex.Fields.BelongsTo,
label: "Category",
display_field: :name,
live_resource: MyAppWeb.CategoryLive,
panel: :details
},
published: %{
module: Backpex.Fields.Boolean,
label: "Published",
index_editable: true
},
inserted_at: %{
module: Backpex.Fields.DateTime,
label: "Created At",
only: [:index, :show],
panel: :metadata
}
]
end
@impl Backpex.LiveResource
def can?(_assigns, :delete, item), do: not item.published
def can?(_assigns, _action, _item), do: true
def item_query(query, _live_action, _assigns) do
from p in query, where: is_nil(p.archived_at)
end
end
```
--------------------------------
### Seed Demo Data for Backpex
Source: https://github.com/naymspace/backpex/blob/develop/guides/about/contribute-to-backpex.md
Execute this command to insert demo data into the PostgreSQL database for the Backpex demo application.
```bash
docker compose exec app mix ecto.seed
```
--------------------------------
### Boolean Filter Example
Source: https://github.com/naymspace/backpex/blob/develop/skills/create-filter/SKILL.md
Implement a boolean filter for checkbox predicates. Requires `Backpex.Filters.Boolean` and defines `options/1` to return predicate maps.
```elixir
defmodule MyAppWeb.Filters.PostPublished do
use Backpex.Filters.Boolean
import Ecto.Query
@impl Backpex.Filter
def label, do: "Published?"
@impl Backpex.Filters.Boolean
def options(_assigns) do
[
%{label: "Published", key: "published", predicate: dynamic([x], x.published)},
%{label: "Not published", key: "not_published", predicate: dynamic([x], not x.published)}
]
end
end
```
--------------------------------
### Admin Layout HEEX Component
Source: https://context7.com/naymspace/backpex/llms.txt
Example of using the `Backpex.HTML.Layout.app_shell` component to structure an admin interface, including topbar, sidebar, and flash messages.
```heex
<%# lib/my_app_web/components/layouts/admin.html.heex %>
<:topbar>
<%# Optional theme switcher %>
<:label>
<.link href="/logout" class="text-error">
Logout
<:sidebar>
Posts
Users
{render_slot(@inner_block)}
```
--------------------------------
### Generate Schema and Migration
Source: https://github.com/naymspace/backpex/blob/develop/guides/get_started/installation.md
Use these Mix tasks to generate a schema for your resource and create a database migration.
```bash
$ mix phx.gen.schema Blog.Post blog_posts title:string views:integer
$ mix ecto.migrate
```
--------------------------------
### Range Filter Example
Source: https://github.com/naymspace/backpex/blob/develop/skills/create-filter/SKILL.md
Implement a range filter for numeric, date, or datetime inputs. Requires `Backpex.Filters.Range` and defines `type/0` to specify the data type.
```elixir
defmodule MyAppWeb.Filters.PostLikeRange do
use Backpex.Filters.Range
@impl Backpex.Filters.Range
def type, do: :number
@impl Backpex.Filter
def label, do: "Likes"
end
```
--------------------------------
### LiveView Hook Example
Source: https://github.com/naymspace/backpex/blob/develop/CLAUDE.md
This demonstrates how to create client-side JavaScript hooks for Phoenix LiveView using the `phx-hook` attribute. Ensure hooks are exported in `assets/js/index.js`.
```javascript
phx-hook
```
--------------------------------
### Basic Item Action Configuration
Source: https://github.com/naymspace/backpex/blob/develop/guides/actions/item-actions.md
Configure a basic item action by defining its module and the context in which it should appear.
```elixir
def item_actions([_show, _edit, _delete]) do
[
show: %{
module: DemoWeb.ItemAction.Show,
only: [:row]
}
]
end
```
--------------------------------
### Search Documentation with mix usage_rules.search_docs
Source: https://github.com/naymspace/backpex/blob/develop/usage_rules.md
Utilize `mix usage_rules.search_docs` to find documentation across packages. This task supports searching specific packages and multi-word queries.
```elixir
mix usage_rules.search_docs Enum.zip
```
```elixir
mix usage_rules.search_docs Req.get -p req
```
```elixir
mix usage_rules.search_docs "making requests" -p req
```
```elixir
mix usage_rules.search_docs "Enum.zip" --query-by title
```
--------------------------------
### MultiSelect Filter Validation Example
Source: https://github.com/naymspace/backpex/blob/develop/guides/filter/filter-validation.md
Shows the validation process for a built-in MultiSelect filter. It verifies that all selected values are included in the list of options provided by `options/1`.
```elixir
# If options returns:
[{"John", "user-1"}, {"Jane", "user-2"}]
# Valid: ["user-1"], ["user-1", "user-2"]
# Invalid: ["user-1", "invalid-uuid"]
```
--------------------------------
### Select Filter Validation Example
Source: https://github.com/naymspace/backpex/blob/develop/guides/filter/filter-validation.md
Demonstrates the validation for a built-in Select filter. It checks if the selected value is present in the list of available options returned by `options/1`.
```elixir
# If options returns:
[{"Active", "active"}, {"Inactive", "inactive"}]
# Valid: "active", "inactive"
# Invalid: "unknown"
```
--------------------------------
### Configure Resource Ordering with a Function
Source: https://github.com/naymspace/backpex/blob/develop/guides/live_resource/ordering.md
Dynamically determine resource ordering by providing a function reference to `init_order`. The function must accept assigns and return a map with `:by` and `:direction` keys. Anonymous functions are not supported.
```elixir
use Backpex.LiveResource,
# ...other options
init_order: &__MODULE__.init_order/1
def init_order(_assigns) do
%{by: :username, direction: :asc}
end
```
--------------------------------
### Validate Numeric Range in Changeset
Source: https://github.com/naymspace/backpex/blob/develop/guides/filter/filter-validation.md
Implement the `changeset/3` callback to enforce a numeric range for a filter field. This example ensures the value is between 0 and 100 (inclusive).
```elixir
def changeset(changeset, field, _assigns) do
Ecto.Changeset.validate_number(changeset, field,
greater_than_or_equal_to: 0,
less_than_or_equal_to: 100
)
end
```
--------------------------------
### Implement Custom Filter Validation
Source: https://github.com/naymspace/backpex/blob/develop/guides/filter/filter-validation.md
Add custom validations to a filter by implementing the `changeset/3` callback. This example validates that a numeric field is within a specified range.
```elixir
@impl Backpex.Filter
def changeset(changeset, field, _assigns) do
changeset
|> Ecto.Changeset.validate_number(field, greater_than: 0, less_than: 1000)
end
```
--------------------------------
### Configure PubSub Server Globally
Source: https://github.com/naymspace/backpex/blob/develop/guides/live_resource/listen-to-pubsub-events.md
Set the default PubSub server for Backpex in your application's configuration file.
```elixir
config :backpex, pubsub_server: Demo.PubSub,
```
--------------------------------
### Configure Resource Action
Source: https://github.com/naymspace/backpex/blob/develop/guides/actions/resource-actions.md
Add a resource action to your resource configuration module by implementing the `resource_actions/0` callback. The key in the keyword list is the unique `id` of the resource action.
```elixir
# in your resource configuration file
@impl Backpex.LiveResource
def resource_actions() do
[
invite: %{
module: MyWebApp.Admin.ResourceActions.Invite,
}
]
end
```
--------------------------------
### Define Numeric Filter Type and Validation
Source: https://github.com/naymspace/backpex/blob/develop/guides/filter/custom-filter.md
This example defines a numeric filter with the Ecto type `:integer` and uses `validate_number/2` to enforce a range between 0 and 10000.
```elixir
defmodule MyApp.Filters.QuantityFilter do
use BackpexWeb, :filter
import Ecto.Query
@impl Backpex.Filter
def label, do: "Minimum Quantity"
@impl Backpex.Filter
def type(_assigns), do: :integer
@impl Backpex.Filter
def changeset(changeset, field, _assigns) do
Ecto.Changeset.validate_number(changeset, field,
greater_than_or_equal_to: 0,
less_than_or_equal_to: 10000
)
end
@impl Backpex.Filter
def render(assigns) do
~H"""
≥ {@value}
"""
end
@impl Backpex.Filter
def render_form(assigns) do
~H"""
"""
end
@impl Backpex.Filter
def query(query, attribute, value, _assigns) do
# value is already an integer!
where(query, [x], field(x, ^attribute) >= ^value)
end
end
```
--------------------------------
### Control Field Visibility with `can?`
Source: https://github.com/naymspace/backpex/blob/develop/guides/fields/visibility.md
Use the `can?` option with a function to determine field visibility, which can be used on `:index` as well. This example shows the 'Created At' field only during the `:show` action.
```elixir
# in your resource configuration file
@impl Backpex.LiveResource
def fields do
[
inserted_at: %{
module: Backpex.Fields.DateTime,
label: "Created At",
can?: fn
%{live_action: :show} = _assigns ->
true
_assigns ->
false
end
}
]
end
```
--------------------------------
### Basic Custom Field Implementation
Source: https://github.com/naymspace/backpex/blob/develop/guides/fields/custom-fields.md
Defines a simple custom field with functions to render its value and form input. Use this as a starting point for creating your own fields.
```elixir
use Backpex.Field
@impl Backpex.Field
def render_value(assigns) do
~H"""
<%= HTML.pretty_value(@value) %>
"""
end
@impl Backpex.Field
def render_form(assigns) do
~H"""
<:label>
"""
end
```
--------------------------------
### Elixir Guard Clause Example
Source: https://github.com/naymspace/backpex/blob/develop/usage_rules.md
Use guard clauses to add conditions to function clauses. Ensure the input meets the specified criteria before executing the function body.
```elixir
when is_binary(name) and byte_size(name) > 0
```
--------------------------------
### Format Code with Mix
Source: https://github.com/naymspace/backpex/blob/develop/CLAUDE.md
Formats the Backpex project code using the mix format command. This command should be executed on the host system.
```sh
mix format
```
--------------------------------
### Use Module Function for LiveResource Configuration
Source: https://github.com/naymspace/backpex/blob/develop/guides/upgrading/v0.8.md
Demonstrates the change from using anonymous functions to module functions for LiveResource configuration options like `init_order`.
```elixir
use Backpex.LiveResource,
init_order: fn _assigns -> %{by: :username, direction: :asc} end
```
```elixir
use Backpex.LiveResource,
init_order: &__MODULE__.init_order/1
def init_order(_assigns) do
%{by: :username, direction: :asc}
end
```
--------------------------------
### Boolean Filter Validation Example
Source: https://github.com/naymspace/backpex/blob/develop/guides/filter/filter-validation.md
Illustrates the validation logic for a built-in Boolean filter. It ensures that all selected checkbox keys correspond to valid options defined in `options/1`.
```elixir
# If options returns:
[
%{label: "Published", key: "published", predicate: ...},
%{label: "Draft", key: "draft", predicate: ...}
]
# Valid: ["published"], ["draft"], ["published", "draft"]
# Invalid: ["unknown_key"]
```
--------------------------------
### Configure Router for Backpex LiveResources
Source: https://github.com/naymspace/backpex/blob/develop/guides/get_started/installation.md
Add the `backpex_routes()` macro to your `router.ex` file to make LiveResources accessible. Ensure the scope pipes through `:browser`.
```elixir
# router.ex
import Backpex.Router
scope "/admin", MyAppWeb do
pipe_through :browser
# add this line
backpex_routes()
end
```
--------------------------------
### Validate Format in Changeset
Source: https://github.com/naymspace/backpex/blob/develop/guides/filter/filter-validation.md
Implement the `changeset/3` callback to validate the format of a filter's value using a regular expression. This example checks for a specific alphanumeric pattern.
```elixir
def changeset(changeset, field, _assigns) do
Ecto.Changeset.validate_format(changeset, field, ~r/^[A-Z]{2,3}-\d+$/)
end
```
--------------------------------
### Custom Filter Example
Source: https://github.com/naymspace/backpex/blob/develop/skills/create-filter/SKILL.md
Implement a custom filter when built-in types are insufficient. Requires `Backpex.Filter` and implementation of `query/4`, `render/1`, and `render_form/1`. Use `Phoenix.Component` for HEEx support.
```elixir
defmodule MyAppWeb.Filters.PostCustom do
use Phoenix.Component
use Backpex.Filter
import Ecto.Query
@impl Backpex.Filter
def label, do: "Custom"
@impl Backpex.Filter
def query(query, attribute, value, _assigns) do
where(query, [x], field(x, ^attribute) == ^value)
end
@impl Backpex.Filter
def render(assigns) do
~H"""@value"""
end
@impl Backpex.Filter
def render_form(assigns) do
~H"""
"""
end
end
```
--------------------------------
### Add Backpex Resource Routes to Router
Source: https://github.com/naymspace/backpex/blob/develop/guides/get_started/installation.md
Use the `backpex_routes/0` macro and `live_session/3` with `Backpex.InitAssigns` to expose LiveResources and attach the `current_url` assign. This is the recommended approach for integrating LiveResources into your application's routing.
```elixir
# router.ex
import Backpex.Router
scope "/admin", MyAppWeb do
pipe_through :browser
backpex_routes()
# add these lines
live_session :default, on_mount: Backpex.InitAssigns do
live_resources "/posts", PostLive
end
end
```
--------------------------------
### Add Filter to LiveResource
Source: https://github.com/naymspace/backpex/blob/develop/guides/filter/how-to-add-a-filter.md
Integrate a defined filter module into your LiveResource by specifying it in the `filters/0` callback. This example adds a filter named 'category_id' using the 'PostCategorySelect' module.
```elixir
@impl Backpex.LiveResource
def filters, do: [
category_id: %{
module: MyAppWeb.Filters.PostCategorySelect
}
]
```
--------------------------------
### Configure Formatter for Backpex
Source: https://github.com/naymspace/backpex/blob/develop/guides/get_started/installation.md
Add Backpex to your `.formatter.exs` file to enable its formatter configuration, ensuring consistent code style.
```elixir
# my_app/.formatter.exs
[
import_deps: [:backpex]
]
```
--------------------------------
### Update PubSub Configuration Syntax
Source: https://github.com/naymspace/backpex/blob/develop/guides/upgrading/v0.8.md
Shows the change in PubSub configuration syntax from separate options to a keyword list within the `pubsub` key.
```elixir
use Backpex.LiveResource,
...
pubsub: Demo.PubSub,
topic: "users",
event_prefix: "user_"
```
```elixir
use Backpex.LiveResource,
...
pubsub: [
name: Demo.PubSub,
topic: "users",
event_prefix: "user_"
]
```
--------------------------------
### Phoenix Router Scope Alias Example
Source: https://github.com/naymspace/backpex/blob/develop/usage_rules.md
When using `scope` blocks in Phoenix, be aware that an optional alias is prefixed to all routes within the scope. This avoids duplicate module prefixes.
```elixir
scope "/admin", AppWeb.Admin do
pipe_through :browser
live "/users", UserLive, :index
end
```
--------------------------------
### Backpex Filter query/4 Callback
Source: https://github.com/naymspace/backpex/blob/develop/guides/filter/filter-validation.md
The `query/4` callback receives already-validated and casted values. This example shows how to use the validated `value` (an integer in this case) to construct a query condition.
```elixir
def query(query, attribute, value, _assigns) do
# value is already an integer
where(query, [x], field(x, ^attribute) == ^value)
end
```
--------------------------------
### Configure Resource Ordering with a Map
Source: https://github.com/naymspace/backpex/blob/develop/guides/live_resource/ordering.md
Specify the default ordering for resources by providing a map to the `init_order` option. This map should include the field to order by (`:by`) and the direction (`:direction`).
```elixir
use Backpex.LiveResource,
# ...other options
init_order: %{by: :inserted_at, direction: :desc}
```
--------------------------------
### Hide Filter Based on User Role
Source: https://github.com/naymspace/backpex/blob/develop/guides/filter/visibility-and-authorization.md
Implement the `can?/1` callback to conditionally show a filter. This example hides the filter unless the current user's role is `:admin`.
```elixir
defmodule MyAppWeb.Filters.MyFilter do
use BackpexWeb, :filter
@impl Backpex.Filter
def can?(assigns), do: assigns.current_user.role == :admin
end
```
--------------------------------
### Migrate Layout to Callback
Source: https://github.com/naymspace/backpex/blob/develop/guides/upgrading/v0.18.md
Move the `layout` option from `use Backpex.LiveResource` to the `layout/1` callback to avoid compile cycles. This change is recommended but not strictly required.
```elixir
defmodule MyAppWeb.PostLive do
use Backpex.LiveResource,
layout: {MyAppWeb.Layouts, :admin},
adapter_config: [...]
end
```
```elixir
defmodule MyAppWeb.PostLive do
use Backpex.LiveResource,
adapter_config: [...]
@impl Backpex.LiveResource
def layout(_assigns), do: {MyAppWeb.Layouts, :admin}
end
```
--------------------------------
### Configure Money Library Defaults
Source: https://github.com/naymspace/backpex/blob/develop/guides/upgrading/v0.16.md
Set default currency and formatting options for the `money` library in your `config/config.exs` file. These should align with your Backpex currency field configurations.
```elixir
config :money,
default_currency: :EUR,
separator: ".",
delimiter: ",",
symbol_on_right: true,
symbol_space: true
```
--------------------------------
### Show Field in All Views Except New
Source: https://github.com/naymspace/backpex/blob/develop/guides/fields/visibility.md
Use the `except` option to hide a field from specific views. This example shows the 'Likes' field in all views except the new view.
```elixir
# in your resource configuration file
@impl Backpex.LiveResource
def fields do
[
likes: %{
module: Backpex.Fields.Number,
label: "Likes",
except: [:new]
}
]
end
```
--------------------------------
### Configure Field Authorization with `can?/1`
Source: https://github.com/naymspace/backpex/blob/develop/guides/authorization/field-authorization.md
Use the `can?/1` callback in your field configuration to conditionally show fields. This example restricts the `inserted_at` field to only be visible in the `:show` live action.
```elixir
# in your resource configuration file
@impl Backpex.LiveResource
def fields do
[
inserted_at: %{
module: Backpex.Fields.DateTime,
label: "Created At",
can?: fn
%{live_action: :show} = _assigns ->
true
_assigns ->
false
end
}
]
end
```
--------------------------------
### Verify Compile Cycle Improvement
Source: https://github.com/naymspace/backpex/blob/develop/guides/upgrading/v0.18.md
Run this command to check for compile-time cycles after migrating the layout to a callback.
```bash
mix xref graph --format cycles --label compile-connected
```
--------------------------------
### Update Router with Default Redirect
Source: https://github.com/naymspace/backpex/blob/develop/guides/get_started/installation.md
Add a `get` route to your `router.ex` file that points to the redirect controller's action. This ensures that requests to the root of the scope are handled by the redirect.
```elixir
#router.ex
scope "/admin", MyAppWeb do
pipe_through :browser
backpex_routes()
# add this line
get "/", RedirectController, :redirect_to_posts
live_session :default, on_mount: Backpex.InitAssigns do
live_resources "/posts", PostLive
end
end
```
--------------------------------
### Set Available Page Size Options
Source: https://github.com/naymspace/backpex/blob/develop/guides/live_resource/pagination.md
Define the available page size choices for users with `per_page_options`. Defaults to [15, 50, 100] if not specified.
```elixir
use Backpex.LiveResource,
# ...other options
per_page_options: [10, 25, 50, 100]
```