Rails Simple Form input with Font-Awesome - simple-form

I want to use icons instead of text for labels in a horizontal simple_form. However, I am unable to separate the text from the icons
= simple_form_for #user, html: { class: 'form-horizontal' }, wrapper: :horizontal_form do |f|
# shows 'username' label only
= f.input :username
# shows icon with 'username'
= f.input :username, label_html: {class: "fas fa-user"}
# shows nothing
= f.input :username, label_html: {class: "fas fa-user"}, label: false

For those who want to do the same, there is a simpler/cleaner way :
= f.label :username, label: ('<i class="fas fa-user"></i>').html_safe
= f.text_field :username
Also work with I18n localization file :
(en.yml)
username: '<i class="fas fa-user"></i>'
then
= f.label :name, label: t(:username).html_safe
= f.text_field :username
Using simple_form (4.1.0)
Hope this help.

You can use the wrapper_html option:
= f.input :username, label: false, wrapper_html: { class: 'fa fa-user' }
You will probably have to add some css to make it look the way you want. For example, to get the icon on a different line than the input, I had to add display: block to the icon.

wrapper_html: and label_html: were complicated, so I just did it manually
.row
.col-3
.text-right
i.fas.fa-user
.col-9
= f.input_field :username, label: false, class: 'form-control'

I've just implemented this very thing on my own project. There was a really simple solution.
First, I created a helper for outputting fontawesome icons. In app/helpers/font_awesome_helper.rb:
module FontAwesomeHelper
def fa_icon(icon, style: :regular)
content_tag(:i, "", class: [icon_style_class(style), icon_class(icon)].join(" "))
end
private
def icon_class(icon)
"fa-#{icon}"
end
def icon_style_class(style)
case style
when :light, :l
"fal"
when :regular, :r
"far"
when :solid, :s
"fas"
when :duotone, :duo, :d
"fad"
else
"fa"
end
end
end
You can extend this further to support inverting icon colours, flipping horizontally, etc.
Finally, you can use your fa_icon helper in your simple-form input:
= f.input :username, label: fa_icon("user", style: :solid)

Related

Recaptcha gem needs a failed subimission on Rails7

A working form with recaptcha moved from rails6 to rails7 always arises a recaptcha validation error at first submit. On second submit it works.
= form_with url: mail_submit_path do |form|
= render partial: "err_details", locals: {field: :email}
.field
%label.label email
.control.has-icons-left
= form.text_field :email, value: #email, required: true, class: "input"
%span.icon.is-left
%i.fas.fa-envelope{:'aria-hidden' => "true"}
= render partial: "err_details", locals: {field: :captcha}
.field
.recaptcha
= recaptcha_tags
.field
.control
= form.submit "Submit", class: "button is-link"
On first submit some data is missing: from the rails logs:
I, [2022-01-18T18:42:23.795409 #1451245] INFO -- : [3c877c6c-5a2a-46e5-8ff6-5338c36d1078] Parameters: {"authenticity_token"=>"[FILTERED]", "email"=>"someone#gmail.com", "g-recaptcha-response"=>" ", "commit"=>"Submit"}
I would think it is a turbo issue, but not sure.
I was having the same issue in Rails 6.1.4. For some reason, changing
<%= recaptcha_tags %>
to
<%= recaptcha_tags(noscript: false) %>
worked for me.
I'd also like to add that I've had more success disabling Turbo for forms using recpatcha tags.
<%= form_with(model: #resource, local: true, data: { turbo: "false"}) do |f| %>

Rails 5 - Ransack query with Simple Form grouping with OR combinator

In my application I have a JobAd model. With several attributes, and I am using Ransack, with Simple Form to query this model.
For some attributes, like :title, :category, I want to use the default combinator AND, but for a specific group of attributes I want to use OR combinator. This attributes are:
onsite_job (type boolean)
full_remote (type boolean)
partial_remote (type boolean)
So far I was able to make the form work with the AND combinator. But I am not able to create the group for those fields. How can I achieve this, using Ransack with Simple Form builder.
In my view I have the following:
= search_form_for #q, url: backoffice_person_offer_suggestions_path(#person), remote: true, wrapper: :default20, builder: SimpleForm::FormBuilder, html: { method: :get } do |f|
= f.input :category_id_in, as: :select, collection: -> { Category.all },label: 'Category', input_html: { class: 'ld-select-button', multiple: true }
= f.input :experience_min_eq, collection: ProfileForm::EXPERIENCE_YEARS, label: 'Minimum Experience Years', input_html: { class: 'ld-select-button' }, include_blank: 'Any'
/ [...some other fields..]
= f.input :onsite_job_true, as: :ld_boolean, label: 'Onsite', input_html: { include_hidden: false }
= f.input :full_remote_true, as: :ld_boolean, label: 'Fully remote', input_html: { include_hidden: false }
= f.input :partial_remote_true, as: :ld_boolean, label: 'Partially remote', input_html: { include_hidden: false }
/ [...some other fields..]
= f.submit value: 'Search', class:'ld-button ld-blue-button ld-medium-button'
How can I group those attributes under a OR combinator?
Ruby 2.6.6
Rails 5.2.5
PostgreSQL 10.18
Ransack 2.3.2
Simple Form 5.0.2
Update
If I remove Simple Form from my project, I am able to generate the appropriate input tag with with the nested group:
f.grouping_fields do |g|
g.check_box :onsite_job_true
end
Output:
<input name="q[g][0][onsite_job_true]" type="hidden" value="0">
<input type="checkbox" value="1" name="q[g][0][onsite_job_true]" id="q_g_0_onsite_job_true">
But when I add Simple Form, if I try code like: f.input_field :grouping_fields or f.input :grouping_fields
I get an error:
NoMethodError: undefined method `grouping_fields' for Ransack::Search<class: JobAd, base: Grouping <combinator: and>>:Ransack::Search
Which seems Simple Form is sending the :grouping_fields to the Ransack instance#q.
The problem was the FormHelper builder was set to builder: SimpleForm::FormBuilder.
That's why I was not able to do f.grouping_fields
After removing the builder: SimpleForm::FormBuilder, I was able to do:
= f.grouping_fields do |g|
= g.input :m, as: :hidden, input_html: { value: 'or' }
= g.input :onsite_job_true, as: :ld_boolean, label: 'Onsite', input_html: { include_hidden: false }
= g.input :full_remote_true, as: :ld_boolean, label: 'Fully remote', input_html: { include_hidden: false }
= g.input :partial_remote_true, as: :ld_boolean, label: 'Partially remote', input_html: { include_hidden: false }
Which generated the appropriate grouping with the OR combinator.

rails 4: Adding a class to a select tag

Trying to add a class to a select tag
<%= f.select(:ptype, options_for_select(TourParticipation::PTYPES, selected: "traveler", disabled: "Role:") , { :class => "widens" } ) %>
results in
<select name="tour_participation[ptype]" id="tour_participation_ptype"></select>
Why is the class not applied to my select tag?
You forget that before html_options is options hash. Try this:
<%= f.select(:ptype, options_for_select(TourParticipation::PTYPES, selected: "traveler", disabled: "Role:") , {}, { :class => "widens" } ) %>
See definition:
http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-select

Validation of 2 form fields in a view from one model

i don't get it. How can i validate separately 2 form fields in a view. Today i learned, that the validation in model always validates all objects in a model, instead of the object that is given through the param. Now i try to figure out, how to validate only the object that is given trough the formfield.
html
%td
= form_for opportunity, remote: true do |f|
= f.text_field :boni_score, placeholder: '0.0 - 6.0'
= f.submit "Bonität hinzufügen", class: "block btn btn-sm btn-primary marginTop"
%td
= form_for opportunity, remote: true do |f|
= f.text_field :schufa_score, placeholder: '0-9999'
= f.text_field :schufa_range, placeholder: 'A-P oder Unbekannt', class: 'marginTop'
= f.submit "Speichern", class: "block marginTop btn btn-sm btn-info"
validation
SCHUFA_RANGE =* ('A'..'P')
SCHUFA_RANGE << 'Unbekannt'
validates :schufa_range, inclusion: SCHUFA_RANGE, on: :update, if: :boni_score_blank?
validates :schufa_score, numericality: { only_integer: true }, length: { maximum: 9999, minimum: 0 }, on: :update, if: :boni_score_blank?
validates :boni_score, numericality: { only_integer: false }, length: { maximum: 6, minimum: 0 }, if: :schufa_blank?
def boni_score_blank?
boni_score.blank?
end
def schufa_blank?
schufa_range.blank? || schufa_score.blank?
end
when i press the submit button for the one, then the hole think validates. in fact, i don't get the logic for this. Is it possible to validate each object that is currently in the param?
Ok guys, i have a solution
validates :schufa_range, inclusion: SCHUFA_RANGE, on: :update, if: proc { |opportunity| opportunity.schufa_range_changed? }
validates :schufa_score, numericality: { only_integer: true, greater_than_or_equal_to: 0, less_than_or_equal_to: 9999 }, on: :update, if: proc { |opportunity| opportunity.schufa_score_changed? }
validates :boni_score, presence: true, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 6 }, on: :update, if: proc { |opportunity| opportunity.boni_score_changed? }
The validation happens now when the model.objects changed.

uploadify and paperclip on rails 3.1

i'm trying simply to upload a file using uploadify and paperclip.
This is index view:
<%- session_key = Rails.application.config.session_options[:key] -%>
$('#upload').uploadify({
'uploader' : 'uploadify.swf',
'script' : '/videos',
'cancelImg' : 'images/cancel.png',
'buttonText' : 'Add video!',
'folder' : '/public',
'auto' : true,
'scriptData' : {"<%= key = Rails.application.config.session_options[:key] %>" : "<%= cookies[key] %>",
"<%= request_forgery_protection_token %>" : "<%= form_authenticity_token %>",
},
onError : function (event, id, fileObj, errorObj) {
alert("error: " + errorObj.info);
}
});
This is my model:
class Video < ActiveRecord::Base
has_attached_file :source
validates_attachment_presence :source
end
...and this is my migration file:
class CreateVideos < ActiveRecord::Migration
def self.up
create_table :videos do |t|
t.string :source_content_type
t.string :source_file_name
t.integer :source_file_size
t.timestamps
end
end
def self.down
drop_table :videos
end
end
Now, when i upload a file, there aren't errors raised, neither client side, nor server side, but it looks like paperclip doesn't get the parameters sent him by uploadify. In fact, if i remove validation from model, resource is created without parameters.
In controller i add:
def create
logger.info(params.inspect) (1)
#video = Video.new(params[:video])
#video.save
logger.info #video.inspect (2)
end
In development.log (1) gives me
{"Filename"=>"prova.mov", "authenticity_token"=>"9q5w5LipGoBj Iac055OPbDofFU5FMbpEX675 RqOqs=", "folder"=>"/public", "_StreamVideo_Api_session"=>...
(2) without validation
#<Video id: 1, source_content_type: nil, source_file_name: nil, source_file_size: nil, created_at: "2011-10-10 12:12:38", updated_at: "2011-10-10 12:12:38">
(2) with validation
#<Video id: nil, source_content_type: nil, source_file_name: nil, source_file_size: nil, created_at: nil, updated_at: nil>
Where may be the problem?
Thank you in advance for answers!
In my view i put:
<h1>New video</h1>
<% form_for :video, :html => { :multipart => true } do |f| %>
<%= f.file_field :source%>
<% end %>
But http://localhost:3000/videos/new shows me only the title!!
the code looks ok, you should just add there encodeURI function. In Uploadify 2.1
it should work with:
'scriptData' : {
$('meta[name=csrf-param]').attr('content') : encodeURI(encodeURIComponent($('meta[name=csrf-token]').attr('content')))
}
With Uploadify 3.1:
'formData': {
$('meta[name=csrf-param]').attr('content') : encodeURI($('meta[name=csrf-token]').attr('content'))
}

Resources