I am having trouble displaying selected radio buttons in the edit action.
The app allows the user to create his own forms(surveys) and then apply them (answer them) to their children.
The issue:
When rendering the new action that allows the user to answer his form, forms display well, and save to database properly. Assigns the choices to the answer content.
On the other hand, edit action duplicates the choices, showing the ones that were selected AND new ones. I check the id of the answers and is rendering 2 times each answer.
Any ideas of how to fix this behaviour?
Relevant code:
_form.html.erb
<%= f.fields_for :answers do |a| %>
<% choices.each do |choice| %>
<%= a.radio_button :a_content, choice.c_description %>
<%= a.label :a_content, choice.c_description, :value => choice.c_description, class: 'no-margin' %>
<% end %>
<%= a.hidden_field :question_id, :value => question.id %>
<% end %>
answered_forms_controller.rb
def new
#child = current_user.children.find(params[:child_id])
#form = current_user.forms.find(params[:form_id])
#answered_form = #child.answered_forms.new(form_id: params[:form_id])
#answered_form.answers.build
end
def create
#answered_form = AnsweredForm.create(answered_form_params)
if #answered_form.save
flash[:success] = "Nuevo cuestionario " + #answered_form.form.f_title + " aplicado!"
redirect_to current_user.children.find(params[:child_id])
else
render 'new'
end
end
def edit
#child = current_user.children.find(params[:child_id])
#form = current_user.forms.find(params[:form_id])
end
def update
if #answered_form.update_attributes(answered_form_params)
flash[:success] = "Cuestionario para paciente actualizado!"
redirect_to #answered_form.child
else
render 'edit'
end
end
UPDATE:
I now figured out that the duplication occurs because in the new action I got #answered_form.answers.build, but if I remove that, I don't see the fields when creating a new answered_form.
I knew this because tried to put 2 times #answered_form.answers.build in the new action and then got duplicated when creating and triplicated when editing, so edit always adds the fields one more time than new action if you have something like #answered_form.answers.build in the new action.
I believe you should be able to do something like:
<%= f.collection_radio_buttons :a_content, choice, :id, :c_description, {}, { checked: choices.selected_response_id } %>
With this you should be able to generate your radio buttons for all your answers.
PS: the final hash has the condition for checking the selected option choices.selected_response_id you should change that to the selected response on your answer model.
Although Rails tries to infer the preselected radio button, it may not always work hence the reason for this final hash.
Read more here
If you want to preselect your radio button, it means you have already stored a boolean value in your database for this field. Just insert this value after the checked option inside your helper:
radio_button_tag("something", something, checked = value)
should work the same with f.radio_button
Related
I have a simple form for creating tasks which is customized with #new_task to always create tasks. A separate form is used to update them.
#Form
<%= form_for([#project, #new_task]) do |f| %>
<%= f.text_field :title, placeholder: 'Add a Task' %>
<%= f.submit %>
<% end %>
#TasksController
def show
#projects = Project.all
#project = Project.find(params[:project_id])
#task = Task.find(params[:id])
#new_task = Task.new(title: #task.title)
#tasks = #project.tasks.all
end
The problem is when I'm on tasks/show (which calls the task ID) the form assumes it's an update and populates the text field with the task name.
I need to clear the text field so that only the "Add a Task" placeholder is visible. I've tried a number of different ways with no luck and am hoping somebody here can help.
All Rails forms behave like this - they pre-populate the fields with the values stored in your variable. If you've just done #new_task = Task.new, then all the values are nil, so all the fields are empty.
If, as in your case, you've done #new_task = Task.new(:title => #task.title), then the title attribute has a value (of #task.title), so that will be displayed in the form.
If you don't want anything to be displayed, just don't pre-set values.
I've a settings controller setup like this:
class Admin::SettingsController < ApplicationController
def index
#settings = Setting.all
end
def update
setting_params.each do |key, value|
Setting.where(key: key).first.update_attribute :value, value
end
redirect_to admin_settings_path, notice: "Settings saved."
end
private
def setting_params
params.require(:settings).permit(:site_title, :site_desc)
end
end
The index action has a view file in relevant path, its code is as follows:
<h1>Settings</h1>
<%= form_tag admin_settings_path, method: "put" do %>
<p>
<label>Site Title:</label>
<%= text_field_tag "settings[site_title]" %>
</p>
<p>
<label>Site Description:</label>
<%= text_field_tag "settings[site_desc]" %>
</p>
<p>
<%= submit_tag "Save settings" %>
</p>
<% end %>
Now, I'm able to save/update these fields data in relevant model and I can see the data through command Setting.all in rails console. But the issue is, after saving the record via form when I reload the settings index page the form is blank and it is not showing previously saved values in the fields.
What I'm doing wrong here?
You can do what has been mentioned in the previous answer i.e. using a form_for. However, this can also be accomplished by creating a Hash in both the controller actions that creates and processes this form.
In the action that creates this form, the values in the hash could be initialized to blanks/zeros depending upon the input tag and in the action that processes this form, the values in the hash could be assigned to the values obtained from the posted params[].
I ran into the similar issue with form_tag and I used the following code in my index action i.e. the action that renders the form initially:
#search = {name: "", ranking_group: 0}
Whereas, in the search action, I used the following code to fill up this hash:
#search = {name: params[:name], ranking_group: params[:ranking_group]}
Finally, in the view, I used the appropriate default value options with the input tags as below:
<%= text_field_tag :name, #search[:name] %>
<%= select_tag :ranking_group, options_for_select(AmenityEntities::Amenity.ranking_group_options, #search[:ranking_group]), include_blank: true %>
Hope this helps.
I think you need to use form_for(#variable) instead of just a form_tag because you need to persiste the object after save.
form_for works with resources, take a look here: http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html
I'm working on a dynamic form in a Rails app, and I need to insert a variable number of records into a model in a single form submission. I've done this using PHP -> MySQL/Postgres before, but I have no idea how to do it in Rails.
Ultimately, users should be able to create any number of records to be inserted, but in my example below, I'm limiting it to 2... let me see if I can do that, first...
Here's the form - the ids all get a unique suffix because they are being populated dynamically from localStorage objects on submission.
new.html.erb
<%= form_for #entry, html: {id: :new_entry_form} do |f| %>
<% for i in 0..1 %>
<%= f.text_field :name, :id => 'name_#{i}' %>
<%= f.text_field :day, :id => 'day_#{i}' %>
<% end %>
<% end %>
Here's the associated controller - I'm sure that this is missing something, but I don't know what.
def new
#entry = Entry.new
end
def create
#entry = Entry.create(entry_params)
redirect_to "http://localhost:3000/entries"
end
private
def entry_params
params.require(:entry).permit(:name, :day)
end
Any help would be much appreciated.
Follow this link it shows how to create multiple object in one form submit:
http://vicfriedman.github.io/blog/2015/07/18/create-multiple-objects-from-single-form-in-rails/
The functionality I want to achieve with this is to have different fields based on the action the user is currently on.
The generic scaffold bundles the form into a partial and renders it in the new and edit actions. In a typical signup case, one may not want to update the password everytime the profile is updated. One way I used to solve this in the past is to create separate forms for new and edit; including the password in new only. Obviously, most fields repeat themselves. Is there a way to keep the partial but omit (thereby not updating) some fields on the form per action?
Let me assume you are building the form for user model.So in controller you will have
def new
#user = User.new
.....
end
def edit
#user = User.find(params[:id])
....
end
In the form partial use
<% if #user.new_record? %>
<%= f.field_type :field_name %>
<% end %>
This will not render the field during edit/update.
You can try it this way in one partial:
<% if params[:action] == "new" %>
<%= f.field_type :field_name %>
<% end %>
But you should think about the security because this doesnt keep away attackers from adding POST fields manually to write to fields that aret displayed as Fields on you form!
You can check whether the active record object being passed to the view (such as #user) is a new record or and old one using the method 'new_record?'. Based on this, you can decide what fields you want to display.
Alternatively, you could also have a partial and then pass it some value (most likely a Boolean) and based on that value you can decide which fields to render.
This can been done like:
render :partial => 'partial_name', :locals => {:bool => true}
And then in your partial do
<% if bool == true %>
<%= f.xyz_tag :name %> //whatever field you want
<% end %>
I have a very common situation and a solution, but I would like to ask the Rails experts out there if it can be improved.
I have a very typical RESTful controller where the user supplies some of the object attributes upon creation. There is a thing model, a ThingsController and various views, including new, create, and a _form partial.
A thing has two attributes,
a color, which is set when they hit a link to create it (i.e. a “Create Red Thing” link that encodes the ID of red as a URL parameter)
a description, which is entered by the user in the form view
I’m happy with the approach for dealing with an attribute like the description that that a user specifies in the form, but less confident about the way that I handle an attribute that is passed through via the URL parameters associated with the first click.
This is what I am doing right now (note that I have omitted error checking to simplify matters). First, my new and create methods in the controller are as follows:
def new
#thing = Thing.new
#thing.color = Color. find(params[:color])
end
def create
#thing = Thing.new(params[:thing])
#thing.color = Color. find(params[:color])
if #thing.save
flash[:notice] = "Successfully created thing."
redirect_to somewhere_url
else
render :action => 'new'
end
end
The new view just invokes the _form partial, which looks as follows:
<% form_for #thing do |f| %>
<%= f.error_messages %>
<%= hidden_field_tag "color", #thing.color.id %>
<%= f.label :description %>
<%= f.text_area :description %>
<%= f.submit "Submit" %>
<% end %>
It seems a little messy to be passing the color ID through to the create method as a URL parameter by putting a hidden field in the form. Does this look reasonable, or is there another approach that would be better?
Normally in this situation, I would put a hidden field in the form, which will hold the color_id. The nice thing about this way is that you can get by with just setting the color of the object before you render the form. So your controller changes to:
def new
#thing = Thing.new
#thing.color = Color. find(params[:color])
end
def create
#thing = Thing.new(params[:thing])
if #thing.save
flash[:notice] = "Successfully created thing."
redirect_to somewhere_url
else
render :action => 'new'
end
end
and your form will change to
<% form_for #thing do |f| %>
<%= f.error_messages %>
<%= f.hidden_field :color_id %>
<%= f.label :description %>
<%= f.text_area :description %>
<%= f.submit "Submit" %>
<% end %>
The color is then passed through both forms, and you only need to retrieve the color in the first form. (Don't forget to add validations your Thing model to make sure it has a valid color though).