I want to assign unique Id to each row generated by nested form .
I looked this question Creating unique id for <fieldset> when using form_for Rails Nested Model Form but this doesn't solve my problem .
I managed to solve this problem by looking into nested form gem .
Inside nested gem unique Id is generated for each addition dynamically.
data-blueprint is parsed and "new_#{association}" is replaced with generated unique ID.In my case relation was like 'Catalogues' has_many 'Category' so my association was categories.
I assigned new row with id = "new_categories" and its replaced by unique Id when new row is added.
Maybe its useful some one else.
Actually, the solution given by Anil Maurya only works for items that have been dynamically added via javascript using link_to_add provided by the gem. But for me, it would leave new_association for already existing items.
In order to properly identify every nested element (even the deeply nested ones), it is possible to use f.index. The advantage is that if the entry already exists (meaning, if it was in the database), then it will just be replaced by the index that it has in the array. However, using link_to_add will replace f.index by the ID automatically generated by nested_form, just like Anil Maurya's solution.
For deeply nested solutions, instead of just writing fields_for and using the same variable f everytime, if you need to properly tag your elements, your should specify which partial to render and each time use a different f variable, which you should pass to the partial
For example: if you have
Main has_many :nested1s
Nested1 has_many :nested2s
Nested2 has_many :nested3s
Then your code should look like this (I gave an example with tables because it's more difficult):
<%= nested_form_for #Main do |main_form| %>
<table>
<thead>
<stuff />
</thead>
<%= main_form.fields_for :nested1s, :wrapper => false do |nested1_f| %>
<%= render 'main/nested1_fields', nested1_f: nested1_f %>
<% end %>
_nested1_fields.html.erb
<tbody class="fields">
<tr>Stuff</tr>
<tr>
<table id="nested1-<%= nested1_f.index %>-nested2s">
<thead>Stuff</thead>
<%= nested1_f.fields_for :nested2s, :wrapper => false do |nested2_f| %>
<%= render 'main/nested2_fields', nested1_f: nested1_f, nested2_f: nested2_f %>
<% end %>
</table>
</tr>
<tr><%= nested1_f.link_to_add 'add nested2', :nested2, :data => { :target => "#nested1-#{nested1_f.index}-nested2s"}, class: "btn btn-sm btn-success" %>
</tbody>
_nested2_fields.html.erb
<tbody class="fields">
...
<table id="nested1-<%= nested1_f.index %>-nested2-<%= nested2_f.index %>-nested3s">
<%= fields_for :nested3s do |nested3_f| %>
...
...
</tbody>
Also it is important to note that the gem nested_form will only work well if every nested fieldsets are wrapped by a tag with the class "fields"
Related
I'm working on an admin functionality for an application in Rails.
I've got a table in a page that lists a series of attributes of a particular model "Property".
I want users to be able to click on each line and make the attribute value editable by rendering a partial. In order to do that I assume I need to create a partial for each attribute and have a similar form in each partial with one visible field related to the attribute the user clicked on.
Something like:
View:
<tr id="edit_price" data-link="<%= 'edit_field_price_path' %>">
<% if !#property.price.blank? %>
<th scope="row">Price</th>
<td>$<%= #property.price %></td>
<td>Edit</td>
<% else %>
<th scope="row" class="empty">Price</th>
<td class="empty">Add price</td>
<% end %>
</tr>
Partial:
<%= form_with model: #property, method: :put do |f| %>
<%= f.number_field :price %>
<%= f.hidden_field ONE_FOR_EACH_VALUE, value: ATTRIBUTE_VALUE %>
...
<% end %>
The problem is that I've got over 40 potential fields that can be edited, which means I'd need to create over 40 partials in separate files and add them all to my routes.rb file.
How can I come up with a smarter solution for that?
Is it possible to pass the attribute name as a variable and dynamically edit a single form with jquery?
Does the same need to be done with the routes file?
Thanks a lot in advance.
for that you can use something like best in place gem, it basically create the functionality you like, not for the complete line, but for specific attributes.
read the documentation for configuration, after doing that, you can create the clickable/editable attribute by doing this on your view
<%= best_in_place #user, :name, :as => :input %>
this will create the clickable text, and this will fire the input on the frontend to edit it.
I ended up creating all of those partials. They have different types of fields, so I couldn't find any way to optimize that.
Running a single jquery script that identifies where to place each partial depending on the field name to access each form partial made implementation a bit easier though. It's been proposed here: Concatenate jquery variable into Rails partial
I have a table in view:
#view
<%= form_tag save_table_path do %>
<table>
<% #channel_name_body.values.max_by(&:size).size.times do |i| %>
<tr class="border">
<% #channel_name_body.values.map { |a| a[i] }.each do |value| %>
<td contenteditable class="border light_green"><%= value %></td>
<% end %>
</tr>
<% end %>
</table>
<%= submit_tag "save",:class => "btn btn-primary offset4" %>
<% end %>
I don't know what to do next to pass value of all cell in table to controller such as:
#controller
def save_table
#table=params[:table] #or #row1=params[:row1]... or #col1=params[:col1]....
end
Edit: I found way to solve this problem, it must use js.
I don't want to use js, what about if I change to <%= text_field_tag :cell, value %> how can I get value of all cell in table ?
I think you're getting confused with how to handle data in Rails (or any backend system)
HTML
HTML is a markup language; which means if you give it certain code, it will put various elements onto the page. The <table> tag is one of those elements, and has no bearing on the controller-side functionality of your app
Controller Params
HTML form params are directly related to the form (nothing else)
In Rails, you get the params hash ordered like this:
params[:form_name][:input_name]
Your Code
From what you've shown, it seems you have several parts missing
Firstly, you need input elements (to populate the params). Currently, you have:
<td contenteditable class="border light_green"><%= value %></td>
This does not create any params, as it's not an input element. It's just a value that's been outputted on the screen. What you'd need is something like:
<td contenteditable class="border light_green"><%= text_field_tag :cell, :value => value %></td>
By adding these inputs, you will give Rails the ability to populate the params hash with their values, which you can then access from your controller like this:
def save
#table = params[:form_name][:cell][0]
end
Hope this helps?
Try this:
<%= text_field_tag "table[cell#{index}]", value %>
On form submit it will give you values like params[:table][:cell1], params[:table][:cell2] and so on...
Hope this helps..
I am new to Rails and have been learning it on my own. This is also the first time I am posting on Stackoverflow although I refer to it a lot. Below is the snippet of the ERB code that's displaying the records of a model called Ideas:
<% #idea.each do |i| %>
<tr>
<td><%= i.name %></td>
<td><%= i.description %></td>
<td><a class="btn" href="share"><i class="icon-share"></i></a></td>
<td>
<%= link_to(ideas_edit_path(#i), :class => 'btn') do %>
<i class="icon icon-edit"> </i>
<% end %>
</td>
<td><a class="btn" href="destroy"><i class="icon-trash"></i></a></td>
</tr>
<% end %>
Each row contains "Name", "Description" followed by icons called "share", "edit", "destroy". I want to display a form for each of these actions for that particular record. I don't know how to pass the id of the record to these actions. Can somebody please point me in the right direction? I think I have the routes defined correctly because I can type in the full ERL (/ideas/2/edit) and it brings up the edit form.
When you're using the named routes (i.e. ideas_edit_path), you can just pass a model object in as an argument, and they'll build the correct route for that object. There's a bug in your code above where you're referring to #i when it should be i (the local variable declared in the loop above it).
Another minor nit: you probably want to use #ideas rather than #idea for the collection to indicate that it's a collection, but that's not necessarily a bug in itself.
Change your #idea to #ideas to reflect that it is a collection.
The set that you iterate over should be something like
#ideas.each do |idea|
link_to(edit_idea_path(idea), :class => 'btn')
end
So your link is now to edit_idea_path(idea)
The form file will be in app/view/ideas called edit.html.erb
Actually the form is shared by the new and edit actions so the best idea is to have _form.html.erb and include that in both the new and edit forms.
Code in the .erb template will be like
form_for #idea do |f|
various input fields
end
I would recommend that you quickly try to create another app using the scaffolding that's available in rails. Then look at what gets generated and you'll be better informed about what things should be named, where they are, etc.
This might sounds a bit drastic, but really it's as simple as:
$ cd ~ # Go to root
$ mkdir newapp # Create a new directory
$ cd newapp # Create a new rails app
$ rails generate scaffold Idea name:string description:text # Use scaffolding
You can use the link_to helper with a do to build a block.
<%= link_to edit_idea_path(i), class: "btn" do %>
<i class="icon icon-edit"></i>
<% end %>
Looks like your using the Bootstrap framework with Rails -- very nice combination!
I'm starting to develop a small application in Ruby On Rails. I have a short form (within a view) in which the number of fields is variable and created with the code snippet below:
<% for item in #event.items %>
<tr>
<td><%= item.name %></td>
<td><input type="number" name="quantity" /></td>
</tr>
<% end %>
I want to after click 'submit', run a controller's method that access to the data included in each of the fields in the form and perform insertions on the database. In the end, I want the page to be refreshed.
How do I customize the action of the submit button to perform a controller's function? And how do I access inside this function to the form fields (whose number is variable as mentioned).
Thanks in advance for your help.
You can use nested attributes. Then it should looks something like this (sorry for HAML):
= form_for #event do |f|
= f.fields_for :items do |item|
= item.object.name #displays item name
= item.number :quantity
And in your event model:
accepts_nested_attributes_for :items
I would suggest to use in this case the nested_form gem https://github.com/ryanb/nested_form.
This is hopefully a slam dunk for a Rails maven :
I have a form that is supposed to iterate over a set of LineItems and gather information on each. I am trying to get form_for and fields_for to create the proper field names and parameters to give my controller a params hash something like
params[:line_items] = { <line_item.id> => { :rma_reason => "some string", :rma_qty => 2 } }
What I have is:
<% form_for(#object) do |rma_form| %>
<% #order.line_items.each do |item| %>
....
<% fields_for item do |item_f| %>
<%= item_f.text_area :rma_reason %>
<%= item_f.text_field :rma_qty, :value => item.quantity, :size=>3 %>
<% end %>
....
<% end %>
<% end %>
And the resultant HTML looks like (what you would expect, I guess):
<textarea id="line_item_id" name="line_item[id]"></textarea>
<input id="line_item_rma_qty" name="line_item[rma_qty]" size="3" type="text" value="1" />
However what I am trying to get (and failing to find any solution beyond going back to ad-hoc HTML tags) is, field names that are indexed by the line_item.id, e.g. line_item[1928][rma_qty] for instance. This would allow my controller to iterate over each line_item and update it with the given params.
... maybe in a pure REST UI, the form should be tied to ONE instance of LineItem, and the standard form_for would work - but the user should be able to submit all the changes at once with one form. Is it possible?
When you're nesting form fields, you have to make sure you are chaining the fields_for methods form the appropriate form builder:
<% rma_form.fields_for :line_item, item do |item_f| %>
by calling fields_for alone, you were breaking the chain from form_for and thus the incorrect field names.
the fields_for needs to be called on the main form helper, and a string parameter with magic []s and an argument indicating which instance should be inserted in the []s
<% rma_form.fields_for "line_item[]", item do |item_f| %>
so now my tag looks something like
<input id="return_authorization_line_item_1070870205_rma_qty" name="return_authorization[line_item][1070870205][rma_qty]" size="3" type="text" value="1" />
which is peachy.
this classic railscast is a good fields_for intro, and this comment explains the effect of the magic bracket that did what I wanted - other than that, couldn't find this feature documented anywhere.