Rails: split a nested form into partials - ruby-on-rails

I have a nested form which works perfectly fine, however, I'm trying to figure out how to split that nested form into a partial.
original form:
<%= form_for(#user) do |f| %>
<%= f.fields_for :achievements, Achievement.new do |ff| %>
<div class="field">
<%= ff.label :certification_name, 'Cert Name' %>
<%= ff.text_field :certification_name %>
</div>
<% end %><!-- fields_for -->
<%= f.submit 'Save', id: "submit-achievement", class: 'btn btn-primary' %>
Here's what I'm trying to do....
<%= form_for(#user) do |f| %>
<%= f.fields_for :achievements, Achievement.new do |ff| %>
<%= render partial: 'achievements/new_certification' %>
<% end %><!-- fields_for -->
<%= f.submit 'Save', id: "submit-achievement", class: 'btn btn-primary' %>
here's the partial.
<div class="field">
<%= ff.label :certification_name, 'Cert Name' %>
<%= ff.text_field :certification_name %>
</div>
the problem is that it doesn't know what to do with the 'ff' variable.
ActionView::Template::Error (undefined local variable or method `ff' for #<#<Class:0x007fdccd5498c0>:0x007fdcc04894d8>):

You can achieve this by passing a local variable to your partial like so:
<%= render partial: 'achievements/new_certification', locals: {ff: ff} %> # not a fan of the naming
Then in achievements/_new_certification.html.erb
<div class="field">
<%= ff.label :certification_name, 'Cert Name' %>
<%= ff.text_field :certification_name %>
</div>
Documentation on partials

Related

How to insert new line breaks using form_for with collection_check_boxes

I use the following form_for at one point in my code to display a series of topics for users to select from.
<%= form_for #user do |f| %>
<%= f.collection_check_boxes(:topic_ids, Topic.all.sample(50).each, :id, :topic_name) %>
<%= f.submit %>
<% end %>
When it renders on the page, the boxes are all one-after-the-other. How can I separate them so that there is one check box per line?
from reference here
It is possibly to customize the way the elements will be shown by giving a block to the method as sample below from your code above
<%= form_for #user do |f| %>
<%= f.collection_check_boxes :topic_ids, Topic.all.sample(50).each, :id, :topic_name do |b| %>
<%= b.label(class: "check_box") do %>
<%= b.check_box(class: "check_box") %>
<%= b.object.topic_name %></br>
<% end %>
<% end %>
<%= f.submit %>
<% end %>
You may of course render HTML inside the block:
<%= form_for #user do |f| %>
<%= f.collection_check_boxes :topic_ids, Topic.all.sample(50).each, :id, : topic_name do |b| %>
<div class="my-checkbox-wrapper">
<%= b.label(class: "foo") do %>
<%= b.object.topic_name %>
<%= b.check_box(class: "bar") ></br>
<%end%>
<%= f.submit %>
<%end%>
You can have a look at this example
It is very broad question. In short, using CSS.
For example using Bootstrap 4:
<%= form_for #user do |f| %>
<div class="form-check">
<%= f.collection_check_boxes :topic_ids, Topic.all.sample(50).each, :id, :topic_name, class: 'form-check-input' %>
</div>
<%= f.submit %>
<% end %>

Ruby on Rails - Nested Render

I am trying to make a multi step sign up form using wicked gem.
But when try a nested render. im getting an error like
undefined local variable or method `f' for
<#:0x007f1d11128718>
new.html.erb
<%= render 'form', name: #name do %>
<%= render 'form_first_name' %>
<% end %>
<%= link_to 'Back', names_path %>
_form.html.erb
<%= form_for(name) do |f| %>
<%= yield %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
_form_first_name.html.erb
<div class="field">
<%= f.label :first_name %>
<%= f.text_field :first_name %>
</div>

Extend forms without page reload, rails

I'm searching for a solution to extend my form without page reload.
First I tried to render a partial with coffee or javascript, but escape_javascript didnt work.
Here's the view
<%= form_for #recipe = current_user.recipes.build do |f| %>
<%= f.label :name, "Recipe Name" %>
<%= f.text_field :name %>
<%= button_to "Add Ingredient", '#', class: "btn btn-lg btn-primary", id: "add" %>
<p></p>
<%= f.submit class: "btn" %>
<% end %>
The form above should be extented with following partial by every click on the button
<div id="recipe-ingredients">Quantity
<%= f.fields_for :quantities, #recipe.quantities.build do |quantity| %>
<%= render 'quantity_fields', f: quantity %>
<% end %>
</div>
_quantity_fields
<%= f.label :amount, "Amount:" %>
<%= f.text_field :amount %>
<%= f.collection_select(:ingredient_id, Ingredient.all, :id, :name) %>
This approach did not work (recipes.js.erb)
$(document).ready(function() {
$("#add").click(function() {
$("p").append("<%= escape_javascript
render(:partial => 'quantities') %>");
});
});
There's a workaround (see below) but I'm searching for a better solution.
$(document).ready(function() {
$("#workout-week").append(<%= escape_javascript(
Haml::Engine.new(File.read(File.join(Rails.root,'app/views',
'_show_period.html.haml'))).render(Object.new, period: #period)) %>);
});
A second approach is to write following lines in Coffee or JavaScript:
<%= f.fields_for :quantities, #recipe.quantities.build do |quantity| %>
<%= f.label :amount, "Amount:" %>
<%= f.text_field :amount %>
<%= f.collection_select(:ingredient_id, Ingredient.all, :id, :name) %>
<% end %>
I'm a newbie so take this with a grain of salt, but have you tried using render :foo instead of redirect_to :foo in the appropriate controller function?
I solved it with cocoon
<%= form_for #recipe do |f| %>
<div class="field">
<%= f.label :name %>
<br/>
<%= f.text_field :name %>
<%= f.fields_for :quantities do |quantity| %>
<%= render 'quantity_fields', :f => quantity %>
<% end %>
<div class="links">
<%= link_to_add_association 'add', f, :quantities %>
</div>
</div>
<%= f.submit %>
<% end %>

Rails 4 - Rendering partial with access to class

I have two classes Bid (has_many :mozs) and Moz (belongs_to :bid). I am trying to render a partial for creating Moz objects.
<%= f.fields_for :mozs do |builder| %>
<%= render "moz_fields", :f => builder %>
<% end %>
in my partial:
<div class="field fields">
<%= f.label :url, "Comparative URL" %><br>
<%= f.text_field :url %>
<%= f.hidden_field :destroy %>
<%= link_to_function "remove", "remove_fields(this)"%>
</div>
When the contents of the partial are in the fields_for tag:
<%= f.fields_for :mozs do |builder| %>
<div class="field fields">
<%= builder.label :url, "Comparative URL" %><br>
<%= builder.text_field :url %>
<%= builder.hidden_field :destroy %>
<%= link_to_function "remove", "remove_fields(this)"%>
</div>
<% end %>
then everything works fine. But I need it in a partial to dynamically add the fields. When I keep it in a partial I get this error: undefined method `url' for NilClass:Class.
I don't understand why the class would be nil just because I put it in a partial.
I think the problem will likely be with your rendering of a partial inside the fields_for tag && you're not using the locals argument:
<%= render partial: "moz_fields", locals: { f: builder } %>
#moz_fields
<%= f.fields_for :mozs do |b| %>
<div class="field fields">
<%= b.label :url, "Comparative URL" %><br>
<%= b.text_field :url %>
<%= b.hidden_field :destroy %>
<%= link_to_function "remove", "remove_fields(this)"%>
</div>
<% end %>

How to ensure all nested attributes show during 'edit'

I currently have a nested model User has_many Sales_Orders has_many Items.
I can create the Sales_Order with nested Items properly but when I try to 'edit' the Sales_Order, the Sales_Order information is visible but the Items are not shown. Any idea why these wouldn't show?
[sales_orders_controller.rb]
...
def edit
#sales_order = SalesOrder.find(params[:id])
end
[edit.html.erb]
<% provide(:title, "Edit SO") %>
<h1>Edit Sales Order</h1>
<div class="row">
<div class="span6 offset3">
<%= form_for(#sales_order) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="span3">
<%= f.label :so, "SO#:" %>
<%= f.text_field :so %>
<%= f.label :customer, "Customer:" %>
<%= f.text_field :customer %>
<%= f.label :enter_date, "Date Entered:" %>
<%= f.text_field :enter_date, value: date_formatter(#sales_order.enter_date) %>
<%= f.label :request_date, "Request Date:"%>
<%= f.text_field :request_date, value: date_formatter(#sales_order.request_date) %>
<%= f.label :comments, "CS Comments:" %>
<%= f.text_area :comments %>
</div>
<div class="span3">
<% f.fields_for #sales_order.items do |builder| %>
<%= render 'item_fields', f: builder %>
<% end %>
</div>
<%= f.submit "Save changes", class: "btn btn-large btn-primary" %>
<% end %>
</div>
</div>
[_item_fields.erb]
<fieldset>
<%= f.label :item_code, "Item Code:" %>
<%= f.text_field :item_code %>
<%= f.label :qty_in_kg, "Qty (kg):" %>
<%= f.text_field :qty_in_kg %>
<%= f.label :qc_comments, "Comments:" %>
<%= f.text_field :qc_comments %>
<%= link_to "remove", '#', class: "remove_fields" %>
</fieldset>
<% f.fields_for #sales_order.items do |builder| %>
should be
<%= f.fields_for #sales_order.items do |builder| %>
Without the = you're building the output in the loop but never rendering/printing the return value (the generated HTML output).
Use <%= f.fields_for #sales_order.items do |builder| %>
Notice the = sign. This implies, "evaluate and embed"

Resources