Simple Form

repository·main·Indexed 27 days ago

https://github.com/heartcombo/simple_form

A flexible DSL for creating Rails forms that provides powerful components while maintaining layout control. It includes built-in support for CSS frameworks like Bootstrap 5 and Zurb Foundation 5, automatic input mapping based on database column types, and extensive I18n integration for labels, hints, and placeholders.

Tokens
8.8K
Snippets
22
Records
47
Agent score
94%

What's inside simple_form

  1. Use Optional Form Components

    main

    To prevent components like :hint or :placeholder from generating automatically, use the optional method in your wrapper configuration. An optional component will only be rendered if it is explicitly enabled in the view (e.g., f.input :name, hint: true).

    You can also use unless_blank: true on a wrapper to ensure it only renders when the content is present.

    config.wrappers placeholder: false do |b|
      b.use :placeholder
      b.use :label_input
      b.wrapper tag: :div, class: 'separator' do |component|
        component.optional :hint, wrap_with: { tag: :span, class: :hint }
        component.use :error, wrap_with: { tag: :span, class: :error }
      end
    end
  2. Configure form translations via I18n

    main

    Simple Form uses I18n to look up labels, hints, placeholders, include_blanks, and prompts.

    Structure

    Translations are organized by model and attribute under the simple_form key:

    en:
      simple_form:
        labels:
          user:
            username: 'User name'
        hints:
          user:
            username: 'User name to sign in.'
        placeholders:
          user:
            username: 'Your username'

    Advanced I18n Features

    • Action-specific translations: You can provide different labels for new vs edit actions by nesting them under the action name.
    • Defaults: Use a defaults key to specify translations for all models at once.
    • Prompt/Include Blank translation: To enable I18n lookups for :prompt or :include_blank, you must pass translate as the value: f.input :role, prompt: :translate.
    • Collection Options: If a collection is composed of symbols only, Simple Form will look up labels in simple_form.options.[model].[attribute].[symbol].
    • Namespaced Models: For a model like Admin::User, place translations under admin_user (not admin/user) within the simple_form hierarchy.
    • Simple Fields: For simple_fields_for :posts, use the plural posts in your locale file.
    en:
      simple_form:
        labels:
          user:
            username: 'User name'
            edit:
              username: 'Change user name'
        hints:
          defaults:
            username: 'User name to sign in.'
        placeholders:
          defaults:
            username: '****'
        options:
          user:
            role:
              admin: 'Administrator'
              editor: 'Editor'
  3. Manage HTML5 Features and Browser Validations

    main

    Simple Form enables HTML5 extensions (like email, number, required, autofocus) by default.

    Disable HTML5 Extensions: Remove b.use :html5 from your wrapper configuration.

    Disable Browser-side Validation: If you want to keep HTML5 attributes but prevent the browser from blocking form submission (e.g., via the required attribute), set SimpleForm.browser_validations = false. This adds novalidate to the form.

    Per-form Validation Control: You can add novalidate: true to a specific form via the html option: <%= simple_form_for(resource, html: { novalidate: true }) do |form| %>.

    HTML5 Date/Time Inputs: These are not generated by default. To use native browser date/time pickers, pass html5: true to the input: <%= f.input :expires_at, as: :date, html5: true %>.

  4. Create custom inputs

    main

    You can add new input types by creating a class that inherits from SimpleForm::Inputs::Base. To use the new input, call f.input :attribute, as: :your_custom_name in your view. You may need to create the app/inputs/ directory and restart your server.

    To redefine an existing input (e.g., adding a wrapper div to DateTimeInput), inherit from the existing class and override the input method.

    # app/inputs/currency_input.rb
    class CurrencyInput < SimpleForm::Inputs::Base
      def input(wrapper_options)
        merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
    
        "$ #{@builder.text_field(attribute_name, merged_input_options)}".html_safe
      end
    end
    
    # In your view
    f.input :money, as: :currency
  5. Install Simple Form

    main

    To install Simple Form in your Rails application, add the gem to your Gemfile, install it via bundler, and then run the Simple Form installation generator to create the necessary configuration files.

    # Add to Gemfile
    gem 'simple_form'
    bundle install
    rails generate simple_form:install
  6. Use Simple Form with Non-Active Record Objects

    main

    To use Simple Form with plain Ruby objects, you must satisfy certain requirements so the library can identify attributes and persistence state.

    Option 1: Include ActiveModel::Model This is the easiest way to make an object compatible.

    Option 2: Implement required methods If not using ActiveModel::Model, implement:

    • to_model: Returns the object.
    • to_key: Returns a unique key (e.g., id).
    • persisted?: Returns true/false.
    • model_name: Returns an object responding to param_key (e.g., OpenStruct.new(param_key: "user")).

    Attribute Inference: To allow Simple Form to automatically choose input types (like checkboxes for booleans), implement:

    • has_attribute?(attr_name)
    • type_for_attribute(attr_name): Must return an object responding to #type (e.g., OpenStruct.new(type: :boolean)).

    Explicit Form Definition: If your object is very minimal, you must specify the as: option in the form to tell Simple Form which class to use.

  7. Create and Customize Custom Wrappers

    main

    You can create nested wrappers or named wrappers to apply different styles to different forms or inputs.

    Named Wrappers: Define a wrapper with a name (e.g., :small) in the config, then apply it using wrapper: :small in simple_form_for or on a specific f.input call.

    Customizing Wrapper Components on Demand: If you define a custom wrapper with a name (e.g., :my_wrapper), you can pass specific options in your view to control its behavior:

    • my_wrapper: false: Turns off the custom wrapper.
    • my_wrapper_html: { id: '...' }: Configures the HTML attributes of the wrapper.
    • my_wrapper_tag: :p: Changes the HTML tag used for the wrapper.
    # Define a named wrapper
    config.wrappers :small do |b|
      b.use :placeholder
      b.use :label_input
    end
    
    # Use it in a form
    simple_form_for @user, wrapper: :small do |f|
      f.input :name
    end
    
    # Or on a specific input
    simple_form_for @user do |f|
      f.input :name, wrapper: :small
    end
  8. Enable Country Select

    main

    To use country selection inputs, you must add the country_select gem to your Gemfile.

    If you prefer not to use the gem, you can override the default behavior by mapping country inputs to a different type (e.g., :string) in your config/initializers/simple_form.rb file.

  9. Implement a custom form builder

    main

    You can create a custom form builder by inheriting from SimpleForm::FormBuilder. To use it, create a helper method that calls simple_form_for while passing your custom builder class to the builder: option.

    # Create the builder
    class CustomFormBuilder < SimpleForm::FormBuilder
      def input(attribute_name, options = {}, &block)
        super(attribute_name, options.merge(label: false), &block)
      end
    end
    
    # Create a helper to use it
    def custom_form_for(object, *args, &block)
      options = args.extract_options!
      simple_form_for(object, *(args << options.merge(builder: CustomFormBuilder)), &block)
    end
  10. Basic Usage of Simple Form

    main

    To use Simple Form, replace the standard Rails form_for with simple_form_for. This provides a DSL that maps input types (based on database column definitions) to specific helper methods, automatically generating labels, hints, and error messages.

    <%= simple_form_for @user do |f| %>
      <%= f.input :username %>
      <%= f.input :password %>
      <%= f.button :submit %>
    <% end %>
  11. Extend Simple Form with Custom Components

    main

    You can add custom logic/components to your wrappers by defining a module and including it via SimpleForm.include_component.

    1. Define a module with methods representing your new component options.
    2. Include the module in your initializer.
    3. Use the new method name within your config.wrappers block.
    # 1. Define the component
    module NumbersComponent
      def number(wrapper_options = nil)
        @number ||= begin
          options[:number].to_s.html_safe if options[:number].present?
        end
      end
    end
    
    # 2. Include it
    SimpleForm.include_component(NumbersComponent)
    
    # 3. Use it in config
    config.wrappers :with_numbers, tag: 'div', class: 'row', error_class: 'error' do |b|
      b.use :number, wrap_with: { tag: 'div', class: 'span1 number' }
      # ... other components
    end
    
    # 4. Use in view
    <%= f.input :title, number: 1 %>
  12. Configure Simple Form for Zurb Foundation 5

    main

    To use Zurb Foundation 5 wrappers, use the --foundation flag during installation.

    Note on Hints: The Foundation wrapper does not support the :hint option by default. To enable hints, you must uncomment the appropriate line in config/initializers/simple_form_foundation.rb and provide your own CSS styles for them.

    rails generate simple_form:install --foundation