forms

Shallow Controller, Deep Params: Form Object Pattern

When controllers become parameter jungles, use a form object. It centralizes coercion, validations, and save logic. This pattern is extremely effective for admin panels and multi-step flows.

HTML forms with validation and accessibility

HTML5 form validation uses attributes like required, pattern, min, max, and type to validate input. I leverage native validation before JavaScript. The <label> element associates text with inputs for accessibility. Input types like email, tel, u

Disable submit button while Turbo form is submitting

Double-submits are easy to trigger on slow connections, especially with Turbo where the page doesn’t visibly reload. I add a Stimulus controller that listens to turbo:submit-start and turbo:submit-end events on the form. On submit start, disable the s

Frame navigation that targets a specific frame via form_with

Sometimes a form submission should update a specific section rather than navigate the whole page. With Turbo, this is as easy as setting data-turbo-frame on the form. For example, a filter form can target a results frame, so submissions replace only t

Action Text comment form that works inside a Turbo Frame

Action Text is great, but you need to be deliberate about how you render it in a Turbo-powered UI. I keep the comment form inside a turbo_frame_tag so it can be replaced on validation errors (still 422). On success, I clear the form by replacing the f

Form handling with React Hook Form

React Hook Form provides performant form handling with minimal re-renders. Unlike controlled components that re-render on every keystroke, it uses uncontrolled inputs with refs. The register function connects inputs to the form state, and handleSubmit

Add/remove nested fields with Stimulus (no cocoon)

Nested fields are a common Rails pain point, and the old solution was heavy JS gems. With Stimulus, I keep it minimal: render a hidden <template> containing the fields with a placeholder index, then on “Add” clone it and swap the placeholder for

React Hook Form with Zod validation

Combining React Hook Form with Zod provides type-safe form validation with a schema-first approach. Zod schemas define the shape and rules for form data, and the zodResolver bridges them to React Hook Form. TypeScript infers form types from schemas au

Inline create form that prepends into a list with Turbo Streams

My favorite Hotwire demo is the classic “inline create” on an index page. The form sits at the top of the page. When submitted, the create action returns turbo streams that (1) prepend the new item into the list and (2) replace the form with a fresh,

Inline form validation feedback via Turbo Streams

When forms live inside a Turbo Frame (modal or inline edit), validation needs to feel immediate without a full-page refresh. I render the form inside a frame with an ID like post_form. On submit, create/update returns status: :unprocessable_entity and

Hotwire-powered multi-step forms

Multi-step forms traditionally require complex JavaScript state management, but Hotwire makes them simple. Each step is a separate controller action that renders a Turbo Frame containing the current step's fields. Navigation between steps updates only

Transactionally Create Parent + Children with accepts_nested_attributes_for

Nested writes should be transactional: either everything is created or nothing is. Rails does this well when you keep validations coherent and avoid side effects in callbacks.