Merge pull request #1556 from plataformatec/plataformatec/frg-api-to-register-components
Add API to register custom components
This commit is contained in:
commit
e294ee2eda
|
@ -1,6 +1,7 @@
|
|||
## Unreleased
|
||||
|
||||
* Allow custom errors classes to inputs . [@feliperenan](https://github.com/feliperenan)
|
||||
* Add API to register custom components.[@feliperenan](https://github.com/feliperenan)
|
||||
* Allow custom errors classes to inputs.[@feliperenan](https://github.com/feliperenan)
|
||||
* Remove support from Rails 4.0, 4.1 and 4.2. [@feliperenan](https://github.com/feliperenan)
|
||||
* Add support for citext, hstore, json & jsonb column types. [@swrobel](https://github.com/swrobel)
|
||||
|
||||
|
|
86
README.md
86
README.md
|
@ -989,6 +989,92 @@ when the content is present.
|
|||
end
|
||||
```
|
||||
|
||||
## Custom Components
|
||||
|
||||
When you use custom wrappers, you might also be looking for a way to add custom components to your
|
||||
wrapper. The default components are:
|
||||
|
||||
```ruby
|
||||
:label # The <label> tag alone
|
||||
:input # The <input> tag alone
|
||||
:label_input # The <label> and the <input> tags
|
||||
:hint # The hint for the input
|
||||
:error # The error for the input
|
||||
```
|
||||
|
||||
A custom component might be interesting for you if your views look something like this:
|
||||
|
||||
```erb
|
||||
<%= simple_form_for @blog do |f| %>
|
||||
<div class="row">
|
||||
<div class="span1 number">
|
||||
1
|
||||
</div>
|
||||
<div class="span8">
|
||||
<%= f.input :title %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="span1 number">
|
||||
2
|
||||
</div>
|
||||
<div class="span8">
|
||||
<%= f.input :body, as: :text %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
```
|
||||
|
||||
A cleaner method to create your views would be:
|
||||
|
||||
```erb
|
||||
<%= simple_form_for @blog, wrapper: :with_numbers do |f| %>
|
||||
<%= f.input :title, number: 1 %>
|
||||
<%= f.input :body, as: :text, number: 2 %>
|
||||
<% end %>
|
||||
```
|
||||
|
||||
To use the number option on the input, first, tells to Simple Form the place where the components
|
||||
will be:
|
||||
|
||||
``` ruby
|
||||
# config/initializers/simple_form.rb
|
||||
Dir[Rails.root.join('lib/components/**/*.rb')].each { |f| require f }
|
||||
```
|
||||
|
||||
Create a new component within the path specified above:
|
||||
|
||||
```ruby
|
||||
# lib/components/numbers_component.rb
|
||||
module NumbersComponent
|
||||
# To avoid deprecation warning, you need to make the wrapper_options explicit
|
||||
# even when they won't be used.
|
||||
def number(wrapper_options = nil)
|
||||
@number ||= begin
|
||||
options[:number].to_s.html_safe if options[:number].present?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
SimpleForm.include_component(NumbersComponent)
|
||||
```
|
||||
|
||||
Finally, add a new wrapper to the config/initializers/simple_form.rb file:
|
||||
|
||||
```ruby
|
||||
config.wrappers :with_numbers, tag: 'div', class: 'row', error_class: 'error' do |b|
|
||||
b.use :html5
|
||||
b.use :number, wrap_with: { tag: 'div', class: 'span1 number'}
|
||||
b.wrapper tag: 'div', :class: 'span8' do |ba|
|
||||
ba.use :placeholder
|
||||
ba.use :label
|
||||
ba.use :input
|
||||
ba.use :error, wrap_with: { tag: 'span', class: 'help-inline' }
|
||||
ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
## HTML 5 Notice
|
||||
|
||||
By default, **Simple Form** will generate input field types and attributes that are supported in HTML5,
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
#
|
||||
# Uncomment this and change the path if necessary to include your own
|
||||
# components.
|
||||
# See https://github.com/plataformatec/simple_form#custom-components to know
|
||||
# more about custom components.
|
||||
# Dir[Rails.root.join('lib/components/**/*.rb')].each { |f| require f }
|
||||
#
|
||||
# Use this setup block to configure all options available in SimpleForm.
|
||||
SimpleForm.setup do |config|
|
||||
# Wrappers are used by the form builder to generate a
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
#
|
||||
# Uncomment this and change the path if necessary to include your own
|
||||
# components.
|
||||
# See https://github.com/plataformatec/simple_form#custom-components to know
|
||||
# more about custom components.
|
||||
# Dir[Rails.root.join('lib/components/**/*.rb')].each { |f| require f }
|
||||
#
|
||||
# Use this setup block to configure all options available in SimpleForm.
|
||||
SimpleForm.setup do |config|
|
||||
config.error_notification_class = 'alert alert-danger'
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
#
|
||||
# Uncomment this and change the path if necessary to include your own
|
||||
# components.
|
||||
# See https://github.com/plataformatec/simple_form#custom-components to know
|
||||
# more about custom components.
|
||||
# Dir[Rails.root.join('lib/components/**/*.rb')].each { |f| require f }
|
||||
#
|
||||
# Use this setup block to configure all options available in SimpleForm.
|
||||
SimpleForm.setup do |config|
|
||||
# Don't forget to edit this file to adapt it to your needs (specially
|
||||
|
|
|
@ -265,6 +265,49 @@ See https://github.com/plataformatec/simple_form/pull/997 for more information.
|
|||
@@configured = true
|
||||
yield self
|
||||
end
|
||||
|
||||
# Includes a component to be used by Simple Form. Methods defined in a
|
||||
# component will be exposed to be used in the wrapper as Simple::Components
|
||||
#
|
||||
# Examples
|
||||
#
|
||||
# # The application needs to tell where the components will be.
|
||||
# Dir[Rails.root.join('lib/components/**/*.rb')].each { |f| require f }
|
||||
#
|
||||
# # Create a custom component in the path specified above.
|
||||
# # lib/components/input_group_component.rb
|
||||
# module InputGroupComponent
|
||||
# def prepend
|
||||
# ...
|
||||
# end
|
||||
#
|
||||
# def append
|
||||
# ...
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# SimpleForm.setup do |config|
|
||||
# # Create a wrapper using the custom component.
|
||||
# config.wrappers :input_group, tag: :div, error_class: :error do |b|
|
||||
# b.use :label
|
||||
# b.optional :prepend
|
||||
# b.use :input
|
||||
# b.use :append
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Using the custom component in the form.
|
||||
# <%= simple_form_for @blog, wrapper: input_group do |f| %>
|
||||
# <%= f.input :title, prepend: true %>
|
||||
# <% end %>
|
||||
#
|
||||
def self.include_component(component)
|
||||
if Module === component
|
||||
SimpleForm::Inputs::Base.include(component)
|
||||
else
|
||||
raise TypeError, "SimpleForm.include_component expects a module but got: #{component.class}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
require 'simple_form/railtie' if defined?(Rails)
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'test_helper'
|
||||
|
||||
# Module that represents a custom component.
|
||||
module Numbers
|
||||
def number(wrapper_options = nil)
|
||||
@number ||= options[:number].to_s.html_safe
|
||||
end
|
||||
end
|
||||
|
||||
# Module that represents a custom component.
|
||||
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
|
||||
|
||||
class CustomComponentsTest < ActionView::TestCase
|
||||
test 'includes the custom components' do
|
||||
SimpleForm.include_component Numbers
|
||||
|
||||
custom_wrapper = SimpleForm.build tag: :div, class: "custom_wrapper" do |b|
|
||||
b.use :number, wrap_with: { tag: 'div', class: 'number' }
|
||||
end
|
||||
|
||||
with_form_for @user, :name, number: 1, wrapper: custom_wrapper
|
||||
|
||||
assert_select 'div.number', text: '1'
|
||||
end
|
||||
|
||||
test 'includes custom components and use it as optional in the wrapper' do
|
||||
SimpleForm.include_component InputGroup
|
||||
|
||||
custom_wrapper = SimpleForm.build tag: :div, class: 'custom_wrapper' do |b|
|
||||
b.use :label
|
||||
b.optional :prepend
|
||||
b.use :input
|
||||
b.use :append
|
||||
end
|
||||
|
||||
with_form_for @user, :name, prepend: true, wrapper: custom_wrapper
|
||||
|
||||
assert_select 'div.input-group-prepend > span.input-group-text'
|
||||
assert_select 'div.input-group-append > span.input-group-text'
|
||||
end
|
||||
|
||||
test 'raises a TypeError when the component is not a Module' do
|
||||
component = 'MyComponent'
|
||||
|
||||
exception = assert_raises TypeError do
|
||||
SimpleForm.include_component(component)
|
||||
end
|
||||
assert_equal exception.message, "SimpleForm.include_component expects a module but got: String"
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue