Skip to content
Permalink
Browse files

Change `form_with` to generates ids by default

When `form_with` was introduced we disabled the automatic
generation of ids that was enabled in `form_for`. This usually
is not an good idea since labels don't work when the input
doesn't have an id and it made harder to test with Capybara.

You can still disable the automatic generation of ids setting
`config.action_view.form_with_generates_ids` to `false.`
  • Loading branch information...
npezza93 authored and rafaelfranca committed Jun 13, 2017
1 parent f76ca45 commit 260d6f112a0ffdbe03e6f5051504cb441c1e94cd
@@ -1,3 +1,14 @@
* Change `form_with` to generates ids by default.

When `form_with` was introduced we disabled the automatic generation of ids
that was enabled in `form_for`. This usually is not an good idea since labels don't work
when the input doesn't have an id and it made harder to test with Capybara.

You can still disable the automatic generation of ids setting `config.action_view.form_with_generates_ids`
to `false.`

*Nick Pezza*

* Fix issues with `field_error_proc` wrapping `optgroup` and select divider `option`.

Fixes #31088
@@ -478,6 +478,8 @@ def apply_form_for_options!(record, object, options) #:nodoc:

mattr_accessor :form_with_generates_remote_forms, default: true

mattr_accessor :form_with_generates_ids, default: true

# Creates a form tag based on mixing URLs, scopes, or models.
#
# # Using just a URL:
@@ -640,16 +642,6 @@ def apply_form_for_options!(record, object, options) #:nodoc:
#
# Where <tt>@document = Document.find(params[:id])</tt>.
#
# When using labels +form_with+ requires setting the id on the field being
# labelled:
#
# <%= form_with(model: @post) do |form| %>
# <%= form.label :title %>
# <%= form.text_field :title, id: :post_title %>
# <% end %>
#
# See +label+ for more on how the +for+ attribute is derived.
#
# === Mixing with other form helpers
#
# While +form_with+ uses a FormBuilder object it's possible to mix and
@@ -746,7 +738,6 @@ def apply_form_for_options!(record, object, options) #:nodoc:
# end
def form_with(model: nil, scope: nil, url: nil, format: nil, **options)
options[:allow_method_names_outside_object] = true
options[:skip_default_ids] = true

if model
url ||= polymorphic_path(model, format: format)
@@ -1044,16 +1035,6 @@ def fields_for(record_name, record_object = nil, options = {}, &block)
# or model is yielded, so any generated field names are prefixed with
# either the passed scope or the scope inferred from the <tt>:model</tt>.
#
# When using labels +fields+ requires setting the id on the field being
# labelled:
#
# <%= fields :comment do |fields| %>
# <%= fields.label :body %>
# <%= fields.text_field :body, id: :comment_body %>
# <% end %>
#
# See +label+ for more on how the +for+ attribute is derived.
#
# === Mixing with other form helpers
#
# While +form_with+ uses a FormBuilder object it's possible to mix and
@@ -1072,7 +1053,6 @@ def fields_for(record_name, record_object = nil, options = {}, &block)
# FormOptionsHelper#collection_select and DateHelper#datetime_select.
def fields(scope = nil, model: nil, **options, &block)
options[:allow_method_names_outside_object] = true
options[:skip_default_ids] = true

if model
scope ||= model_name_from_record_or_class(model).param_key
@@ -1676,7 +1656,7 @@ def to_model
def initialize(object_name, object, template, options)
@nested_child_index = {}
@object_name, @object, @template, @options = object_name, object, template, options
@default_options = @options ? @options.slice(:index, :namespace, :skip_default_ids, :allow_method_names_outside_object) : {}
@default_options = @options ? @options.slice(:index, :namespace, :allow_method_names_outside_object) : {}

convert_to_legacy_options(@options)

@@ -1985,7 +1965,6 @@ def fields_for(record_name, record_object = nil, fields_options = {}, &block)
# See the docs for the <tt>ActionView::FormHelper.fields</tt> helper method.
def fields(scope = nil, model: nil, **options, &block)
options[:allow_method_names_outside_object] = true
options[:skip_default_ids] = true

convert_to_legacy_options(options)

@@ -15,7 +15,6 @@ def initialize(object_name, method_name, template_object, options = {})

@object_name.sub!(/\[\]$/, "") || @object_name.sub!(/\[\]\]$/, "]")
@object = retrieve_object(options.delete(:object))
@skip_default_ids = options.delete(:skip_default_ids)
@allow_method_names_outside_object = options.delete(:allow_method_names_outside_object)
@options = options

@@ -97,7 +96,7 @@ def add_default_name_and_id(options)
index = name_and_id_index(options)
options["name"] = options.fetch("name") { tag_name(options["multiple"], index) }

unless skip_default_ids?
if generate_ids?
options["id"] = options.fetch("id") { tag_id(index) }
if namespace = options.delete("namespace")
options["id"] = options["id"] ? "#{namespace}_#{options['id']}" : namespace
@@ -183,8 +182,8 @@ def name_and_id_index(options)
end
end

def skip_default_ids?
@skip_default_ids
def generate_ids?
ActionView::Helpers::FormHelper.form_with_generates_ids
end
end
end
@@ -12,7 +12,6 @@ class CheckBoxBuilder < Builder # :nodoc:
def check_box(extra_html_options = {})
html_options = extra_html_options.merge(@input_html_options)
html_options[:multiple] = true
html_options[:skip_default_ids] = false
@template_object.check_box(@object_name, @method_name, html_options, @value, nil)
end
end
@@ -11,7 +11,6 @@ class CollectionRadioButtons < Base # :nodoc:
class RadioButtonBuilder < Builder # :nodoc:
def radio_button(extra_html_options = {})
html_options = extra_html_options.merge(@input_html_options)
html_options[:skip_default_ids] = false
@template_object.radio_button(@object_name, @method_name, @value, html_options)
end
end
@@ -75,10 +75,6 @@ def render(&block)
def render_component(builder)
builder.translation
end

def skip_default_ids?
false # The id is used as the `for` attribute.
end
end
end
end
@@ -8,7 +8,7 @@ def initialize(object_name, method_name, template_object, choices, options, html
@choices = block_given? ? template_object.capture { yield || "" } : choices
@choices = @choices.to_a if @choices.is_a?(Range)

@html_options = html_options.except(:skip_default_ids, :allow_method_names_outside_object)
@html_options = html_options.except(:allow_method_names_outside_object)

super(object_name, method_name, template_object, options)
end
@@ -28,6 +28,15 @@ class Railtie < Rails::Engine # :nodoc:
end
end

initializer "action_view.form_with_generates_ids" do |app|
ActiveSupport.on_load(:action_view) do
form_with_generates_ids = app.config.action_view.delete(:form_with_generates_ids)
unless form_with_generates_ids.nil?
ActionView::Helpers::FormHelper.form_with_generates_ids = form_with_generates_ids
end
end
end

initializer "action_view.logger" do
ActiveSupport.on_load(:action_view) { self.logger ||= Rails.logger }
end
Oops, something went wrong.

0 comments on commit 260d6f1

Please sign in to comment.
You can’t perform that action at this time.