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
Related
I am a beginner in ruby. I have a table in a view, that when I click on the line / item it should pick up the ID of the selected line and move to the other view that will be triggered, I am 3 days searching on and I can not implement.
The view that should take the ID or another parameter so that in the other I can treat the select to bring more detailed information >>:
<td>
<%= link_to pedido.id, detalhes_backoffice_pedidos_path(:pedido_id =>
pedido.id) , :onclick=>"window.open(this.href,'create_company',
'height=600,
width=600');return false;" %>
</td>
The view ("popup") that is called when clicked on the request id. Obs.:Tried in countless ways, and at the moment she is like this ... >>>>
<div class='container-fluid'>
<div style='display: block;' class="col-xs-6 esquerdo ">
<label>Num.pedido<%= pedido.id %></label> <br>
<label>nome</label> <br>
<label>telefone</label> <br>
</div>
Controller>>
class Backoffice::PedidosController < BackofficeController
.....
def detalhes
render :layout => "application"
#pedido = params[:pedido_id]
end
I am totally lost, after trying so much .... If you can pass some example link for study, it will be very useful too !!
It has become clear that you just need to use AJAX to show the selected pedido details on the page. Rails has an easy way to do this.
First put in a table with a div below it for displaying the pedido info. Each row in the table has a link to the controller action that will do the AJAX. Use remote: true to make the link AJAX, so the user is not taken to another page.
<table>
<tbody>
<% #pedidos.each do |pedido| %>
<tr>
<td><%= link_to 'More info on this Pedido!' fetch_info_pedidos_path(pedido), remote: true %></td>
</tr>
<% end %>
</tbody>
</table>
<div id="pedido-info"></div>
Make the route for the action in the pedido controller. This is in routes.rb
resources :pedidos do
get :fetch_info, on: :member
end
This should create a path that looks like /pedidos/:id/fetch_info with the name fetch_info_pedidos
The link in the table will make a js format request along this route so the controller action must be ready to handle that. The pedido id will come as a parameter called :id
def fetch_info
#pedido = Pedido.find params[:id]
respond_to :js
end
Since it responds to a js format request it will respond with js content, not html - that means we need to have a js file as the view, but before we make that let's make a partial for displaying pedido info. This can be dropped into any view using the render method. It will be in app/views/pedidos/_pedido.html.erb (you have to use an underscore at the start of the file name to show it is a partial) You can put any content in here you like, using the pedido variable to refer to the pedido. Here's an example:
<h2>Pedido!</2>
<p>number: <%= pedido.id %></p>
<p>nom: <%= pedido.nom %></p>
<p>telefone: <%= pedido.fone%></p>
Finally let's make the js that gets passed back to the browser. This will be an erb file like other views. It will just put the _pedido partial as the content to the div under the table. app/views/pedidos/fetch_data.js.erb
$('#pedido-info').html("<%= j render #pedido %>");
That's all you need. The j here escapes the output of the render method so that it plays nicely inside a javascript string.
There's a bit of Rails magic happening here, which I will explain, because, as you would learn at any wizard training school: "don't use any magic you don't completely understand"
The render method expects the name of a partial to render, and optionally some local variables to pass. If it's given only an ActiveRecord object, it will look for the partial that matches the class name of the object (Pedido goes to _pedido.html.erb) and it passes the object as a local variable also with matching name. so render #pedido gets translated to render partial: 'pedido', locals: {pedido: #pedido}
I haven't tried any of the code in this answer, I just wrote it off the top of my head, so you may have to jiggle it a bit to get it to work.
here's a link to a page you might have come across if you had simply Googled how to do this. It says essentially the same as what I have said here, except his AJAX brings in a whole collection of objects, not just one at a time.
I may have misunderstood the question, but it seems to me you just need to link to the detalhes action for each pedido in the table.
here is the table:
<table>
<tbody>
<% #pedidos.each do |pedido| %>
<tr>
<td><%= link_to 'Detalhes this Pedido!' detalhes_path(pedido) %></td>
<td>More table data related to this pedido</td>
</tr>
<% end %>
</tbody>
</table>
and in the routes you would have something like this:
resources :pedidos do
get :detalhes, on: :member, as: 'detalhes'
end
I have a text field "tf_Designation" in a view page, see below:
<% form_for(:search) do |f| %>
<table>
<tr>
<td align="center">
<%= f.text_field :tf_Designation,placeholder: "Designation" %>
</td>
</tr>
</table>
<% end %>
I want to get text field value into a controllers page and I am doing like below:
def search
#blah=params[:search][:tf_Designation]
if !params[:search][:tf_Designation].blank?
#Designation = params[:search][:tf_Designation]
render '/index'
end
end
And I do not have search model. But it gave me error at this line #blah=params[:search][:tf_Designation]. The error is below:
undefined method `[]' for nil:NilClass
Kindly suggest me where I make mistake, waiting for your reply. Thanks
It's most likely an issue with how Rails processes form_for - we've only ever used instance variables with it (which can be populated by a resource):
form_for
Form helpers are designed to make working with resources much easier
compared to using vanilla HTML.
Typically, a form designed to create or update a resource reflects the
identity of the resource in several ways
(i) the url that the form is
sent to (the form element's action attribute) should result in a
request being routed to the appropriate controller action (with the
appropriate :id parameter in the case of an existing resource)
(ii)
input fields should be named in such a way that in the controller
their values appear in the appropriate places within the params hash,
(iii) for an existing record, when the form is initially
displayed, input fields corresponding to attributes of the resource
should show the current values of those attributes.
form_tag
I would highly recommend switching to form_tag, as this deals with perishable data:
#app/views/elements/_search.html.erb
<%= form_tag "/search" do %>
<%= text_field_tag :tf_Designation, nil, placeholder: "Designation" %>
<%= submit_tag "Search" %>
<% end %>
#app/controllers/your_controller.rb
def search
#designation = params[:tf_Designation]
unless #designation.blank?
render '/index'
end
end
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"
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!
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.