I have a form in a partial that renders three times (for the same three fields). However, the placeholder value for each field should ideally be different. Therefore, I'm trying to pass in a local variable that will change for each rendering of the partial.
In the controller, I created an array like this
#placeholder = %w[ firstplaceholder, secondplaceholder, thirdplaceholder]
I then tried to loop through the array while rendering the partial
<%= f.fields_for :answers do |builder| %>
<% #placeholder.each do |k, arrayindex| %>
arrayindex = #placeholder.index(k)
<%= render :partial => 'answer_fields', :locals => { :f => builder, :myplaceholder => #placeholder[arrayindex] } %>
<% end %>
<% end %>
Passing the arrayindex to the #placeholder generates this error
no implicit conversion from nil to integer
So I'm guessing that arrayindex variable is 'nil'. Why?
Inside the partial, in situation where there are error messages and form fields are repopulated, there won't be placeholders (the #placeholder instance variable only gets created in the controller if there's no errors), so I first check if the #placeholder instance variable is present, and try to set the placeholder to the index created in the loop, however, because of the error passing the arrayindex in, it's not working. There may be other problems :)
<% if #placeholder ? myplaceholder = #placeholder[arrayindex] : myplaceholder = "answer choice" %>
<%= f.text_field :content, :class => 'span3', :rows => 1, :placeholder => myplaceholder %>
<%= f.label :correctanswer, "Correct?" %>
<%= f.check_box :correctanswer, :class => 'span1' %>
<% end %>
Update
In the controller, I'm building three answer fields for the question model. The partial therefore is getting rendered three times automatically because of this. If I loop through the #placeholder array wrapped around the partial, it's rendering the partial that many more times 3 * 3.
3.times {#question.answers.build}
First, note that you don't need the comma separators here:
#placeholder = %w[ firstplaceholder secondplaceholder thirdplaceholder]
And you don't need to use the index into the array (if I understand what you're trying to do). So it should be as simple as:
<%= f.fields_for :answers do |builder| %>
<% #placeholder.each do |k| %>
<%= render :partial => 'answer_fields', :locals => { :f => builder, :myplaceholder => k } %>
<% end %>
<% end %>
In the controller, along with the array of placeholder values, I did
#i = 0
The forms_for partial was being rendered 4 times because I created 4 answers.
4.times { #question.answers.build}
Therefore, after each rendering of the partial, I incremented the #i instance variable and passed the incremented value into the #placeholder array #placeholder[#i] and inside the partial used the appropriate element of the array
<%= f.fields_for :kanswers do |builder| %>
<%= render :partial => 'kanswer_fields', :locals => { :f => builder, :k => #placeholder[#i]} %>
<% #i += 1 %>
<% end %>
Related
Is it possible to pass the value of checked check_box_tags within a form_for in Rails inside a hash?
Here is a very generic, basic version of the form:
<%= form_for(:object, :url => { :action => 'create', :id => params[:id]}) do |f| %>
<p>Field_a: <%= f.text_field(:field_a) %></p>
<p>Field_b: <%= f.text_field(:field_b) %></p>
<p>Field_c: <%= f.text_field(:field_c) %></p>
<p>Check boxes:</p>
<% check_box_choices_object_array.each do |s| %>
<%= check_box_tag(s.name, 1, false) %>
<%= .name %><br />
<% end %>
<%= submit_tag("Create") %>
<% end %>
Outputs roughly:
Field_a ___________________
Field_b ___________________
Field_c ___________________
Check boxes:
[] box_a
[] box_b
[] box_c
[] box_d
[] box_e
[] box_f
[] box_g
My problem is that since the available check boxes aren't actual fields in the object's table in the database (i.e. I'm not using check_box(:field) in the form), each checked check box gets passed as an individual parameter (i.e. "box_a" => "1", "box_b" => "1", "box_e" => "1"). I would like them to be passed as such:
:checked_boxes => {"box_a" => "1", "box_b" => "1", "box_e" => "1"}
This way, I can access them easily with params[:checked_boxes].
How do I do this, or, better yet, is there a better solution (I'm new to rails)?
I think you'd get the results you want if you wrap the checkboxes iterator in a fields_for :checked_boxes tag - or at least get you close to the results you want.
<%= form_for(:object, :url => { :action => 'create', :id => params[:id]}) do |f| %>
<p>Field_a: <%= f.text_field(:field_a) %></p>
<p>Field_b: <%= f.text_field(:field_b) %></p>
<p>Field_c: <%= f.text_field(:field_c) %></p>
<p>Check boxes:</p>
<%= f.fields_for :checked_boxes do |cb| %>
<% check_box_choices_object_array.each do |s| %>
<%= cb.check_box(s.name, 1, false) %>
<%= .name %><br />
<% end %>
<% end %>
<%= submit_tag("Create") %>
<% end %>
you can deal with no database attributes and models using attr_accessor
class Thing < ActiveRecord::Base
attr_accessible :name
attr_accessor :box_a, :box_b, :box_c
end
This way you can call these attributes in your form.
++ edited to change the question to call partial recursively ++
I am writing this question after a lot of days of frustration about this simple piece of code which isn't working. I have read numerous issues with passing partials on stackoverflow and tried all the solutions I could but it doesn't work.
Calling the partial works for the first loop but from second onwards it bombs with an error
"undefined local variable or method `count' for #<#:0x2f12670>"
Notice here that the error contains a class within a class, so something fishy is happening when the partial is being called recursively.
I have a partial called _form.html.erb which calls another partial _rule_action_fields.html.erb. I need to pass a variable from the form partial to the rule_action_field partial and here is the code:
_form.html.erb: (Please note that the builder object here is being passed from code I have not pasted)
<% #folder_count = 1 %>
<% #rule.rule_actions.each do |ruleaction| %>
<%= f.fields_for :rule_actions, ruleaction do |builder| %>
<%= render( :partial => 'rule_action_fields', :locals => { :f => builder, :count => #folder_count } ) %>
<% end %>
<% #folder_count = #folder_count + 1 %>
<% end %>
_rule_action_fields.html.erb
<p id="folder_fields">
<%= count %>
<label class="form_label">Move the files to </label>
<%= f.select(:folder_id, current_user.folders.collect { |p| [p.name,p.id] }, {:include_blank => true } ) %>
</p>
Unfortunately I cant call this partial with a collection of rule_actions because of some logic which is partially in the calling code and partially in the rule_action_fields partial.
Other syntax I have tried:
<%= render :partial => 'rule_action_fields',:f => builder, :locals => { :count => folder_count } %>
<%= render :partial => 'rule_action_fields', locals => { :count => folder_count } %>
<%= render 'rule_action_fields', :count => folder_count %>
Any ideas?
I've got a Rails app that has two main views: an overview and a sequenced view. The user can enter data in either view. I use the same form helper for both views, but I want the redirect_to from the create action to respect the user's context. So I pass a hidden_field_tag called 'track'.
I can't seem to access the value of 'track' inside my controller.
Here's the form:
<%= form_for([#mission, #mission.stickies.build]) do |f| %>
<div class="field">
<%= f.text_field :name, :size => 60 %>
<%= f.hidden_field :kind, :value => kind %>
<%= hidden_field_tag :track, :value => track %>
<class="actions">
<br><%= f.submit "Add to " + kind.pluralize.capitalize %>
</div>
<% end %>
And here's where I call it in one of the views:
<%= render :partial => "stickies/form" , :locals => { :kind => "driver", :track => 'main' } %>
Here's the parameters dump (from a different call):
{"utf8"=>"✓",
"authenticity_token"=>"N3IXwNQosOfxw1ZcpfFPOLPKzHbvNyaBhAiP3ftT9GY=",
"sticky"=>{"name"=>"Tesssksjd argghh.",
"kind"=>"success"},
"track"=>"{:value=>\"sequence\"}",
"commit"=>"Add to Successes",
"mission_id"=>"32"}
And here's the relevant code in my create controller:
if params[:track][:value] == "main" then
redirect_to mission_path(#mission) + '#' + #sticky.kind.pluralize
elsif params[:track][:value] == "sequence" then
redirect_to mission_stickies_path(#mission, :kind => #sticky.kind)
end
I can't seem to find the syntax, or comparator, or whatever I need to access the value represented by "track"=>"{:value=>\"sequence\"}".
Any help or pointers would be greatly appreciated. I'm new to Rails and Ruby, this is my first app.
Don't write it with the :value => track, rather do:
<%= hidden_field_tag :track, track %>
and access it with params[:track]
I've got a problem to get my partial working.
I want to pass an object via a local variable to a partial, but I get a
undefined method `model_name' for NilClass:Class
error all the time. But the variable is passed over because I can call it in the partial with .to_yaml, which gives me all the variables properties.
But when I try to use it in a form_for I get that error.
Maybe it has something to do with my db query. Because when i try to call it with another local variable there is no error. But my query should produce a single object, or am I wrong with that?
Here is my show.html.erb:
<%= #partneroffer = Partneroffer.where(:partner_id => #partner.id, :yearname_id => year.id).first %>
<%= render :partial => "form2", :locals => { :partneroffer => #partneroffer } %>
And here is my partial (_form2.html.erb):
<%= form_for partneroffer , :html => { :class => 'form-horizontal' } do |f| %>
<%= f.label :partnerstatus_id, :class => 'control-label' %>
<%= f.collection_select(:partnerstatus_id, Partnerstatus.all, :id, :name) %>
<%= f.submit nil, :class => 'btn btn-primary' %>
<%= link_to t('.cancel', :default => t("helpers.links.cancel")),
partner_year_terms_path, :class => 'btn' %>
<% end %>
It could be that in your partial, partneroffer is a nil object, so it doesn't have the method "model_name".
You are rendering the view the right way, and you are passing the locals the right way, however, are you sure that Partneroffer.where(:partner_id => #partner.id, :yearname_id => year.id).first is not getting a nil value? Try this code in show.html.erb:
<%- #partneroffer = Partneroffer.where(:partner_id => #partner.id, :yearname_id => year.id).first %>
<%- if #partneroffer %>
<%= render :partial => "form2", :locals => { :partneroffer => #partneroffer } %>
<%- else %>
#partneroffer is nil!!!!
<%- end %>
I've found the solution based on one of the related topics (Render :partial a random object from DB by id, in custom form)! The problem was that I have to call the partial four times. But in only one case there was a record in my query results. Each time there wasn't a record rails threw this error message. I knew there was at least a result in one of the partial calls but wasn't aware that there has to be one in each result. Thx to weexpectedthis!
Okay so I am quite new to Rails and am trying to do the following without success:
I have an Object (from my Active Record) containing a project, which contains n sub-projects, which contain n tasks. Now for each of these I want a partial view.
So I render from the project view the sub-project with the following code:
<%= render(:partial => 'subproject', :collection => #project.sub_projects) %>
Within my sub-project partial view called _subproject.rhtml (adding the code to a good ol Rails 1.2.3 project), so I can access the data like this:
<%= subproject.name %>
That will print out the name alright but when I try to generate a textfield this won't work:
<%= text_field 'subproject', 'name' %>
But this will:
<%= text_field 'subproject', 'name', :value => subproject.name %>
What am I doing wrong?
Edit: Changed title due to my problem is not passing the value but displaying it within a form field.
Edit2: As requested my controller code:
#project = Project.find(params[:id])
You can write this:
<%= render(:partial => 'subproject', :collection => #project.sub_projects) %>
as
<%= render :partial => #project.sub_projects %>
This will render every sub project with the sub_projects/_sub_project.html.erb partial. A little shortcut.
This:
<%= text_field 'subproject', 'name' %>
Says create a text_field called: subproject[name], but doesn't give it a value. You need to pass the value you want to set (the code that works).
The more idiomatic way of doing this now is with form_for:
<% form_for #subproject do |f| %>
<%= f.text_field :name %>
<% end %>
Or if you're using formtastic (https://github.com/justinfrench/formtastic), which is fantastic, you'd write:
<% semantic_form_for #subproject do |f| %>
<%= f.input :name %>
<% end %>
I hope this helps!