Problem:
In Rails 4.2, setting a global default value for textarea cols
and rows
:
TL;DR:
Because there seems to be no public-API from both SimpleForm 3.0 and Rails 4.2 to be able to set default textarea cols
and rows
values (see my Debugging below as to why), then I have come up with the following workarounds:
Workaround 1 (tested working):
create the following file:
# config/initializers/text_area_extensions.rb
module TextAreaExtensions
def render
@options[:cols] ||= 40
@options[:rows] ||= 20
super
end
end
ActionView::Helpers::Tags::TextArea.class_eval do
prepend TextAreaExtensions
end
... would render any textarea -- simpleform builder or rails form builder or text_area_tag -- to have default cols and rows like the following:
<textarea class="text" cols="40" rows="20"></textarea>
NOTE that this is a workaround of which is not a long-term robust solution, because this is only guaranteed to work to this specific version of ActionView::Helpers::Tags::TextArea
class. Later Rails major or even minor versions might not work!
Workaround 2:
Instead of "patching" ActionView::Helpers::Tags::TextArea
above, you can also patch SimpleForm::Inputs::TextInput
if you only want to set default cols and rows for SimpleForm forms but do not set default for Rails forms, but because I prefer Workaround 1 above and my answer is too lengthy already, so I skip. But if anyone interested to know, let me know, and I'll update this.
Workaround 3:
Probably a better approach is to use custom method that you can call (i.e. a view helper method), that will have the default cols and rows already, instead of "patching" the gem code like Workaround 1 above. However, I was under the impression that you have a big application already that you'd want to just simply set a global code, instead of manually setting/updating all affected view files (which you even said above), and thus my Workaround 1 above.
Debugging:
I traced the code of execution:
SimpleForm "text" input:
module SimpleForm
module Inputs
class TextInput < Base
enable :placeholder, :maxlength
def input
@builder.text_area(attribute_name, input_html_options)
end
end
end
end
... which do not suggest a public API in SimpleForm to set global-default cols and rows, and so following input_html_options
:
# ...
@input_html_options = html_options_for(:input, input_html_classes).tap do |o|
o[:readonly] = true if has_readonly?
o[:disabled] = true if has_disabled?
o[:autofocus] = true if has_autofocus?
end
# ...
... also do not suggest a public API in SimpleForm for setting global cols and rows. And so following Rails' @builder.text_area
(see code above), which led me here:
def text_area(object_name, method, options = {})
Tags::TextArea.new(object_name, method, self, options).render
end
of which which led me here: for
TextArea.new
def initialize(object_name, method_name, template_object, options = {})
@object_name, @method_name = object_name.to_s.dup, method_name.to_s.dup
@template_object = template_object
@object_name.sub!(/\[\]$/,"") || @object_name.sub!(/\[\]\]$/,"]")
@object = retrieve_object(options.delete(:object))
@options = options
@auto_index = retrieve_autoindex(Regexp.last_match.pre_match) if Regexp.last_match
end
... which also has no public API to set global cols and rows, and so following next here: for TextArea.new.render
def render
options = @options.stringify_keys
add_default_name_and_id(options)
if size = options.delete("size")
options["cols"], options["rows"] = size.split("x") if size.respond_to?(:split)
end
content_tag("textarea", options.delete("value") { value_before_type_cast(object) }, options)
end
... which also do not have a public API to set global cols and rows, which left me no choice but to "patch" the code using the workaround 1 above.
Trivia:
- I verified that you are right when you said that Rails 4 no longer sets default
cols
and rows
values for textarea
, because seems like DEFAULT_TEXT_AREA_OPTIONS = { "cols" => 40, "rows" => 20 }
is only implemented until Rails version 3.2.13 as you can see here