Modify text displayed in simple_form input when using enum - ruby-on-rails

I'm using simple_form for managing my users. For selecting the user role I use input as: :radio_button.
The collection come from a enum on the user model. How can I modify the text to show something specific like "Super Admin" instead of super_admin?
_form.html.slim
= form.input :role, collection: User.roles, as: :radio_buttons, item_wrapper_class: 'btn btn-default', checked: User.roles[user.role], required: true
user.rb
enum role: [:super_admin, :admin, :generic]

you can use the label_method option with the collection
= form.input :role, collection: User.roles, label_method: lambda {|k| k.humanize}, as: :radio_buttons, item_wrapper_class: 'btn btn-default', checked: User.roles[user.role], required: true

If you want to do something more complex than calling a method on the key, Simple Form has support for translating collection options with I18n - you just have to provide the collection as an array of symbols for the lookup to work.
Here's what worked for me on SimpleForm 3.5.0:
Locale file:
en:
simple_form:
options:
user:
role:
super_admin: 'Super Admin'
admin: 'Admin'
generic: 'Regular Joe'
View:
<%= f.input :role, collection: User.roles.symbolize_keys.keys %>

Related

Translating form_for syntax to simple_form syntax

I have this code within my rails form:
Categories: <%= f.collection_select :tag_ids, Tag.order(:name), :id, :name, {}, {multiple: true} %>
This code is working, but I want to use simpleform gem to redesign my form. However, I cannot seem to figure how to 'translate' this code into simple form. Anyone have any idea how? Thanks.
Something like this should do the trick:
If you have a many to many relation you could first try what the default does.
<%= f.association :tags %>
If the defaults don't work out you can make an explicit collection:
<%= f.input :tag_ids, as: :select, collection: Tag.order(:name), label_method: :name, input_html: {multiple: true} %>
# or
<%= f.input :tag_ids, as: :select, collection: Tag.order(:name).pluck(:name, :id), input_html: {multiple: true} %>
Alternatively if you define the Tag#to_label method you don't have to pass the name of the label method. The Tag#id gets used as default value method. If you would like another value specify the method like so: value_method: :something_else.
See the simple_form Usage section (intro, collections and associations).

Hover over display related text for simple form association field

I am using Rails and simple form. I have a collection that I am displaying with an association field. For each item in the collection, I want to display a hover over title of an attribute belonging to that item, namely description.
Here is my association:
<%= f.association :user_roles, collection: #roles, as: :check_boxes, label_method: :name, label: false %>
I want to display a hover over text of the description of each role. In my head something like the following should be doable:
<%= f.association :user_roles, collection: #roles, wrapper_html: {title: UserRole.where(id: this_current_items_id).first.description}, as: :check_boxes, label_method: :name, label: false %>
or:
<%= f.association :user_roles, collection: #roles, wrapper_html: {title: :description}, as: :check_boxes, label_method: :name, label: false %>
Neither of these work obviously but in my head a solution like this should be easy. I guess the guys at simple form never thought of this situation.
However, is this possible to do? Or, how can I get the ID of the current item so that I am displaying that items description on hover over?
PS: What I need is a simple form hover_method!
You can easily add other attributes to each item in your collection like so:
<%= f.association :user_roles, collection: #roles.map { |r| [r.name, r.id, { title: r.description, "data-toggle": "hover" }] }, as: :check_boxes, label: false %>

Placeholder in rails simpleform association

How to put placeholder in rails simpleform association. I have tried a different ways but nothing works for me. The target code is:
<%= f.association :sex, :include_blank => true %>
If you are using Select2, you can include placeholders in select elements. The requirement is to include a blank element as first item and you can include the placeholder text as a data HTML attribute.
In your case:
<%= f.association :sex, include_blank: true,
data: { placeholder: 'Search...'} %>
Please check the simple_form.rb in initializers
You can find something below
# Use this setup block to configure all options available in SimpleForm.
SimpleForm.setup do |config|
.
.
.
config.wrappers :default, :class => :input, :hint_class => :field_with_hint, :error_class => :field_with_errors do |b|
## Extensions enabled by default
# Calculates placeholders automatically from I18n
# You can also pass a string as f.input :placeholder => "Placeholder"
b.use :placeholder
.
.
end
end
so it is depends on translational file
So you need to do for user model sex attribute
en:
simple_form:
placeholders:
user:
sex:
As placeholder works for input
Then you try this
<% f.association :user do |u| %>
<%= u.input :sex %>
<% end %>
And It should work
Using Rails 5.0.0.beta2 and Simple Form 3.2.1, this works for me:
<%= f.association :strands,
collection: Strand.order(label: :asc),
include_blank: "-- Select strands --"
%>
I had no luck using various permutations on :prompt and some of the other ideas that I found suggested here.
<%= f.association :sex, :include_blank => true, placeholder: "sex" %>

ActiveAdmin add filter to form

I have some properties on an active admin model, which can have a LOT of different values, so right now I'm displaying them using checkboxes:
PropertyType.find_each do |pt|
f.input :property_values
f.input :property_values, label: pt.display_name, as: :check_boxes, collection: pt.property_values.order(name: :asc, display_name: :asc).load , multiple: true
end
What I would like to do is to add an input field, in which while i'm writing, it filters the whole checkboxes list, only displaying the ones that matches the input field.
Is there a way to do that?
Thanks.
Yes. Check out chosen_rails gem.
In active_admin it will look something like this:
f.input :property_values,
label: pt.display_name,
as: :check_boxes,
collection: pt.property_values.order(name: :asc, display_name: :asc).load,
input_html: { class: 'chosen-select' },
multiple: true
The only thing I haven't tried it with check_boxes, but with as: :select, and it works perfectly. I think select would be doing the same for you, since you have multiple: true

undefined method `name' for ["Yes", true]:Array

I acctual don't know where Array ["Yes",true] came from. I have two models like this:
GeneralExam has_many topic_questions
TopicQuestion belongs to general_exam, belongs_to topic
In TopicQuestion, I have columns: general_exam_id, topic_id, number_question, to store a number question for each topic in general exam.
I built a nested form for create new general exam, on form I built a dynamic select, when user choose a course from a dropdown list, I have other dropdown lists to display topics of course chosen by user.
This is my javascript code for dynamic select:
<% content_for :head do %>
<script type="text/javascript">
$(document).ready(function() {
$('#general_exam_course_id').change(function () {
$.ajax({
type: "POST",
url: "<%= update_topics_general_exams_path %>",
data: { course_id: $('#general_exam_course_id').val() },
dataType: "script"
});
});
</script>
<% end %>
#general_exam_course_id is ID of dropdown list for select course. update_topics_general_exams_path is route to my update action in general exam controller, this is my update action:
def update_topics
#course = Course.find(params[:course_id])
#topics = #course.topics
end
I have a update_topics.js.erb also:
$('div#topic_questions select').html("<%= j options_from_collection_for_select(#topics, 'id', 'name') %>");
Dropdown lists in div#topic_questions will get #topics value from update_topics action (I think so) and display it. When I create new general exam, it's ok. But when I press Edit link, it show me an error which I don't know why and where it comes:
NoMethodError in General_exams#edit
undefined method `name' for ["Yes", true]:Array
Extracted source (around line #3):
1: <div class="row">
2: <div class="span6"><%= remove_child_link "Remove below topic", f %></div><br><br>
3: <div class="span3"><%= f.association :topic, collection: #topics, label_method: :name, value_method: :id, prompt: "Choose a topic", label: false %></div>
4: <%= f.input :number_question, placeholder: 'Number of questions', label: false, style: 'display: inline' %>
5: </div>
My edit action only have: #general_exam = GeneralExam.find(params[:id]). I don't know why topic association field of general exam display an Array ["Yes", true]. I don't have it, don't define it any where, why it come when I edit general exam?
Update
If I remove label_method: :name, value_method: :id in:
<%= f.association :topic, collection: #topics, label_method: :name, value_method: :id, prompt: "Choose a topic", label: false %>
The page is not error, but Dropdown lists have value Yes, No in select, not the name of topic I have created for exam. Form can get the number question of each topic, but it can not get name of topic.
When I create:
When I edit:
I found this in config/locales/simple_form.en.yml:
en:
simple_form:
"yes": 'Yes'
"no": 'No'
Is this a problem?
Update: Don't pass #topics in new action but it's still have on new page When course even is not selected yet
My new action:
def new
#general_exam = GeneralExam.new
5.times { #general_exam.topic_questions.build }
##topics = Topic.all
end
As in my extract source above, I have below code in new, edit too (use same form):
<%= f.association :topic, collection: #topics, label_method: :name, value_method: :id, prompt: "Choose a topic", label: false %>
So I don't pass #topics, but when I go to new page, dropdown lists for topic still display Yes, No value.
Ok , our time for comments chat-like is over :)(the System suggested to move to the chat room ) . The solution it seems to be passing the collection inline in the association of the simple_form :
<%= f.association :topic, collection: #topics, label_method: :name, value_method: :id, prompt: "Choose a topic", label: false %>
becomes :
<%= f.association :topic, collection: Topic.limit(1), prompt: "Choose a topic", label: false %>
It would work for now , I think .
You've got the right idea by assigning your query to #topics and passing it to your view... but, you're putting it in the wrong actions and not passing them to the right views:
def update_topics
#course = Course.find(params[:course_id])
#topics = #course.topics
end
-
What you should do:
There is NO update view for your update action, so, you must place the following 2 lines:
#course = Course.find(params[:course_id])
#topics = #course.topics
in both your new action and your edit action
Then you can go ahead and use your original simple_form code, which IS/WAS ORIGINALLY correct:
<%= f.association :topic, collection: #topics,
label_method: :name, value_method: :id,
prompt: "Choose a topic", label: false
%>
Alternatively, you could SKIP the #topics in your controllers and simply put the following in your views:
new view
<%= f.association :topic, collection: Topics.all,
label_method: :name, value_method: :id,
prompt: "Choose a topic", label: false
%>
edit view
<%= f.association :topic, collection: Course.find(params[:course_id]).topics,
label_method: :name, value_method: :id,
prompt: "Choose a topic", label: false
%>
NOTE the difference:
I would think that in your new view you would want the user to see ALL possible topics.
While in your edit view you just want them to see the topics for this course, correct?
-
Why it happened:
Since, you were not passing ANY collection earlier, there was no 'name' method/column for simple_form to use as the labels/display values in the dropdown and thus the error message you got regarding Array ["Yes",true]
If/when you removed the label_method: :name, value_method: :id, options you probably would have seen as many choices as you had expected rows in the dropdown, but instead of a list of the course topic names you would have seen a list of Topic objects (something like this):
#<Topic::xxxx>
#<Topic::xxxx>
...
#<Topic::xxxx>
And, when you don't supply the collection, you get only 2 yes/no values which is the simple_form default per the config file you found (config/locales/simple_form.en.yml).
So, as you might have guessed by now, this is why what you finally used...
<%= f.association :topic, collection:
Topic.limit(1),
prompt: "Choose a topic",
label: false
%>
...kind of "worked" as a workaround -- because it *did* execute a proper query and supplied it to the simple_form, but it limited the results to only the *first* topic in the table (without any ordering/sort)
At least, this is what I have learned/gone through. HTH!

Resources