Skip to main content

create-live-resource

Use when scaffolding a new Backpex LiveResource, setting up admin CRUD views, or configuring adapter_config, fields, filters, and routing for a resource.

소스 정보

저장소
naymspace/backpex
최근 소스 활동
2026년 10월 7일 06:43
감지된 SKILL.md 언어
영어
스타
844
포크
79

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
create-live-resource
description
Use when scaffolding a new Backpex LiveResource, setting up admin CRUD views, or configuring adapter_config, fields, filters, and routing for a resource.
# Creating a Backpex LiveResource You are an expert at creating LiveResources for Backpex. When the user wants to create a new admin resource, follow this process: 1. **Identify the Ecto schema** the resource will manage 2. **Generate the LiveResource module** with adapter_config, fields, and callbacks 3. **Add the route** to the router ## LiveResource Module Structure ```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 ] @impl Backpex.LiveResource def layout(_assigns), do: {MyAppWeb.Layouts, :admin} @impl Backpex.LiveResource def singular_name, do: "Post" @impl Backpex.LiveResource def plural_name, do: "Posts" @impl Backpex.LiveResource def fields do [ title: %{ module: Backpex.Fields.Text, label: "Title", searchable: true } ] end end ``` ## `use Backpex.LiveResource` Options | Option | Type | Default | Description | |--------|------|---------|-------------| | `adapter_config` | keyword | **required** | Ecto adapter configuration (see below) | | `adapter` | atom | `Backpex.Adapters.Ecto` | Data layer adapter | | `primary_key` | atom | `:id` | Primary key field | | `per_page_options` | list | `[15, 50, 100]` | Selectable page sizes | | `per_page_default` | integer | `15` | Default page size | | `init_order` | map or fn | `%{by: :id, direction: :asc}` | Initial sort order | | `fluid?` | boolean | `false` | Full-width layout | | `full_text_search` | atom | `nil` | PostgreSQL tsvector column name | | `save_and_continue_button?` | boolean | `false` | Show "Save & Continue" button | | `pubsub` | keyword | nil (falls back to `:backpex, :pubsub_server` app config, topic defaults to module name) | `[server: MyApp.PubSub]` | | `on_mount` | atom/list | nil | LiveView on_mount hooks | ## adapter_config (Ecto) | Key | Required | Description | |-----|----------|-------------| | `schema` | yes | Ecto schema module | | `repo` | yes | Ecto repo module | | `update_changeset` | no | `fn item, attrs, metadata -> changeset` | | `create_changeset` | no | `fn item, attrs, metadata -> changeset` | | `item_query` | no | `fn query, live_action, assigns -> query` | The `metadata` keyword list contains `:assigns` and `:target` (the form field that triggered the change). The `item_query` function must build on the incoming `query` argument (use `from p in query, ...`), not the schema directly. ## Required Callbacks | Callback | Returns | Description | |----------|---------|-------------| | `singular_name/0` | string | e.g. `"Post"` | | `plural_name/0` | string | e.g. `"Posts"` | | `fields/0` | keyword list | Field definitions | | `layout/1` | `{module, :function}` or `fn assigns -> ...` | Layout to use | ## Optional Callbacks | Callback | Default | Description | |----------|---------|-------------| | `can?/3` | always true | `fn assigns, action, item -> bool` | | `filters/0` | `[]` | Filter definitions | | `filters/1` | delegates to `filters/0` | Assigns-aware variant for dynamic filters | | `panels/0` | `[]` | Field grouping: `[key: "Label"]` | | `metrics/0` | `[]` | Index page metrics | | `resource_actions/0` | `[]` | Resource-level actions | | `item_actions/1` | returns default_actions unchanged | Modify default item actions | | `on_item_created/2` | noop | `fn socket, item -> socket` | | `on_item_updated/2` | noop | `fn socket, item -> socket` | | `on_item_deleted/2` | noop | `fn socket, item -> socket` | | `return_to/5` | index page | Custom redirect after save | | `index_row_class/4` | nil | Custom CSS for table rows | | `render_resource_slot/3` | default HTML | Override UI slots | | `translate/1` | delegates to `Backpex.translate/1` | Override UI strings | ## Router Setup ```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 ``` `backpex_routes()` must appear once per scope. `live_resources/3` generates routes for Index, Form (new/edit), and Show views. Options for `live_resources/3`: - `only: [:index, :show, :new, :edit]` to restrict routes - `except: [:new]` to exclude specific routes ## Complete Example ```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 ``` ## Conventions - **File location**: `lib/my_app_web/live/<resource>_live.ex` - **Module naming**: `MyAppWeb.<Resource>Live` (e.g. `MyAppWeb.ProductLive`) - **Changeset functions** should accept 3 arguments: `item`, `attrs`, `metadata` - **Use `layout/1` callback** instead of the `layout:` option (avoids compile-time dependencies) - **Always build on the incoming query** in `item_query/3`
GitHub에서 보기