### Ash Form Builder Development Setup
Source: https://hexdocs.pm/ash_form_builder/0.4.0
Steps to set up the development environment for Ash Form Builder, including cloning the repository, fetching dependencies, and running tests.
```bash
git clone https://github.com/nagieeb0/ash_form_builder.git
cd ash_form_builder
mix deps.get
mix test
```
--------------------------------
### Generate Live CRUD Interface
Source: https://hexdocs.pm/ash_form_builder/0.4.0
Use the `mix ash_form_builder.gen.live` command to generate a full CRUD LiveView interface for a given resource. This example generates for 'Accounts User'.
```bash
mix ash_form_builder.gen.live Accounts User
```
--------------------------------
### Implement a Custom Theme
Source: https://hexdocs.pm/ash_form_builder/0.4.0
Create a custom theme by implementing the `AshFormBuilder.Theme` behaviour. This example shows how to render a text input field using Phoenix Components and custom classes.
```elixir
defmodule MyAppWeb.CustomTheme do
@behaviour AshFormBuilder.Theme
use Phoenix.Component
@impl AshFormBuilder.Theme
def render_field(assigns, opts) do
case assigns.field.type do
:text_input -> render_text_input(assigns)
:multiselect_combobox -> render_combobox(assigns)
# ... etc
end
end
defp render_text_input(assigns) do
~H"""
"""
end
end
```
--------------------------------
### Fetch Dependencies
Source: https://hexdocs.pm/ash_form_builder/0.4.0
After updating `mix.exs`, run this command to fetch the new dependencies.
```bash
mix deps.get
```
--------------------------------
### Generate Live CRUD with Custom Options
Source: https://hexdocs.pm/ash_form_builder/0.4.0
Demonstrates using generator options like `--page-size` to control the number of rows per page and `--out` to specify a custom output directory.
```bash
mix ash_form_builder.gen.live Inventory Product --page-size 50
mix ash_form_builder.gen.live Accounts User --out lib/my_app_web/live/admin
```
--------------------------------
### Using Ash Form Builder in LiveView
Source: https://hexdocs.pm/ash_form_builder/0.4.0
Shows how to integrate an Ash Form Builder form into a Phoenix LiveView for creating a user, including mounting the form component and handling submission.
```elixir
defmodule MyAppWeb.UserLive.Create do
use MyAppWeb, :live_view
def mount(_params, _session, socket) do
form = MyApp.Users.User.Form.for_create(actor: socket.assigns.current_user)
{:ok, assign(socket, form: form)}
end
def render(assigns) do
~H"""
<.live_component
module={AshFormBuilder.FormComponent}
id="user-form"
resource={MyApp.Users.User}
form={@form}
/>
"""
end
def handle_info({:form_submitted, MyApp.Users.User, user}, socket) do
{:noreply, push_navigate(socket, to: ~p"/users/#{user.id}")}
end
end
```
--------------------------------
### Scaffold LiveView CRUD Interface
Source: https://hexdocs.pm/ash_form_builder/0.4.0
This mix command scaffolds a complete Phoenix LiveView CRUD interface for a given Ash resource, including index and form views, pre-wired with Cinder.collection and AshFormBuilder.
```bash
mix ash_form.gen.live -r MyApp.Todos.Task --accent teal --transitions smooth
```
--------------------------------
### Register Custom Themes
Source: https://hexdocs.pm/ash_form_builder/0.4.0
Register your custom themes in config.exs to refer to them by short name within your forms.
```elixir
config :ash_form_builder, :themes,
my_brand: MyAppWeb.Themes.MyBrand,
retro: MyAppWeb.Themes.Retro
```
--------------------------------
### Generated LiveView Index Module
Source: https://hexdocs.pm/ash_form_builder/0.4.0
This is the generated `index.ex` file for a LiveView. It includes necessary `use` statements, aliases, and callback implementations for handling parameters, form submissions, and delete events.
```elixir
defmodule MyAppWeb.UserLive.Index do
use MyAppWeb, :live_view
use Cinder.UrlSync # injects handle_info for URL sync automatically
alias MyApp.Accounts.User
@collection_id "user-collection"
def mount(_params, _session, socket) do
{:ok, assign(socket, url_state: false, record: nil, form: nil)}
end
def handle_params(params, uri, socket) do
socket = Cinder.UrlSync.handle_params(params, uri, socket)
{:noreply, apply_action(socket, socket.assigns.live_action, params)}
end
# Triggered by AshFormBuilder.FormComponent after a successful Ash action
def handle_info({:form_submitted, User, _result}, socket) do
{:noreply,
socket
|> put_flash(:info, "User saved successfully.")
|> Cinder.refresh_table(@collection_id) # async re-query, no page reload
|> push_patch(to: ~p"/users")}
end
def handle_event("delete", %{"id" => id}, socket) do
User |> Ash.get!(id, actor: socket.assigns[:current_user])
|> Ash.destroy!(actor: socket.assigns[:current_user])
{:noreply, socket |> put_flash(:info, "User deleted.") |> Cinder.refresh_table(@collection_id)}
end
end
```
--------------------------------
### Testing Form Rendering and Creation
Source: https://hexdocs.pm/ash_form_builder/0.4.0
Tests for Ash Form Builder's LiveView, verifying form rendering with auto-inferred fields and the task creation process with redirection.
```elixir
defmodule MyAppWeb.TaskLiveTest do
use MyAppWeb.ConnCase
import Phoenix.LiveViewTest
test "renders form with auto-inferred fields", %{conn: conn} do
{:ok, _view, html} = live_isolated(conn, MyAppWeb.TaskLive.Form)
assert html =~ "Task Title"
assert html =~ "Description"
assert html =~ "Completed"
end
test "creates task and redirects", %{conn: conn} do
{:ok, view, _html} = live_isolated(conn, MyAppWeb.TaskLive.Form)
assert form(view, "#task-form", task: %{
title: "Test Task",
description: "Test description"
}) |> render_submit()
assert_redirect(view, ~p"/tasks/*")
end
end
```
--------------------------------
### Create Task Form in LiveView
Source: https://hexdocs.pm/ash_form_builder/0.4.0
This LiveView component demonstrates how to mount and render a create form for a Task resource using AshFormBuilder. It initializes the form with the current user as the actor.
```elixir
defmodule MyAppWeb.TaskLive.New do
use MyAppWeb, :live_view
def mount(_params, _session, socket) do
form = MyApp.Todos.Task.Form.for_create(actor: socket.assigns.current_user)
{:ok, assign(socket, form: form)}
end
def render(assigns) do
~H"""
<.live_component
module={AshFormBuilder.FormComponent}
id="task-create-form"
resource={MyApp.Todos.Task}
form={@form}
/>
"""
end
def handle_info({:form_submitted, MyApp.Todos.Task, task}, socket) do
{:noreply, push_navigate(socket, to: ~p"/tasks/#{task.id}")}
end
end
```
--------------------------------
### Basic File Upload Configuration
Source: https://hexdocs.pm/ash_form_builder/0.4.0
Configures a single file upload field for a user's avatar, specifying accepted image types and size limits. The uploaded file path is stored in the `avatar_path` attribute.
```elixir
defmodule MyApp.Users.User do
use Ash.Resource,
domain: MyApp.Users,
extensions: [AshFormBuilder]
attributes do
uuid_primary_key :id
attribute :name, :string, allow_nil?: false
attribute :avatar_path, :string
end
actions do
create :create do
accept [:name]
argument :avatar, :string, allow_nil?: true
# Store the uploaded file path in the avatar_path attribute
change fn changeset, _ ->
case Ash.Changeset.get_argument(changeset, :avatar) do
nil -> changeset
path -> Ash.Changeset.change_attribute(changeset, :avatar_path, path)
end
end
end
end
form do
action :create
submit_label "Create User"
field :name do
label "Full Name"
required true
end
field :avatar do
type :file_upload
label "Profile Photo"
hint "JPEG or PNG, max 5 MB"
accept :images # or ~w(.jpg .png) — see table below
max_files 1
max_file_size {5, :mb} # also accepts a raw byte integer
cloud MyApp.Buckets.Cloud
end
end
end
```
--------------------------------
### Configure Glassmorphism Theme
Source: https://hexdocs.pm/ash_form_builder/0.4.0
Enable the Glassmorphism theme by updating your application's configuration. This theme offers a premium glass-effect UI with animations and dark mode support.
```elixir
config :ash_form_builder, :theme, AshFormBuilder.Themes.Glassmorphism
```
--------------------------------
### Configure MishkaTheme
Source: https://hexdocs.pm/ash_form_builder/0.4.0
Set the MishkaTheme in your application's configuration if you are using the mishka_chelekom dependency. This integrates MishkaChelekom components for styling.
```elixir
config :ash_form_builder, :theme, AshFormBuilder.Theme.MishkaTheme
```
--------------------------------
### Define Create and Update Forms in a Resource
Source: https://hexdocs.pm/ash_form_builder/0.4.0
Configure separate 'form' blocks for create and update actions within the same Ash resource. This allows for distinct field configurations and submit labels for each action.
```elixir
defmodule MyApp.Todos.Task do
use Ash.Resource,
domain: MyApp.Todos,
extensions: [AshFormBuilder]
# ... attributes and relationships
actions do
defaults [:create, :read, :update, :destroy]
end
# CREATE form configuration
form do
action :create
submit_label "Create Task"
field :title do
label "Task Title"
placeholder "Enter task title"
required true
end
end
# UPDATE form configuration (separate block)
form do
action :update
submit_label "Save Changes"
# Can have different field customizations for update
field :title do
label "Task Title"
hint "Changing the title will notify collaborators"
end
end
end
```
--------------------------------
### Configure Shadcn Theme
Source: https://hexdocs.pm/ash_form_builder/0.4.0
Apply the Shadcn theme by modifying your application's configuration. This theme provides a clean, minimal design inspired by shadcn/ui.
```elixir
config :ash_form_builder, :theme, AshFormBuilder.Themes.Shadcn
```
--------------------------------
### Update Task Form in LiveView
Source: https://hexdocs.pm/ash_form_builder/0.4.0
This LiveView component shows how to mount and render an update form for an existing Task resource. It fetches the task and initializes the form for updating.
```elixir
defmodule MyAppWeb.TaskLive.Edit do
use MyAppWeb, :live_view
def mount(%{"id" => id}, _session, socket) do
task = MyApp.Todos.get_task!(id, actor: socket.assigns.current_user)
form = MyApp.Todos.Task.Form.for_update(task, actor: socket.assigns.current_user)
{:ok, assign(socket, form: form, mode: :edit)}
end
def render(assigns) do
~H"""
<.live_component
module={AshFormBuilder.FormComponent}
id="task-edit-form"
resource={MyApp.Todos.Task}
form={@form}
/>
"""
end
def handle_info({:form_submitted, MyApp.Todos.Task, task}, socket) do
{:noreply, push_navigate(socket, to: ~p"/tasks/#{task.id}")}
end
end
```
--------------------------------
### Custom Action Form Helpers
Source: https://hexdocs.pm/ash_form_builder/0.4.0
Demonstrates how Ash Form Builder generates helper functions for custom actions, including record-shaped actions and generic action calls.
```elixir
actions do
create :create do …
update :update do …
update :archive, accept: [] do …
update :publish, accept: [:published_at] do …
end
forms do
form :create do … end
form :update do … end
form :archive do submit_label "Archive" end
form :publish do submit_label "Publish now" end
end
```
```elixir
# Auto-generated:
MyApp.Posts.Post.Form.for_create() # :create (resource form)
MyApp.Posts.Post.Form.for_update(post) # :update (record form)
MyApp.Posts.Post.Form.for_archive(post, actor: user) # :archive (record form)
MyApp.Posts.Post.Form.for_publish(post, actor: user) # :publish (record form)
# Plus the generic fallback for anything else:
MyApp.Posts.Post.Form.for_action(:custom, record: post, actor: user)
```
--------------------------------
### LiveView Handler for Combobox Search
Source: https://hexdocs.pm/ash_form_builder/0.4.0
This LiveView event handler implements the search functionality for the searchable combobox. It filters tags based on the query and pushes the updated options back to the client.
```elixir
def handle_event("search_tags", %{"query" => query}, socket) do
tags = MyApp.Todos.Tag
|> Ash.Query.filter(contains(name: ^query))
|> MyApp.Todos.read!()
{:noreply, push_event(socket, "update_combobox_options", %{
field: "tags",
options: Enum.map(tags, &{&1.name, &1.id})
})}
end
```
--------------------------------
### Generated LiveView Index Template
Source: https://hexdocs.pm/ash_form_builder/0.4.0
This is the generated HEEx template for the LiveView index page. It includes a header with a 'New User' link, a `Cinder.collection` for displaying users, and a modal for creating or editing users using `AshFormBuilder.FormComponent`.
```html
<.header>
Users
<:actions>
<.link patch={~p"/users/new"}><.button>New User
<%!-- Cinder.collection: filterable, sortable, paginated — state synced to URL --%>
<%!-- TODO: Replace with your resource's real attributes (see Customising Columns) --%>
<:col :let={user} field="id" sort label="ID">{user.id}
<:col :let={user} label="Actions">
<.link patch={~p"/users/#{user}/edit"}>Edit
<.link phx-click="delete" phx-value-id={user.id}
data-confirm="Delete this user? This cannot be undone.">Delete
<%!-- Modal: mounts only for :new and :edit live_actions --%>
<.modal :if={@live_action in [:new, :edit]} id="user-modal" show
on_cancel={JS.patch(~p"/users")}>
<.live_component
module={AshFormBuilder.FormComponent}
id={if @record, do: "user-edit-#{@record.id}", else: "user-new"}
resource={MyApp.Accounts.User}
form={@form}
submit_label={if @live_action == :new, do: "Create User", else: "Save Changes"}
/>
```
--------------------------------
### Configure Creatable Combobox Field
Source: https://hexdocs.pm/ash_form_builder/0.4.0
This DSL configuration enables the 'creatable' feature for a multiselect combobox, allowing users to create new related records directly from the form. It specifies the create action, label, and search event.
```elixir
forms do
form :create do
field :tags do
type :multiselect_combobox
opts [
creatable: true,
create_action: :create,
create_label: "Create \"",
search_event: "search_tags"
]
end
end
end
```
--------------------------------
### Configure Dynamic Nested Has-Many Form
Source: https://hexdocs.pm/ash_form_builder/0.4.0
This DSL configuration defines a has-many relationship for subtasks and sets up a nested form for managing them. It includes labels for the section, adding, and removing subtasks, and defines fields for the nested resource.
```elixir
relationships do
has_many :subtasks, MyApp.Todos.Subtask
end
forms do
form :create do
nested :subtasks do
label "Subtasks"
cardinality :many
add_label "Add Subtask"
remove_label "Remove"
field :title do
required true
end
field :done do
type :toggle
end
end
end
end
```
--------------------------------
### Add Ash Form Builder Dependency
Source: https://hexdocs.pm/ash_form_builder/0.4.0
Add the necessary dependencies to your `mix.exs` file to include Ash Form Builder and its related components.
```elixir
defp deps do
[
{:ash, "~> 3.0"},
{:ash_phoenix, "~> 2.0"},
{:ash_form_builder, "~> 0.3.0"},
# Required if using mix ash_form_builder.gen.live
{:cinder, "~> 0.12"},
# Optional: For MishkaChelekom theme
{:mishka_chelekom, "~> 0.0.8"}
]
end
```
--------------------------------
### Multiple File Upload Configuration
Source: https://hexdocs.pm/ash_form_builder/0.4.0
Configures a file upload field for multiple attachments, specifying accepted document types, a maximum number of files, and size limits.
```elixir
field :attachments do
type :file_upload
label "Attachments"
hint "Upload multiple documents (max 5)"
accept :documents
max_files 5
max_file_size {10, :mb}
cloud MyApp.Buckets.Cloud
end
```
--------------------------------
### Preload Relationships for Update Forms in LiveView
Source: https://hexdocs.pm/ash_form_builder/0.4.0
Use the `for_update/2` helper in your LiveView to automatically preload many-to-many relationships for update forms. This ensures existing selections are displayed correctly.
```elixir
# In your LiveView
def mount(%{"id" => id}, _session, socket) do
# for_update/2 automatically preloads required relationships
task = MyApp.Todos.Task |> MyApp.Todos.get_task!(id)
form = MyApp.Todos.Task.Form.for_update(task, actor: socket.assigns.current_user)
{:ok, assign(socket, form: form)}
end
```
--------------------------------
### Configure Default Theme
Source: https://hexdocs.pm/ash_form_builder/0.4.0
Optionally configure the default theme for AshFormBuilder in your config.exs file. You can use short atoms or module names.
```elixir
config :ash_form_builder, :theme, :default
# config :ash_form_builder, :theme, :shadcn
# config :ash_form_builder, :theme, AshFormBuilder.Themes.Glassmorphism
```
--------------------------------
### Extend Ash Resource with AshFormBuilder
Source: https://hexdocs.pm/ash_form_builder/0.4.0
Include `AshFormBuilder` in the `extensions` list of your Ash Resource to enable form building capabilities.
```elixir
use Ash.Resource,
domain: MyApp.Todos,
extensions: [AshFormBuilder]
```
--------------------------------
### Use Domain Code Interfaces for Update Forms
Source: https://hexdocs.pm/ash_form_builder/0.4.0
Integrate update forms seamlessly with Domain Code Interfaces by defining helpers for specific actions. This provides a clean interface for generating update forms.
```elixir
# Domain configuration
defmodule MyApp.Todos do
use Ash.Domain
resources do
resource MyApp.Todos.Task do
define :form_to_create_task, action: :create
define :form_to_update_task, action: :update # ← Update form helper
end
end
end
# LiveView usage
form = MyApp.Todos.form_to_update_task(task, actor: current_user)
```
--------------------------------
### Adding Cinder Dependency
Source: https://hexdocs.pm/ash_form_builder/0.4.0
Add the Cinder dependency to your `mix.exs` file to use its data table functionality with Ash Form Builder.
```elixir
{:cinder, "~> 0.12"}
```
--------------------------------
### Customizing Cinder Columns
Source: https://hexdocs.pm/ash_form_builder/0.4.0
Customize Cinder data table columns by replacing placeholder slots in `index.html.heex` with resource attributes. Available attributes include filter, filter with select, and sort.
```heex
<:col :let={user} field="name" filter sort>{user.name}
<:col :let={user} field="email" filter>{user.email}
<:col :let={user} field="role" filter={:select}>{user.role}
<:col :let={user} field="inserted_at" sort>{user.inserted_at}
```
--------------------------------
### Generated Router Entries
Source: https://hexdocs.pm/ash_form_builder/0.4.0
These are the router entries generated by `mix ash_form_builder.gen.live`. They define the routes for the index, new, and edit LiveViews.
```elixir
scope "/", MyAppWeb do
pipe_through :browser
live "/users", UserLive.Index, :index
live "/users/new", UserLive.Index, :new
live "/users/:id/edit", UserLive.Index, :edit
end
```
--------------------------------
### Configure Many-to-Many Combobox Field
Source: https://hexdocs.pm/ash_form_builder/0.4.0
This DSL configuration defines a many-to-many relationship for tags and explicitly sets the form field type to `:multiselect_combobox` for a searchable interface. It also configures options for search event, debounce, label key, and value key.
```elixir
relationships do
many_to_many :tags, MyApp.Todos.Tag do
through MyApp.Todos.TaskTag
end
end
actions do
create :create do
accept [:title]
manage_relationship :tags, :tags, type: :append_and_remove
end
end
forms do
form :create do
field :tags do
type :multiselect_combobox
opts [
search_event: "search_tags",
debounce: 300,
label_key: :name,
value_key: :id
]
end
end
end
```
--------------------------------
### Add AshFormBuilder to mix.exs
Source: https://hexdocs.pm/ash_form_builder/0.4.0
Include the AshFormBuilder dependency in your project's mix.exs file to add it to your Elixir project.
```elixir
def deps do
[
{:ash_form_builder, "~> 0.4.0"}
]
end
```
--------------------------------
### Configure Default Theme
Source: https://hexdocs.pm/ash_form_builder/0.4.0
Set the default theme for AshFormBuilder in your application's configuration. The Default theme provides production-ready Tailwind CSS styling.
```elixir
config :ash_form_builder, :theme, AshFormBuilder.Themes.Default
```
--------------------------------
### Define a Form for an Ash Resource
Source: https://hexdocs.pm/ash_form_builder/0.4.0
Add the AshFormBuilder extension to your Ash Resource and define forms using the `forms do ... end` block. Fields are auto-inferred from the action's `accept` list, but can be overridden.
```elixir
defmodule MyApp.Todos.Task do
use Ash.Resource,
domain: MyApp.Todos,
extensions: [AshFormBuilder]
attributes do
uuid_primary_key :id
attribute :title, :string, allow_nil?: false, public?: true
attribute :description, :string, public?: true
attribute :completed, :boolean, default: false, public?: true
end
actions do
defaults [:read, :destroy]
create :create do
accept [:title, :description, :completed]
end
update :update do
accept [:title, :description, :completed]
end
end
forms do
form :create do
submit_label "Create Task"
accent :teal
transitions :smooth
field :title do
label "Task Title"
placeholder "Enter task title"
required true
end
end
form :update do
submit_label "Update Task"
accent :indigo
end
end
end
```
--------------------------------
### Ash Form Builder Field Type Inference
Source: https://hexdocs.pm/ash_form_builder/0.4.0
Ash Form Builder automatically maps Ash types to UI components for form generation. This table outlines the default mappings.
```text
Ash Type| Constraint| UI Type| Example
---|---|---|---
`:string`| -| `:text_input`| Text fields
`:text`| -| `:textarea`| Multi-line text
`:boolean`| -| `:checkbox`| Toggle switches
`:integer` / `:float`| -| `:number`| Numeric inputs
`:date`| -| `:date`| Date picker
`:datetime`| -| `:datetime`| DateTime picker
`:atom`| `one_of:`| `:select`| Dropdown
`:enum` module| -| `:select`| Enum dropdown
`many_to_many`| -| `:multiselect_combobox`| Searchable multi-select
`has_many`| -| `:nested_form`| Dynamic nested forms
```
=== COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.