Skip to content

Rendering a form

Resources are convenient. They’re not mandatory.

A Form is just a schema with validation and HTML. Mount it on a custom Page, a Conduit component, or a plain view handler.

from almasix.orbit.forms import Form, TextInput, Toggle
settings = (
Form.make("settings")
.schema([
TextInput.make("site_name").required().max_length(80),
Toggle.make("maintenance").label("Maintenance mode"),
])
)
settings.fill({"site_name": "Acme", "maintenance": False})
errors = settings.validate(request_data)
if not errors:
save(settings.dehydrate())
html = settings.render(settings.get_state())
from almasix.orbit import Page
from almasix.orbit.forms import Form, TextInput
class BrandingPage(Page):
navigation_label = "Branding"
navigation_group = "Settings"
def form(self) -> Form:
return Form.make("branding").schema([
TextInput.make("brand_name").required(),
TextInput.make("primary_color").default("#f1511b"),
])

Wire fill / validate / dehydrate in your page action (or Conduit method). Orbit won’t invent a database for you — it will happily render the fields.

form.readonly() # Form-level flag
TextInput.make("slug").readonly() # Field-level

Readonly fields still show up; they just refuse to be edited. Handy for “review before publish” screens.

  • Settings that aren’t a CRUD model
  • Multi-step wizards that don’t map 1:1 to a Resource
  • Embedding a slice of Orbit UI inside a non-admin Conduit page

When you do have a model, prefer a Resource so navigation, permissions, and table/form/infolist stay in one place.

Next: Closures · Field reference.