This document is under construction.
First setup Rails 6 and Daemonite's Material UI as descrided in this gist.
- Install Simple Form
- Integrate with Bootstrap
- Add initializer:
# config/initializers/simple_form_daemonite.rb
Dir[Rails.root.join('lib/components/**/*.rb')].each { |f| require f }
SimpleForm.setup do |config|
# Custom wrapper to support text field boxes
# See http://daemonite.github.io/material/docs/4.1/material/text-fields/#text-field-boxes
config.wrappers :vertical_form_w_text_field_boxes, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
b.use :html5
b.use :placeholder
b.optional :maxlength
b.optional :minlength
b.optional :pattern
b.optional :min_max
b.optional :readonly
b.wrapper tag: :div, class: 'textfield-box' do |c|
c.optional :label
c.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: false
c.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
c.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
end
end
config.wrappers :inline_form_w_text_field_boxes, tag: 'span', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
b.use :html5
b.use :placeholder
b.optional :maxlength
b.optional :minlength
b.optional :pattern
b.optional :min_max
b.optional :readonly
b.wrapper tag: :div, class: 'textfield-box' do |c|
c.use :label, class: 'sr-only'
c.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
c.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
c.optional :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
end
end
# Input Group - custom component
# see example app and config at https://github.com/rafaelfranca/simple_form-bootstrap
config.wrappers :input_group, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
b.use :html5
b.use :placeholder
b.optional :maxlength
b.optional :minlength
b.optional :pattern
b.optional :min_max
b.optional :readonly
b.optional :label
b.wrapper :input_group_tag, tag: 'div', class: 'input-group textfield-box' do |ba|
ba.optional :prepend
ba.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: false
ba.optional :append
ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
end
end
# The default wrapper to be used by the FormBuilder.
config.default_wrapper = :vertical_form_w_text_field_boxes
end
- Create a custom component for prepending and appending add-ons to input elements:
# lib/components/input_group_component.rb
# custom component requires input group wrapper
module InputGroup
def prepend(_wrapper_options = nil)
span_tag = content_tag(:span, options[:prepend], class: 'input-group-text')
template.content_tag(:div, span_tag, class: 'input-group-prepend')
end
def append(_wrapper_options = nil)
span_tag = content_tag(:span, options[:append], class: 'input-group-text')
template.content_tag(:div, span_tag, class: 'input-group-append')
end
end
# Register the component in Simple Form.
SimpleForm.include_component(InputGroup)
- Redefine
StringInput
,TextInput
andNumericInput
:
# app/inputs/text_field_box.rb
module TextFieldBox
def input(wrapper_options)
ensure_placeholder
decorate_w_required
swap_hint_w_error
super
end
private
def decorate_w_required
return unless @required
append_required_mark
prepend_required_text
end
def ensure_placeholder
input_html_options[:placeholder] ||= raw_label_text
end
def append_required_mark
input_html_options[:placeholder].concat(self.class.translate_required_mark)
end
def prepend_required_text
@hint = [
"#{self.class.translate_required_mark} #{self.class.translate_required_text.titleize}",
hint
].compact.join(' - ')
end
# see https://material.io/components/text-fields/#anatomy
def swap_hint_w_error
input_options[:hint] = false if object.errors[attribute_name].any?
end
end
# app/inputs/string_input.rb
require 'text_field_box'
class StringInput < SimpleForm::Inputs::StringInput
include TextFieldBox
end
# app/inputs/text_input.rb
require 'text_field_box'
class TextInput < SimpleForm::Inputs::TextInput
include TextFieldBox
end
# app/inputs/numeric_input.rb
require 'text_field_box'
class NumericInput < SimpleForm::Inputs::NumericInput
include TextFieldBox
end