### 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] ```