In my Rails 5 app I have a Simple Form form for creating or updating for my model Training
. In this form I already have checkboxes for each of my Participant
s to assign them to the Training
. Now I'm trying to add a radio button group (5 for a rating from 1 to 5) for each Participant
, because each can rate the Training
.
Screen shot of the rendered form
I managed to render the radio buttons as I wanted but unfortunately I can only select one of all the radio buttons rendered. They are even strangely connected to the checkboxes, which will probably be because they have the same input method participant_ids
, which is connected to the has_and_belongs_to_many
association with Participant
:participants
.
<%= simple_form_for @training do |f| %>
...
<div id="participants-ratings-container">
<div id="participants-container" style="display: inline-block; vertical-align: top; width: 8em">
<%= f.label t('activerecord.models.participant') %>
<%= f.collection_check_boxes :participant_ids, Participant.all.order(:name), :id, :name, {:item_wrapper_class => 'checkbox-container'} %>
</div>
<div id="ratings-container" style="display: inline-block; vertical-align: top">
<%= f.label t('trainings._form.ratings') %>
<% Participant.all.order(:name).each do |p| %>
<%= f.input :participant_ids, collection: 1..5, as: :radio_buttons, label: false%>
<% end %>
</div>
...
<% end %>
I tried a lot of things but I have no ideas anymore. If it is possible I would like to fill a Hash participant_ratings
in my Training
class in the way "participant.name" => rating value.
Can anyone give me a hint on how to achieve this? Maybe even tell me how to disable the radio button group if the corresponding Participant
is not checked?
Thanks in advance!
UPDATE
I managed to adapt my form and even integrate jQuery raty plugin to enter the rating value for each Participant
. Each rating is sent with it's corresponding participant-id to the server as a hash, eg like so:
"participant_ratings"=>{"3"=>"5", "1"=>"3.5", "2"=>""}.
Every rating is disabled and it's value set to 0 if the corresponding participant checkbox isn't checked. Here is my view code:
<div id="ratings-container" style="display: inline-block; vertical-align: top">
<%= f.label t('trainings._form.ratings') %>
<% Participant.all.order(:name).each do |p| %>
<span class="checkbox_container">
<% current_rating = @training.participant_ratings[p.id].nil? ? '' : @training.participant_ratings[p.id] %>
<label id='star<%= "#{p.id}" %>' data-rating='<%= "#{current_rating}" %>' style="margin-bottom: 12px;" ></label>
<input id="rating<%= "#{p.id}" %>" name="participant_ratings[<%= "#{p.id}" %>]" type="hidden" value="<%= "#{@training.participant_ratings[p.id]}" %>" />
</span>
<script>
$('#star<%= "#{p.id}" %>').raty({
score: function() {
return $(this).attr('data-rating');
},
half : true,
readOnly: <%= !@training.participants.include?(p) %>,
path: '/assets',
click : function(score, evt) {
$('#rating<%= "#{p.id}" %>').val(score);
}
});
$('#training_participant_ids_<%= "#{p.id}" %>').change(function () {
var star = $('#star<%= "#{p.id}" %>');
if(document.getElementById('training_participant_ids_<%= "#{p.id}" %>').checked) {
star.raty('readOnly', false);
} else {
star.raty('cancel');
star.raty('readOnly', true);
$('#rating<%= "#{p.id}" %>').val("");
}
})
</script>
<% end %>
</div>
New screen shot of the rendered form
The last thing I don't seem to be able to figure out is how to save the participant_ratings hash in the corresponding model attribute :participant_ratings
If I allowed the param :participant_ratings
in my trainings_controller.rb
but nothing was saved. So I added
@training.participant_ratings = params[:participant_ratings]
and now I get the error
Attribute was supposed to be a Hash, but was a ActionController::Parameters. -- <ActionController::Parameters {"3"=>"5", "1"=>"3.5", "2"=>""} permitted: false>
The methods in my trainings_controller.rb
:
class TrainingsController < BaseController
...
def update
@training = Training.find(params[:id])
@training.updated_date_time = DateTime.now
@training.participant_ratings = params[:participant_ratings]
if @training.update(training_params)
flash[:notice] = t('flash.training.updated')
redirect_to @training
else
render 'edit'
end
end
private
def training_params
params.require(:training).permit(:village, :topic, :user_id, :start_time, :end_time, {:participant_ids => []}, :participant_ratings)
end
end
How do I save the hash sent by the form in the model's attribute? Where am I going wrong?
Can I somehow define participant_ratings
as a hash in the params similar to the array participant_ids
there?
Firstly, I had to make sure that the participants_rating-hash was inside the training-hash when submitted by my form, so I had to change the name attribute in my hidden form input for the rating:
<input id="rating<%= "#{p.id}" %>" name="training[participant_ratings][<%= "#{p.id}" %>]" type="hidden" value="<%= "#{@training.participant_ratings[p.id]}" %>" />
Secondly, I had to whitelist the keys for my participant_ratings-hash so that they are permitted:
def training_params
ratings_keys = params[:training].try(:fetch, :participant_ratings, {}).keys
params.require(:training).permit(:village, :topic, :user_id, :start_time, :end_time, {:participant_ids => []}, participant_ratings: ratings_keys )
end
I found this solution in this rails thread
After that participant_ratings was saved just fine!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.