-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add html classes to inputs with the wrappers API #622
Conversation
I think you are distorting the wrappers API. I don't think that we should change the API to do this. I'm not happy with this implementation. Maybe allowing to pass classes to the component would be better. Something like: b.use :input, :class => ['cool'] |
@agrussellknives do you see any easy way to change your pull request to not change the wrappers API and pass the classes directly to the component? I really don't want to change the wrappers API to this case. Your feature make sense but the wrappers API is complex and using it to change classes without add a wrapper will make more complex. Also, thank you for the pull request. |
Some historial information. In #457 I change the wrappers API to not use I think that now we can change the API to pass the options directly to the component. b.use :input, :class => ['cool']
# Add :class to the input component
b.use :input, :wrap_with => { :class => :cool }
# create a wrapper with the class 'cool' to wrap the input. WDYT? |
@rafaelfranca it looks good, but we should be careful because a user my pass some options that are not recognized, for example:
So we need a form of contract between the underlying input and this. Finally, if we are improving this area, we should probably deprecate the others (less flexible) ways to customize the input classes. |
I've got no problem changing it for sure. I prefer @rafaelfranca 's API but didn't want to take it upon my self to un-depreciate things :) I took my cue from the parameters to the |
@stephenprater you can give @rafaelfranca I think it's a good approach to follow, would allow configuration per wrapper instead of global label/input classes for instance. Unsure about the need to deprecate the SimpleForm one's, since we could consider those as global to all wrappers? |
So you can pass But b.wrapper :tag => 'div', :class => 'foo' do |x|
x.use :input
end So we can't use this option to change the component, or we will distort the wrappers API and make it more confusing. |
@rafaelfranca gotcha. makes sense now. |
@carlosantoniodasilva yes, we can leave the SimpleForm configuration. |
@stephenprater are you work on it? I think this is a good path to add more customization to SimpleForm |
@rafaelfranca yes, i'll work on it. |
@josevalim How and how strictly do you think this contract should be enforced? Ignore non-whitelisted attributes? Raise an exception? Print a warning? Any guidance is appreciated. Current behavior just ignores things that don't make sense (like |
@stephenprater seems good now. I think is better to use black list in this case. Print a warning if the component is |
@carlosantoniodasilva @josevalim thoughts? |
super(name, [name], options) | ||
end | ||
|
||
def render(input) | ||
options = input.options | ||
if options[namespace] != false | ||
if [:input, :label_input].include? namespace |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why :input
is getting a different approach?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inputs keep their classes in a separate instance variable. it's dup
ed from @html_classes
in SimpleFrom::Inputs::Base#initialize
- why it does that I couldn't tell you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. Just to confirm. I was not in my computer and didn't look at the code. Thanks to explain.
Anything more I need to do to get this merged? |
@stephenprater I'll take a look and merge this tomorrow. |
@carlosantoniodasilva @josevalim @nashby do you guys agree with this path? I will make some refactorings after merge this one |
@@ -40,6 +40,11 @@ module Wrappers | |||
# In the example above, hint defaults to false, which means it won't automatically | |||
# do the lookup anymore. It will only be triggered when :hint is explicitly set. | |||
class Builder | |||
|
|||
class_attribute :non_tag_components | |||
self.non_tag_components = [:placeholder, :error, :hint, :html5, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be a constant since we are using only in this class
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
plugins, etc can add non tag producing components to wrappers, so if you wanted to be a good simpleform citizen, you'd add your component namespace this this list. I mean, I know you can modify the constant in place, since it's Ruby, but this would allow you to do something like this:
module SimpleForm
module Components
module Whatever
SimpleForm::Wrapper::Builder.non_tag_components << :whatever
def whatever
input_html_options[:'data-whatever'] ||= whatever_value
nil
end
def whatever_value
options[:whatever]
end
end
end
That said, I could abstract this so you're not directly addressing the builder class. It seems that theoretically the responsibility to know whether or not it produces a tag should really lie with the component definition - so maybe we move all of this logic there? That sounds like a separate patch though.
Thanks @stephenprater. I'm testing my app with your branch. |
Hate to be a noob, but @stephenprater do you mean rebase against plataformatec's or your pull? And then download the patchfile and apply? |
I rebased against upstream (this fork) a couple of months ago and can get a clean apply of the patch, but if you want to use my fork just depend on it in your Gemfile (make sure you use the classes_on_use branch) |
Thanks, @stephenprater. |
Is this pull request still of actuality? |
I think it would be nice if I could set attributes for specific elements
What is the reason of adding wrap_with option? It could be accomplished with element.wrapper tag: 'div', class: 'el-class' do |wrapper| ... end isn't it? |
+1 for this |
enable a user to add classes or other html attributes to inputs, labels, and custome components using the wrappers API. b.use :input, :class => ['cool'], :id => 'whatever' } A custom component which wants to support this functionality should look in `options[:#{namespace}_html]` for the html options to use. An ArgumentError is raised if an html attribue is passed to any component in `SimpleForm::FormBuilder::ATTRIBUTE_COMPONENTS` but otherwise no validation is done - so it's possible to pass invalid attributes to any tag generating component.
modified a test to cover this case and changed it to no longer memoize the input / label_html options hash. There's no big performance hit to doing so and it keeps the per input wrapper switching implementation clean
also, fix the behavior by making sure that wrapper options passed to a particular input override the options passed to the original builder in `SimpleForm::Inputs::Base#html_options_for` - this might be an existing bug exposed by this test since changing the code in this manner causes no test failures - and at least the behavior is now codified in a test
@rafaelfranca i hate to be an ass about this - but is there ANY CHANCE this could get merged? is there something i can do to help you? |
+1 Would lead to soo much cleaner code. I love to use different wrappers for different forms (especially for forms which have other dimensions in the Bootstrap 3 grid). But the only way to do so is currently (please correct me if I am wrong):
Shorter and no additional "div" around my label
|
👍 +1 |
Yes, this will be merged. As you can see it is in the 3.1 milestone. |
add html classes to inputs with the wrappers API
@stephenprater hey, I merged this PR in a separate branch and I found some problems. The error classes and hint classes are getting duplicated. I think you had the same problem with input classes (this is why I think you called |
👍 on this. I am currently using the config.wrappers :horizontal, tag: :div, class: 'form-group', error_class: 'has-error' do |b|
b.use :html5
b.use :placeholder
b.use :min_max
b.use :maxlength
b.optional :pattern
b.optional :readonly
b.use :label, class: 'col-md-2'
b.wrapper :right_col, tag: :div, class: 'col-md-5' do |component|
component.use :input
component.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
component.use :error, wrap_with: { tag: 'span', class: 'help-block has-error' }
end
end The form column widths can then be overridden via the defaults in the simple_form tag: simple_form_for @user, wrapper: :horizontal, html: { class: 'form-horizontal' }, defaults: { label_html: { class: 'col-md-3' }, right_col_html: { class: 'col-md-6' } } do |f| Only caveat is that while the label_html |
+1 |
add html classes to inputs with the wrappers API Conflicts: lib/simple_form/wrappers/builder.rb test/support/misc_helpers.rb
We made some changes (younited/simple_form@ffecbe0) to have a consistent behaviour for the merging of html attributes. We made the following changes (happened on the 2.2 branch since we cannot move to 3 yet):
|
+1 |
👍 this is extremely helpful when integrating simple_form with Foundation forms. |
Backport pull request heartcombo#622 to simple_form 2.1.x
enable a user to add classes or other html attributes to inputs,
labels, and custome components using the wrappers API. this is
accomplished by passing
false
to the tag key of the wrap_withoptions - like so
b.use :input, :wrap_with { :tag => false, :class => ['cool'] }
passing an argument with a
false
tag is only meaningful in the caseof a single wrapped component which generates a tag itself
(so,
label
andinput
is about it out of the box.) A customcomponent which wants to support this functionality should look in
options[:#{namespace}_html]
for the html options to use.My particular use case for this is that I have about a dozen different
forms, but only three "looks" - and bootstrap has a few places where
you need to put classes on the input. Rather than have to use
a custom input type, just to add a class to the string input, i want
to create three different wrappers for my three different looks and
specify the wrapper once.