Forms & Pages API
Per-attribute and per-method reference for forms and pages. For task-oriented documentation and worked examples, see the Forms & Pages guide.
A form inherits from Avo::Forms::Core::Form and lives under app/avo/forms/; a page inherits from Avo::Forms::Core::Page and lives under app/avo/pages/ (a main page one level under Avo::Pages, a sub-page nested deeper).
class Avo::Forms::AppSettings < Avo::Forms::Core::Form
self.title = "Application Settings"
def fields
# field declarations
end
def handle
# submission logic
end
end
class Avo::Pages::Settings < Avo::Forms::Core::Page
self.title = "Settings"
def navigation
page Avo::Pages::Settings::General, default: true
end
endShared attributes
Both Avo::Forms::Core::Form and Avo::Forms::Core::Page expose these class attributes.
-> self.title
The display title. On a form it renders as the header above the fields (unless a page placement sets show_header: false); on a page it's the page's own title.
self.title = "Application Settings"- Type: String
- Default:
nil. On a page, when unset the humanized last segment of the class name is used for the navigation label.
-> self.description
A description rendered below the title — in the form header, or below the page title.
self.description = "Manage your application configuration"- Type: String
- Default:
nil
-> self.id
The routing key — and URL segment. Forms are submitted to <root_path>/forms/<id> and pages served at <root_path>/pages/<id>, each resolved by its id at request time, so no routes are declared manually.
self.id = :app_settings- Type: Symbol or String
- Default: the class path under its namespace — a form under
Avo::Forms(e.g.Avo::Forms::Settings::Integrations→settings/integrations; inline under a page, it resolves against the page path instead), a page underAvo::Pages(e.g.Avo::Pages::Settings::General→settings/general). Virtual pages declared with a string title default the same way; override those with theidoption. - Constraint: must be unique across all forms (or all pages) — it's how a request is matched.
Form methods
-> fields
Defines the form's structure. Uses the same field syntax as Avo resources and actions, so it supports every Avo field type, panels and cards, and layout components.
def fields
field :email, as: :text, required: true
field :notifications, as: :boolean, default: true
end- Type: instance method you define
- Returns: ignored — declare fields for their side effect, as in resources
-> field
Declares a single field inside fields. Accepts all standard Avo field types and field options.
field :theme, as: :select, options: { light: "Light", dark: "Dark" }- Type: DSL method called inside
fields - Values: any Avo field type via
as:; all standard field options are supported (required:,default:,help_text:,width:,record:, …)
-> handle
Processes the submission and defines the response. Called when the form is submitted, with submitted data available through params.
def handle
current_user.update(params.permit(:first_name, :last_name))
flash[:notice] = "Saved"
default_response
end- Type: instance method you define
- Context: evaluated in the controller that received the request, so any controller helper (
params,current_user,flash,cookies,redirect_to, …) is available. - Helpers:
default_response— the standard redirect-back Turbo Stream response.
Experimental
handle runs in the controller's context rather than behind a dedicated DSL. This keeps the full Rails toolbox available, but the exact contract may change in a future release.
Page attributes
-> self.navigation_label
The label shown in the Avo main menu and in the page's sidebar entry, when it should differ from the title.
self.navigation_label = "App Configuration"- Type: String
- Default: falls back to
self.title; if that is also unset, the humanized last segment of the class name.
Page navigation and content
-> navigation
Defines the sub-pages and forms that make up a main page's navigation. Register children here with page and form.
def navigation
page Avo::Pages::Settings::General, default: true
form Avo::Forms::Profiles
end- Type: instance method you define
Parsed once at boot
navigation is evaluated a single time during application boot. Don't put conditional or otherwise dynamic logic inside it — it won't be re-evaluated per request.
-> page
Registers a sub-page inside navigation. Accepts either an existing page class or a string title that creates a virtual page inline.
def navigation
# Class-based: reference a page file
page Avo::Pages::Settings::General, default: true
# Virtual: declare the page inline with its content
page "Integrations",
description: "Connect third-party services",
content: -> do
form Avo::Forms::Settings::Slack
form Avo::Forms::Settings::Email
end
end- Type: DSL method called inside
navigation - Argument: a
Avo::Forms::Core::Pagesubclass, or a String title for a virtual page
Keyword options:
| Option | Type | Default | Behavior |
|---|---|---|---|
default | Boolean | false | Marks the page shown when the parent main page is accessed directly. Any page type. |
id | Symbol / String | derived | Routing key for a virtual page. Same behavior as self.id. |
description | String | nil | Description for a virtual page (string-title form only). |
content | Proc | nil | Block declaring the virtual page's forms (string-title form only). |
-> form
Registers a form by its class. form behaves differently depending on where it's called:
- Inside
content— renders the form on the page. Multiple forms stack in declaration order. - Inside
navigation— adds the form as a navigation entry that shows the form directly, under the current page, with no dedicated page file. Its navigation label and header default to the form'stitleanddescription.
def content
form Avo::Forms::Settings::AppSettings
form Avo::Forms::Settings::Profile, show_header: false
end- Type: DSL method called inside
contentornavigation - Argument: an
Avo::Forms::Core::Formsubclass
Keyword options:
| Option | Type | Default | Behavior |
|---|---|---|---|
show_header | Boolean | true | Whether to render the form's header (its title + description) above the fields, for this placement. |
-> content
Defines the forms displayed on this page. Register them with form; they render in declaration order.
def content
form Avo::Forms::Settings::AppSettings
form Avo::Forms::Settings::CompanyInfo
end- Type: instance method you define
Parsed once at boot
Like navigation, content is evaluated a single time during application boot. Keep it static — no conditional or dynamic logic.