A number of the concepts in Primer Forms are borrowed from the view_component framework. For example, forms are defined inside Ruby classes and rendered using the
Let's create a sign up form and render it on the page.
Example for the impatient
class SignUpForm < ApplicationForm
form do |sign_up_form|
sign_up_form.group(layout: :horizontal) do |name_group|
label: "First name",
caption: "What your friends call you."
label: "Last name",
caption: "What the principal calls you."
label: "Dietary restrictions",
caption: "Any allergies?"
label: "Send me gobs of email!",
caption: "Check this if you enjoy getting spam."
def initialize(show_notifications_checkbox: true)
@show_notifications_checkbox = show_notifications_checkbox
Autoloading is automatically enabled for any sub-directory inside a Rails' app's app/ directory. Accordingly, we recommend placing all form classes inside app/forms/.
The directory structure within app/forms/ is arbitrary, but we have seen success using the same directory structure as app/controllers/. For example:
Our example class above inherits from
ApplicationForm. This follows the Rails convention of a base class that houses application-specific logic common to all forms. It's similar in purpose to
Ultimately, forms must inherit from
ApplicationForm can be as simple as:
class ApplicationForm < Primer::Forms::Base
# empty body, add common methods, includes, etc here
ApplicationForm in app/forms/application_form.rb
Anatomy of a form
Forms are just Ruby classes that inherit from
Primer::Forms::Base. Define a form's inputs using the
form class method, which accepts a block. The block is called with an instance of
Primer::Forms::Dsl::FormObject, which responds to the following form input methods:
Forms are rendered using the familiar Rails
<%= primer_form_with(model: @user) do |f| %>
<%= render SignUpForm.new(f, show_notifications_checkbox: false) %>
<% end %>
You may have noticed the use of the
primer_form_with helper above. This helper is analogous to Rails'
form_with helper, but layers on some additional functionality. It automatically:
- configures the form to use Primer's form builder
- disables Rails' default error markup functionality, which breaks Primer styling
- forces labels to always identify their inputs via the
- enables the special handling of
system_arguments that allows for utility arguments like
ml: 2 and friends
It is recommended to always use
primer_form_with instead of
Before the introduction of
#form_with in Rails 5.1, forms were created using the
#form_for helper. Although
#form_for has since been soft-deprecated, Primer includes the analogous
#primer_form_for for completeness. Prefer
#primer_form_with for new forms.