I'm making a project for which I have a class online_score which has as one of its attributes an array called url of online_score_url objects. What I did up to now is the following.
views/online_score/new:
<div class="urlInput">
<% f.fields_for :url do |b| %>
<%= render "online_score_url_fields", :f => b %>
<% end %>
<%= add_url_link "Add Another link", f %>
</div>
views/online_score/_online_score_url_fields:
<div class="inputset">
<%= f.label :url %> <%= f.url_field :url, :value => "http://www.google.be"%>
<%= f.label :description %> <%= f.text_field :description %>
<%= link_to_remove_fields "remove", f %>
</div>
My problem is now that I want to be able to dynamically add inputs for online_score_urlobjects which I try to do with JQuery. I try to do this by rendering the partial like so:
helpers/online_scores_helper.rb:
def add_url_link(name, form)
link_to_function name do |page|
online_score_url = render(:partial => 'online_score_url_fields', :f => form )
page << %{
$('.links').append("#{ escape_javascript online_score_url }");
}
end
end
The problem is then that fseems to be undefined in the partial. I expect this has something to do with the line <% f.fields_for :url do |b| %> in my view which doesn't get executed via the dynamic adding. But I don't really know how to fix. I think I need an alternative for the form_formethod? How to do that?
I guess my main question is: how do I iterate over an array in a controlled way, and for every element create a set of input forms like in the partial AND be able to 'add' one or more dynamically?
Thanks for your time.
Try this one:
<%= render "online_score_url_fields", :locals => {:f => b} %>
this is beacuse :f is not a parameter for the render method. So you need to use :object, :collection or something locals with the syntax above.
The same here:
online_score_url = render(:partial => 'online_score_url_fields', :locals => {:f => form} )
Related
Suppose I have a form like below
<%= form_for #uni, :html => {:multipart => true, :honeypot => true} do |uni_form| %>
<% 3.times { #uni.app.build } %>
<%= uni_form.fields_for :apps do |builder| %>
<%= render 'app', uni_form: builder %>
<% end %>
<% end %>
and my app partial is
<div>
<%= uni_form.label :uni_id, "University" %>
<%= uni_form.collection_select :uni_id, #unis, :id, :name, {:include_blank => true} %>
</div>
Now I want the first form code without the loop. Something like this
<%= form_for #uni, :html => {:multipart => true, :honeypot => true} do |uni_form| %>
<% 3.times { #uni.app.build } %>
<%= render 'app', uni_form: builder %>
<%= render 'app', uni_form: builder %>
<%= render 'app', uni_form: builder %>
<% end %>
How can I do this?
Firstly, don't build your associated objects in your view - do it in your controller:
#app/controllers/unis_controller.rb
class UnisConstroller < ApplicationController
def new
#uni = Uni.new
3.times do
#uni.apps.build
end
end
end
Secondly, the fields_for method is your friend here.
You'll gain what you need by using the following:
#app/views/unis/new.html.erb
<%= form_for #uni, :html => {:multipart => true, :honeypot => true} do |uni_form| %>
<%= uni_form.fields_for :apps do |builder| %>
<%= builder.label :uni_id, "University" %>
<%= builder.collection_select :uni_id, #unis, :id, :name, {:include_blank => true} %>
<% end %>
<% end %>
fields_for takes your model's associated objects and automatically creates the fields you need. There is literally no need to "loop" - fields_for does it for you... if you set it up correctly.
The problem you have is you're building your associated objects at runtime, which is not only inefficient & against convention, but I think it will prevent the form_for from recognizing them (which is what allows fields_for to loop through them).
The above code should fix this for you.
I am creating list of forms say
Questions form
Answers form
Hints form
All these have different controller and view, question_controller , answers_controller, hints_controller.
Now I need to fetch all these views in tabbed UI in home page (say home_controller , home#index)
I tried render : partial ,render :template also with locals , I can't achieve.
It can be easily done by moving all the object to same controller ( home_controller , but i am not sure about this approach , since it will make home controller too complicated to manage ) , but I need to keep this in separate controllers (question_controller , answers_controller, hints_controller) and render it to same page. I am using client side validation, simple form gems.
Below is my question controller
class QuestionsController < ApplicationController
def index
#question = Question.new
#question_status = []
#question_mode = []
#question_type = []
#question_lookups = Lookup.where({:lookup_for => "question"})
#question_lookups.each do |lk|
case lk.lookup_type
when 'mode'
#question_mode << lk
when 'status'
#question_status << lk
else
#question_type << lk
end
end
#caa = Questioncaa.new
end
end
Question View ( with Simple form )
<%= simple_form_for #question, :validate => true do |q| %>
<%= q.input :question_info, :as => :ckeditor, :input_html => { :toolbar => 'Easy', :width => 750 } %>
<%= q.input :question_source %>
<%= q.input :is_mobile %>
<%= q.input :is_similar_question %>
<%= q.input :is_boss_question %>
<%= q.input :is_racing_question %>
<%= q.input :is_speed_question %>
<%= q.input :difficulty_level %>
<%= q.input :ideal_time %>
<%= q.input :lookups, :collection => #question_mode, :value_method => :id, :label_method => :lookup_value,:prompt => "Choose Mode", :label => :QuestionMode %>
<%= q.input :lookups, :collection => #question_status, :value_method => :id, :label_method => :lookup_value,:prompt => "Choose Status", :label => :QuestionStatus %>
<%= q.input :lookups, :collection => #question_type, :value_method => :id, :label_method => :lookup_value,:prompt => "Choose Type", :label => :QuestionType %>
<%= simple_fields_for #caa do |c| %>
<%= c.input :needs_hints %>
<%= c.input :needs_video_solution %>
<%= c.input :needs_tips_tricks %>
<%= c.input :needs_formulae %>
<%= c.input :needs_key_concepts %>
<% end %>
<%= q.button :submit %>
<% end %>
Home View
<div class="tab-content">
<div class="tab-pane active" id="learning_map">
<!-- I need to acheive this -->
<%= render :template => "learning_map/index" %>
</div>
<div class="tab-pane" id="questions">
<!-- I need to acheive this -->
<%= render :template => "questions/index", :collection => #question_mode %>
</div>
<div class="tab-pane" id="answers">.
<!-- I need to acheive this -->
<%= render :templates => "answers/index" %>
</div>
</div>
Pls advice me , it will be very helpful. Thanks for reading this.
You should change logic of your templates a little (here is example for 'question' view):
1) split your question template into 2 files:
- header with form declaration of simple_form_for
- _form.html.erb file with <%= fields_for #question do |q| %> and list of your questions fields like <%= q.input %>
2) add <%= render :partial => 'form' %> in your header file
3) use <%= render :partial => 'question\form' %> in your home view template
4) dont forget to initialize #question variable in home_controller.
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Passing only two variables between controller and view - best practice?
There is my action:
def list
#codes = Code.order("created_at")
#languages = Language.order('name').collect {|l| [l.name, l.coderay]}
end
There is my view(I removed some lines):
<% #codes.each do |code| %>
<div class="code">
<%= link_to code.title, :action => 'show', :id => code.id %>
<% if code.author %>
#<%= code.author %>
<% end %>
</div>
<% end %>
<%= render :partial => 'shared/error_messages', :locals => {:object => #code} %>
<%= form_for :code, :url => {:action => 'create' }, :html => {:multipart => true} do |f| %>
<%= f.text_field :title %><br />
<%= f.text_area :content %><br>
<%= f.select(:language, #languages, {:selected => 'text'}) %>
<%= f.text_field :author %><br>
<%= f.submit "Submit code" %>
<% end %>
There are 3 variables in it: #codes(list of posts), #code(current post, used in another action) and #languages.
My IDE writes:
At most two instance variables should be shared between controller and
view
This inspection warns if there are more than two instance
variables shared between a controller and a view. A controller should
only manage one instance variable, plus a second one for the
current_user variable.
Usually I share more variables between Controller and View(in PHP), sometimes 10+.
How it's done in Rails?
You can save an instance var by making languages a helper:
def languages
Language.order('name').collect {|l| [l.name, l.coderay]}
end
Its a guideline some developers follow some of the time.
But I would read up on Rails Routing a bit more. Understanding how Rails routing works should give you a better idea on how to structure your code.
http://guides.rubyonrails.org/routing.html
I modified your code a bit, not tested. But hopefully gives you some good ideas.
Controller:
def new
#code = Code.new
#codes = Code.order("created_at")
end
def create
#code = Code.new(params[:code])
if #code.save?
# Do your thing.
else
# render your :new action passing your #code variable
end
end
View:
<% #codes.each do |code| %>
<div class="code">
# Use Rails Routing - In console, type rake routes to get list of routes.
<%= link_to code.title, code_path(code.id) %> # example.
<% if code.author %>
<%= code.author %>
<% end %>
</div>
<% end %>
<%= render 'shared/error_messages', :object => #code %>
<%= form_for #code, :html => {:multipart => true} do |f| %>
<%= f.text_field :title %><br />
<%= f.text_area :content %><br>
# language_list = helper method.
<%= f.select(:language, language_list, {:selected => 'text'}) %>
<%= f.text_field :author %><br>
<%= f.submit "Submit code" %>
<% end %>
Here is a partial form _standards.html.erb we want to add to the view dynamically:
<p><%= f.association :standards, :collection => Standard.active_std.all(:order => 'name'), :label_method => :name, :value_method => :id :include_blank => true %></p>
Here is the view form itself _form_new.html.erb which calls _standards.html.erb:
<%= simple_form_for #rfq do |f| %>
<div id="std">
<%= render :partial => 'standards/standards', :collection => #rfq.standards, :locals => { :f => f } %>
</div>
<%= link_to_function("Add std", nil) do |page| %>
page.insert_html :bottom, 'std', :partial => 'standards/standards', :object => #rfq.standards.build
<% end %>
<%= f.button :submit, 'Save' %>
<% end %>
This solution did not work as link_to_function was not reacting to click by loading the _standards.html.erb. This solution seems out of date and does not work in rails 3.1.0. I am wondering if there is other solution to add dynamic content to the view page in rails 3.1.0. If you do, please don't hesitate to post. Thanks.
I know this answer is coming months after you need it but hopefully this helps someone else who stumbles across this question. Here is how you can dynamically add a selection box unobtrusively for your example.
_form_new.html.erb
<%= simple_form_for #rfq do |f| %>
<a id="add-selection-box" href="#">Add Selection Box</a>
<div id="std"></div>
<script type="text/javascript">
$(document).ready(function(){
$("#add-selection-box").click(function() {
$("#std").append("<%= escape_javascript(render(:partial => 'standards/standards', :collection => #rfq.standards, :locals => { :f => f })) %>");
});
});
</script>
<% end %>
Here is how you can do it using link_to_function
_form_new.html.erb
<%= simple_form_for #rfq do |f| %>
<%= add_selection_box "Add Selection Box", #rfq.standards, f %>
<div id="std"></div>
<% end %>
helpers/my_form_helper.rb
module MyFormHelper
def add_selection_box(name, collection, form)
page = %{
partial = "#{escape_javascript(render(:partial => "standards/standards", :collection => collection, :locals => { :f => form }))}";
$("#std").append(partial);
}
link_to_function name, page
end
end
In a Rails view, I'm trying to show a <select> drop-down list for a number of different string fields with restricted values.
I've been trying to do this with a partial (below), but the current value is not being selected in the <select> list.
Is it possible to do this in a partial? If so, how?
Is there a better approach to take?
edit.html.erb:
<% form_for(#my_class) do |f| %>
<%= render :partial => "select", :locals => { :attribute_name => :blah, :f => f } %>
<% end %>
_select.html.erb:
<p>
...
<%= f.label attribute_name %><br />
<%= f.select attribute_name, [:option_a,:option_b,:option_c], { :selected => attribute_name } %>
...
</p>
I believe the selected option checks based on the value, not the name of the attribute.
This may work for you, but I have not tested it out:
<%= f.select attribute_name, [:option_a,:option_b,:option_c], { :selected => #my_class.send(attribute_name) } %>