I'm using Rails 6.0.2.2, Foundation, and wanted to do some nested forms using Cocoon. Here are my models:
class Adventure < ApplicationRecord
alias_attribute :pcs, :player_characters
has_many :player_characters, dependent: :destroy
accepts_nested_attributes_for :player_characters
end
class PlayerCharacter < ApplicationRecord
belongs_to :adventure
end
And here my views:
# _form.html.erb
<%= simple_form_for #adventure do |f| %>
<%= f.input :email %>
<%= f.input :test %>
<h3>PCs</h3>
<%= f.simple_fields_for :player_characters do |player_character| %>
<%= render 'player_character_fields', f: player_character %>
<% end %>
<div class='links'>
<%= link_to_add_association 'Add PC', f, :player_characters %>
</div>
<%= f.submit %>
<% end %>
# _player_character_fields.html.erb
<div class='nested-fields'>
<%= f.input :path %>
<%= f.input :race %>
<%= f.input :name %>
<%= f.input :player_name %>
<%= link_to_remove_association "remove PC", f %>
</div>
Neither the render nor the link_to display anything. I tried creating a different partial and if I render it outside of the simple_fields_for it works normally, but as soon as move it inside, it stops.
I tried all the solutions mentioned here https://github.com/nathanvda/cocoon/blob/master/app/assets/javascripts/cocoon.js:
create a file in app/javascript/src/cocoon.js
yarn add cocoon-js
yarn add github:nathanvda/cocoon#c24ba53
but nothing worked, and I didn't get any error messages in the console log.
Related
Order has_many jobs
Job belongs to order
And I want to edit attributes of #job.order:
<% order = #job.order %>
<%= simple_form_for [#job, order],
url: job_path(#job),
method: :put,
remote: true do |f| %>
<%= f.input :order_status, input_html: {class: 'form-control'} %>
(...)
<% end %>
any way to do it by just using input in simple form?
in job.rb
accepts_nested_attributes_for :order
in form.html.erb
simple_form_for #job do |f|
f.simple_fields_for #job.order do |order_form|
order_form.input :status
end
end
in jobs_controller.rb
params.require(:job).permit(:something, :something_else, :order_attributes => [:status])
You can use the excellent Cocoon gem https://github.com/nathanvda/cocoon to manage nested relationships, including the ability to easily add new nested relationships.
class Job < ActiveRecord::Base
has_many :orders
accepts_nested_attributes_for :orders, reject_if: :all_blank, allow_destroy: true
end
class Order < ActiveRecord::Base
belongs_to :job
end
Note the pluralization.
_form.html.erb*
<%= form_for #job do |f| %>
<%= f.label :job_name %>
<%= f.text_field :name %>
<div id='order'>
<%= f.fields_for :orders do |order| %>
<%= render 'order_fields', f: order %>
<% end %>
<div class='links'>
<%= link_to_add_association 'add order', f, :orders %>
</div>
<%= f.submit %>
<% end %>
_order_fields.html.erb partial
<div class='nested-fields'>
<%= f.label :order_name %>
<%= f.text_field :order_name %>
</div>
<%= link_to_remove_association "remove order", f %>
I'm doing a big nested form, where the user can upload an image for each nested form.
But I have a doubt. How can I show to the user, when he edit's the form, if there is already an image uploaded to each nested form? I thought of showing the image file name next to the file loader input, but i have no idea how to do that.
Here's my code:
Model
class Chapter < ActiveRecord::Base
attr_accessible :content, :reference, :story_id, :image, :decisions_attributes
mount_uploader :image, ImageUploader
end
View
<%= simple_form_for(#story) do |f| %>
<%= f.simple_fields_for :chapters do |builder| %>
<%= render "chapters_fields", f: builder %>
<% end %>
<p>
<%= link_to_add_fields "Add chapters", f, :chapters, "chapters" %>
</p>
<% end %>
Form Partial
<div class="chapter-fields">
<h3>Chapter</h3>
<p>
<%= f.input :reference %>
<%= f.input :content, as: :text, input_html: { rows: 10, style: 'width: 100%' } %>
<%= f.input :image %>
<%= f.image_url %>
</p>
<div>
<%= f.simple_fields_for :decisions do |builder| %>
<%= render "decisions_fields", f: builder %>
<% end %>
<%= link_to_add_fields "Add decisions", f, :decisions, "decisions" %>
</div>
<p><%= link_to_remove_fields "Remove chapter", f, "chapter" %></p>
</div>
You can access the object behind a form builder variable via the object keyword.
if f.object.image.blank?
"No current image"
else
"Current image: #{f.object.image.url}"
end
Note: This only works if you have accepts_nested_attributes_for :chapters in your Story model.
I am working on a dynamically nested form using the cocoon gem. I have two models
class CrossTable < ActiveRecord::Base
attr_accessible :title, :table_name, :database, :folder_label_id, :foreign_fields_attributes
belongs_to :folder_label
has_many :foreign_fields
accepts_nested_attributes_for :foreign_fields
validates :title, :table_name, :database, :folder_label_id, presence: true
end
class ForeignField < ActiveRecord::Base
attr_accessible :cross_table_id, :column_name, :description
belongs_to :cross_table
has_many :filter_sets
end
I have cocoon and jquery-rails in the gemfile
I added //=require cocoon to the application.js file
And here is my form partial
<%= simple_form_for #table do |f| %>
<%= f.input :title %>
<%= f.input :folder_label_id, :collection => #folders, :label_method => :title, :value_method => :id %>
<br><br>
<%= f.input :table_name %>
<%= f.input :database %>
<%= f.simple_fields_for :foreign_fields do |fields| %>
<%= render 'foreign_field_fields', :f => fields %>
<div id='links'>
<%= link_to_add_association 'Add Field', f, :foreign_fields %>
</div>
<% end %>
<%= f.button :submit %>
<% end %>
#table is an instance of the cross table model. Nothing in the foreign_field_fields partial shows up and link_to_add_association does nothing, and I get no errors. How can I start debugging this? Does anyone spot an error?
You wrote the link_to_add_association inside the simple_fields_for, which will loop over all :foreign_fields and execute the given block. So if there are no foreign-fields yet, the link_to_add_association is never shown.
You should write your view as follows (as documented):
<%= simple_form_for #table do |f| %>
<%= f.input :title %>
<%= f.input :folder_label_id, :collection => #folders, :label_method => :title, :value_method => :id %>
<br><br>
<%= f.input :table_name %>
<%= f.input :database %>
<%= f.simple_fields_for :foreign_fields do |fields| %>
<%= render 'foreign_field_fields', :f => fields %>
<% end %>
<div id='links'>
<%= link_to_add_association 'Add Field', f, :foreign_fields %>
</div>
<%= f.button :submit %>
<% end %>
Hope this helps.
I'm actually trying cocoon gem(by nathanvda) along with simple_form gem to dynamically add and remove fields on a form .I don't understand why the nested form doen't show up on my forms.Here's the code.(I'm newbie of course).Please can I have some help.
menu/_form.html.erb
<%= simple_form_for #menu do |f| %>
<%= f.input :name %>
<%= f.input :price %>
<%= f.simple_fields_for :drinks do |drink| %>
=render "drink_fields", :f => drink.links %>
<%= link_to_add_association "Add drink"%>
<%end%>
<%= f.button :submit %>
<%end%>
menu/_drink_fields.html.erb
.nested-fields
<%= f.input :name %>
<%= link_to_remove_association "remove drink", f %>
these are the models
class Drinks < ActiveRecord::Base
belongs_to :menu
end
class Menu < ActiveRecord::Base
attr_accessible :drinks_attributes
has_many :drinks, :dependent => :destroy
accepts_nested_attributes_for :drinks
end
in assets/javascripts/application.js
//= require cocoon
in layouts/application.html.erb
<%= javascript_include_tag :cocoon %>
Your nested form is wrong, you are mixing haml and erb. If you have no personal preference yet, I would recommend using haml, I find it much easier and cleaner than erb.
All that aside, your menu/_drink_fields.html.erb should look as follows:
<div class='nested-fields'>
<%= f.input :name %>
<%= link_to_remove_association "remove drink", f %>
</div>
Also, inside your menu/_form.html.erb you should write the following:
<%= f.simple_fields_for :drinks do |drink| %>
<%= render "drink_fields", f: drink %>
<% end %>
<%= link_to_add_association "Add drink", f, :drinks %>
Hope this helps.
Thanks for the head ups nathanvda.I finally find a gem to handle nested fields, Here is the link: https://github.com/lailsonbm/awesome_nested_fields.
I have a basic has_many through relationship:
class Foo < ActiveRecord::Base
has_many :bars, :dependent => :destroy
has_many :wtfs :through => :bars
accepts_nested_attributes_for :bars, :wtfs
end
On my crud forms I have a builder block for the wtf, but I need the label to come from the bar (an attribute called label for instance). What's the proper method to do this?
Here's the most simple scaffold:
<h1>New foo</h1>
<% form_for(#foo) do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<h2>Bars</h2>
<% f.fields_for :wtfs do |builder| %>
<%= builder.hidden_field :bar_id %>
<p>
<%= builder.text_field :wtf_data_i_need_to_set %>
</p>
<% end %>
<p>
<%= f.submit 'Create' %>
</p>
<% end %>
<%= link_to 'Back', foos_path %>
The answer was found in analyzing how the rails FormBuilder works. So in the example above where I need to access the actual wtf object so I can get a property on bar, I need to do the following:
<h2>Bars</h2>
<% f.fields_for :wtfs do |builder| %>
<%= builder.hidden_field :bar_id %>
<p>
<%= builder.label builder.object.bar.data_i_need_for_a_label %>
<%= builder.text_field :wtf_data_i_need_to_set %>
</p>
<% end %>