npx claudepluginhub naymspace/backpexThis skill uses the workspace's default tool permissions.
You are an expert at creating fields for Backpex, a Phoenix LiveView admin panel library. When the user wants to add or create a field, follow this process:
Scaffolds Backpex LiveResources for Phoenix admin CRUD views, configures Ecto adapter_config, fields, filters, and router routes.
Generates FilamentPHP v4 form schemas with fields, validation, sections, tabs, relationships, and enforced layout organization using sections/fieldsets.
Provides Phoenix LiveView best practices: no DB queries in mount (called twice), load data in handle_params, security scopes, scoped PubSub topics, GenServer polling, async assigns, and gotchas.
Share bugs, ideas, or general feedback.
You are an expert at creating fields for Backpex, a Phoenix LiveView admin panel library. When the user wants to add or create a field, follow this process:
Backpex.Fieldfields/0 callback| Module | Use for |
|---|---|
Backpex.Fields.Text | Single-line text inputs |
Backpex.Fields.Textarea | Multi-line text inputs |
Backpex.Fields.Number | Numeric values |
Backpex.Fields.Boolean | Checkboxes / toggles |
Backpex.Fields.Select | Dropdown with static options |
Backpex.Fields.MultiSelect | Multi-value dropdown |
Backpex.Fields.Date | Date picker |
Backpex.Fields.DateTime | Date and time picker |
Backpex.Fields.Time | Time picker |
Backpex.Fields.Currency | Formatted currency values |
Backpex.Fields.URL | URLs with link rendering |
Backpex.Fields.Email | Email addresses |
Backpex.Fields.BelongsTo | belongs_to associations |
Backpex.Fields.HasMany | has_many associations |
Backpex.Fields.HasManyThrough | has_many through associations |
Backpex.Fields.InlineCRUD | Inline editing of embeds_many / has_many |
Backpex.Fields.Upload | File uploads |
| Option | Type | Description |
|---|---|---|
module | atom | Required. The field module |
label | string | Required. Display label |
searchable | boolean | Enable search on this column |
orderable | boolean | Enable column sorting |
visible | fn assigns -> bool | Controls visibility on all views except index |
can? | fn assigns -> bool | Controls visibility on all views including index |
only | list | Restrict to specific views: :new, :edit, :show, :index |
except | list | Hide from specific views |
panel | atom | Group into a named panel |
index_editable | boolean or fn assigns -> bool | Enable inline editing on index |
align | :left, :center, :right | Column alignment on index |
align_label | :top, :center, :bottom, or fn assigns -> atom | Label alignment in forms |
index_column_class | string or fn assigns -> string | Extra CSS class on index column |
render | fn assigns -> HEEx | Override value rendering |
render_form | fn assigns -> HEEx | Override form rendering |
help_text | string or fn assigns -> string | Text below form input |
default | fn assigns -> value | Default value for new items |
select | dynamic(...) | Ecto dynamic expression for computed/virtual fields |
custom_alias | atom | Custom alias for the field in queries |
translate_error | fn {msg, meta} -> {msg, meta} | Custom error message formatting |
Implement Backpex.Field with a @config_schema for field-specific options.
@callback render_value(assigns :: map()) :: %Phoenix.LiveView.Rendered{}
@callback render_form(assigns :: map()) :: %Phoenix.LiveView.Rendered{}
render_value/1 is used on both index and show views. render_form/1 is used on new and edit views.
These are provided by use Backpex.Field and can be overridden as needed:
@callback render_index_form(assigns) # For index_editable support (only truly optional callback)
@callback display_field(field) # Default: returns field name
@callback schema(field, schema) # Default: returns the schema
@callback association?(field) # Default: false
@callback assign_uploads(field, socket) # Default: returns socket unchanged
@callback before_changeset(changeset, attrs, metadata, repo, field, assigns) # 6-arity
@callback search_condition(schema_name :: binary(), field_name :: binary(), search_string :: binary()) # Default: ilike
| Assign | Description |
|---|---|
@value | Current field value |
@name | Field key atom |
@field_options | Merged field options map |
@form | Phoenix.HTML.Form (in form renders) |
@item | The full resource item struct |
@live_action | :index, :edit, :new, or :show |
@readonly | Boolean from readonly option |
@myself | LiveComponent reference for phx-target |
defmodule MyAppWeb.Fields.ColorPicker do
@config_schema [
palette: [
doc: "List of allowed hex colors.",
type: {:list, :string}
]
]
use Backpex.Field, config_schema: @config_schema
@impl Backpex.Field
def render_value(assigns) do
~H"""
<div class="flex items-center gap-2">
<span class="inline-block h-4 w-4 rounded-full" style={"background-color: #{@value}"}></span>
<span>{@value}</span>
</div>
"""
end
@impl Backpex.Field
def render_form(assigns) do
~H"""
<div>
<Layout.field_container>
<:label align={Backpex.Field.align_label(@field_options, assigns, :center)}>
<Layout.input_label for={@form[@name]} text={@field_options[:label]} />
</:label>
<BackpexForm.input
type="color"
field={@form[@name]}
translate_error_fun={Backpex.Field.translate_error_fun(@field_options, assigns)}
help_text={Backpex.Field.help_text(@field_options, assigns)}
phx-debounce={Backpex.Field.debounce(@field_options, assigns)}
/>
</Layout.field_container>
</div>
"""
end
end
@impl Backpex.LiveResource
def fields do
[
color: %{
module: MyAppWeb.Fields.ColorPicker,
label: "Color",
palette: ["#ff0000", "#00ff00", "#0000ff"]
}
]
end
fields/0 returns a keyword list. Each key is the Ecto schema field atom, each value is a map of options.
@impl Backpex.LiveResource
def fields do
[
title: %{
module: Backpex.Fields.Text,
label: "Title",
searchable: true
},
body: %{
module: Backpex.Fields.Textarea,
label: "Body",
except: [:index]
},
category: %{
module: Backpex.Fields.BelongsTo,
label: "Category",
display_field: :name,
searchable: true,
live_resource: MyAppWeb.CategoryLive
},
inserted_at: %{
module: Backpex.Fields.DateTime,
label: "Created At",
only: [:index, :show]
}
]
end
lib/my_app_web/fields/<snake_case_name>.exMyAppWeb.Fields.<FieldName>@config_schema before use Backpex.Field for custom field-specific optionsLayout.field_container and Layout.input_label in render_form/1 for consistent form layoutBackpexForm.input for standard input rendering with error handling