re render fields_for with ajax - ruby-on-rails-3

I have a problem refreshing a partial with fields_for inside.
Here is the code of the partial ('table_detalle')
<table class="table">
<thead>
<tr>
<th><%= t('.denominacion') %></th>
<th><%= t('.cantidad_ingreso') %></th>
<th><%= t('.importe') %></th>
</tr>
</thead>
<tbody>
<%= f.fields_for :operacion_detalles do |builder| %>
<tr>
<%= render 'table_detalle_operacion', f: builder %>
</tr>
<% end unless #operacion.nil? %>
</tbody>
</table>
<%= content_tag :h3, t('.total', :value=> number_to_currency(#operacion.R_IMPORTE)).html_safe, :class => 'pull-right', style: 'display:inline' %>
when the user change a value of a combo i would like to refresh the partial above (because the details objects must change and are editable)
Here is the javascript code:
$('#operacion_TIPOVALOR_ID').change(function(){
$.ajax({
url: '<%= cambiar_tipo_valor_movimientos_path %>',
data: {tipo_valor_id: $('#operacion_TIPOVALOR_ID').val()},
complete: function(){
$('#tipo_valor_loader').css('display','none');
},
beforeSend: function(){
$('#tipo_valor_loader').css('display','inline');
},
success: null,
dataType: 'script'
});
});
the controller code:
def cambiar_tipo_valor
#operacion = Operacion.new
denominaciones = TipoValorDenominacion.all_from_tipo_valor params[:tipo_valor_id]
denominaciones.each do |deno|
#operacion.operacion_detalles.build :tipo_valor_denominacion => deno, :I_CANTIDAD => 0, :R_IMPORTE => 0
end
end
as you can see the "operacion_detalles" change depending on the user selection.
the .js.erb code:
$('#detalle').html('<%= escape_javascript(render :partial => 'table_detalle') %>');
But, i get:
undefined local variable or method `f' for #<#<Class:0x45ae1c8>:0x5062338>
So, i need the f variable to render the partial. Is there any way to emulate the f variable?
Thanks in advance.

I had no other choice than resolve the problem by hand. What i mean?
Instead of a field_for => each_with_index:
<% #operacion.operacion_detalles.each_with_index do |detalle, index| %>
<tr>
<%= render 'table_detalle_operacion', detalle: detalle, index: index %>
</tr>
<% end -%>
The use the tags helpers like this:
<td>
<input type="hidden" value="<%= detalle.tipo_valor_denominacion.R_MULTIPLICADOR %>" class="multiplicador"/>
<%= hidden_field_tag "operacion[operacion_detalles_attributes][#{index}][TIPOVALORDENO_ID]", detalle.TIPOVALORDENO_ID %>
<%= detalle.tipo_valor_denominacion.CTIPOVALORDENO %></td>
<td>
<%= text_field_tag "operacion[operacion_detalles_attributes][#{index}][I_CANTIDAD]", detalle.I_CANTIDAD %>
<%= content_tag(:span, detalle.errors[:I_CANTIDAD].join(', '), class: 'help-block') if detalle.errors.has_key? :I_CANTIDAD %>
</td>
<td>
<%= hidden_field_tag "operacion[operacion_detalles_attributes][#{index}][R_IMPORTE]", detalle.R_IMPORTE %>
<%= content_tag :span, number_to_currency(detalle.R_IMPORTE), class: 'detalle-importe pull-right' %>
<%= content_tag(:span, detalle.errors[:R_IMPORTE].join(', '), class: 'help-block') if detalle.errors.has_key? :R_IMPORTE %>
</td>
In this case i had supply the names, so when this code is executed
$('#detalle').html('<%= escape_javascript(render :partial => 'table_detalle') %>')
It does not need the f variable.
Hope it helps.
pd: I know this is not a very good solution but it works.

Related

Rails Passing Object to Form Partial

rails 5, ruby 2.5
I'm trying something new for me. In my head it makes sense but it is not working. I want to put a <form> tag on my new and edit views, then call a partial, which has the rest of the form. I'm passing in the "instance variable" (correct term?) f using :locals, but it is not recognized in the partial.
# new.html.erb
<% #page_title = "New Food Entry" %>
<%= form_for(#food) do |f| %>
<%= render "form", :locals => { :f => f } %>
<% end %>
# _form.html.erb
<table cellpadding="2" cellspacing="0" style="border: 1px solid #369;" summary="Edit or new Food Record">
<tr>
<td><label>Food Name</label></td>
<td><%= f.text_field :food_item, :size => 30 %></td>
</tr>
...
When I load .../foods/new, I get this error:
undefined local variable or method `f' for #<#<Class:0x00007fdb4c036428>:0x00007fdb342a3890
Any tips would be much appreciated.
According to the Rails docs. Please use <%= render partial: "form", :locals => { :f => f } %> or <%= render "form", :f => f %> syntax.

Added submit button calls the earlier button's function itself

I'm working on Rails 3 app. Here a view displays all the excel files uploaded by user. A button to execute all the checkbox selected files was already present with delete for each file separately. Now I'm supposed to add a 'delete' button to delete the selected files. I've added the button n modified the function called by this form jus to display "in execute" and "in delete" for now to check if the second 'delete' button is functioanal. But every time delete is clicked it prints "in execute" only in cmd. I guess the AJAX related code written in the view 'list' is the problem.
Pls help!! Tell me why is it going to execute always?
The related code is here:
PS: I hav used if params[:commit]="Delete" & if params[:delete_button] also in controller.rb to but didnt help
list.html.erb (the view that displays all files)
<% if #files.length > 0 %>
<h2 id='comments'>Uploaded Excel Files are as listed below for Edit/Delete/Execution</h2>
<div id='checkone' class='hide'>Please check atleast one excel file to execute</div>
<% ajax_str = "new Ajax.Request('/account/execute_testcases', {asynchronous:true, evalScripts:true, onComplete:function(request){adjust_sidebar();Element.show('msg');Element.hide('waitid');Element.hide('disableexecuteid');Element.show('executeid');}, onLoading:function(request){Element.show('waitid');Element.hide('msg');Element.hide('executeid');Element.show('disableexecuteid');}, parameters:Form.serialize(this)}); return false;".html_safe %>
<%= form_for 'file_names', :url => {:controller => 'account', :action => 'execute_testcases'}, :remote => true, :html => {:name => 'frmExecute', :onsubmit => ajax_str }, :id =>'execute_tc' do |f| %>
<table>
<% if #file_count > 1 && #error_in_all_files == false %>
<tr>
<td>
<input type='checkbox' name='chkAll' onclick='checkAll();'>
<span class='text'>Check All/Decheck All</span>
</td>
</tr>
<% end %>
</table>
<table class='upload'>
<% for a in #files %>
<tr>
<td>
<% file_id = a.id.to_i %>
<% if(#excel_errors[file_id].nil? || #excel_errors[file_id].empty?) && a.file_type.to_i != 1 %>
<input type='checkbox' name = "excelfile[]" value="<%= a.excel_filename %>,<%= a.excel_filename_with_timestamp %>">
<% else %>
<input type='checkbox' name = "excelfile[]" value="<%= a.excel_filename %>,<%= a.excel_filename_with_timestamp %>" disabled=true>
<% end %>
<a href="open_excel_file/<%= a.id %>" title='Click to open' class='nodecoration'><%= a.excel_filename %></a>
</td>
<td>
<%= link_to(image_tag("/images/b_edit.png", :border => 0, :title => 'Edit'), :action => 'upload_file', :file_id => a.id) %>
</td>
<td>
<img src='/images/b_drop.png' border=0 title='Delete' onclick="return confirm('This will delete the related reports too. Are you sure to delete?');">
</td>
<td>
<%
if !#excel_errors[file_id].nil? && !#excel_errors[file_id].empty?
#joined_excel_errors = #excel_errors[file_id].join(', ')
%>
Error
<% end %>
</td>
</tr>
<tr id="excel_error_<%=file_id %>" style='display:none;'>
<td colspan=4>
<% if !#excel_errors[file_id].nil? && !#excel_errors[file_id].empty? %>
<div class="padder">
<% for error_value in #excel_errors[file_id] %>
<font color='maroon'><%= error_value %></font><br>
<% end %>
</div>
<% end %>
</td>
</tr>
<% end %>
<tr><td> </td></tr>
<tr>
<td>
<% if #error_in_all_files == false %>
<span class='executebutton' id='executeid'>
<%= f.submit "Execute", name: 'execute_button', :onclick =>"return checkSelected();" %>
</span>
<span class='deletebutton' id='deleteid'>
<%= f.submit "Delete", name: 'delete_button', :onclick =>"return checkSelected();" %>
</span>
<% end %>
<span id='disableexecuteid' class='executebutton' style='display:none;'>
<input type='submit' value="Execute" disabled="disabled">
</span>
<span id='waitid' style="display:none;" class='text'>
<br>Executing Test Cases...Please wait...<%= image_tag("/images/wait26trans.gif", :border => 0) %>
</span>
<span id='msg' style="display:none;" class='text'>
<br><br> Click here to <%= link_to 'View Test Results', {:controller => 'account', :action => 'recent_test_results'}, :class => 'brownlink' %>
</span>
</td>
</tr>
</table>
<span id='subject_list'>
</span>
<% end %>
<% else %>
No test case sheets found!
<br><br>
<%= link_to '>> Upload File', {:controller => 'account', :action => 'upload_file'}, :class => 'brownlink' %>
<% end %>
<% for i in 1..10 %>
<div> </div>
<% end %>
controller.rb
def execute_testcases
if !params[:execute_button].nil?
puts "in execute"
# file_names = []
# originalfile_filewithtime = []
# original_file_map = {}
# originalfile_filewithtime = params[:excelfile]
......
# SOME CODE HERE
......
# render :update do |page|
# page.replace_html :subject_list, :partial => 'show_output', :locals => {:new_file_map => #new_file_map}
# page.visual_effect :highlight, 'subject_list', :duration => 2
# flash[:display]=#execmsg
#end
# puts #execmsg
elsif !params[:delete_button].nil?
puts "in delete"
end
end
I realised it had to do something with the Form.serialize(this) of AJAX which serialises everything. ie It calls the function of first button in the view irrespective of no of submit buttons present

NoMethodError in Users#show

Everytime I try and access the user profile page, I get this error.
ActionView::Template::Error (undefined method `email' for nil:NilClass):
2: <tr>
3: <td class="main">
4: <h1>
5: <%= gravatar_for #user %>
6: <%= #user.name %>
7: </h1>
8: </td>
app/helpers/users_helper.rb:4:in `gravatar_for'
app/views/users/show.html.erb:5:in `_app_views_users_show_html_erb__222181804_33777120'
Below is what my users.controller.rb file looks like.
def show
#user = User.find(params[:id])
#microposts = #user.microposts.paginate(:page => params[:page])
#title = #user.name
For additional reference, below is a copy of my show.html.erb file.
<table class="profile" summary="Profile information">
<tr>
<td class="main">
<h1>
<%= gravatar_for #user %>
<%= #user.name %>
</h1>
</td>
<td class="sidebar round">
<strong>Name</strong> <%= #user.name %><br />
<strong>URL</strong> <%= link_to user_path(#user), #user %>
</td>
</tr>
</table>
Also provided is my users_helper.rb file.
module UsersHelper
def gravatar_for(user, options = { :size => 50 })
gravatar_image_tag(user.email.downcase, :alt => h(user.name),
:class => 'gravatar',
:gravatar => options)
end
end
The error is in your helper method. Please verify that the #user object is not nil.
Then in your view change the line number 5 like this:
<%= gravatar_for(#user) %>
define your users_helper#gravatar_for method like this
def gravatar_for(#user)
..........
#user.email
..........
rerurn somthing #if you want
end

Hidden fields, creating local instance variable in the view, GOOD or BAD?

This is my partial:
<%= form_for(item, :url => update_cart_path) do |item_form| %>
<tr>
<% #variant = item.variant %>
<%= hidden_field(:variant, :id) %>
<td width="300"><%=item.variant.product.name%> <%= "(" + variant_options(item.variant) + ")" unless item.variant .option_values.empty? %></td>
<td class="price"><%= number_to_currency item.price %></td>
<td class="qty"><%=item.quantity%></td>
<td class="total"><span><%= number_to_currency (item.price * item.quantity)%></span></td>
<td class="edit"><%= link_to(image_tag('/images/admin/icons/edit.png'), '#', :class => 'edit') %>
</td>
</tr>
<% end %>
And I'm calling it as follows:
<%= render :partial =>'shared/cart/line_item' , :collection => #order.line_items, :as => :item %>
I have to create a local variable #variant for the hidden_field to work, and because it doesn't make any sense creating it in the controller, I have created the instance local variable in the view.
Is there a better design for this?
If you are only doing that for the hidden_field helper to work, you can use hidden_field_tag instead:
<%= hidden_field_tag('variant', item.variant.id) %>

Observe_field in Rails 3

I am trying to accomplish an observe_field in rails 3.
In rails 2.3.5 I have :-
<%= observe_field 'query', :frequency => 2,
:update => "search_results",
:url => {:controller => params[:area], :action => "search",:area => params[:area]},
:method=>:get,
:with => "query" %>
Which works fine, checking my text_field_tag "query" and updating my "search_results" every two seconds. This is what I am trying to simulate using prototype.
At the moment I have in a basic application in Rails 3:-
<script>
document.observe("dom:loaded", function() {
$('search').observe('change',
respondToChange());
});
</script>
or
<script>
document.observe("dom:loaded", function() {
new Form.Element.Observer(
'search',
1,
respondToChange()
) });
</script>
Both of which triggers the respondToChange function when the page loads, despite the "dom:loaded", and then does not observes anymore.
Does anyone have any idea of how I might obtain the repeated observer checks on my "search" text_field_tag.
I think I have now solved the problem of doing an ajax call via programming. I will have to check it out in all types of browsers, but at the moment it is working in Firefox and Safari. I have now also moved both javascript "document.observe("dom:loaded" and the function it calls "respondToChange()" to the application head with content_for. All other files remain the same.
In my index.html.erb I now have:-
<h1>Listing homepages</h1>
<div id = "testsearch">
<%=render :partial => 'homepage'%>
</div>
<%= form_tag homepages_path, :method => 'get', :remote => true do %>
<%= label_tag(:search, "Search for:") %>
<%= text_field_tag :search, params[:search]%>
<%= submit_tag "search", :name => nil %>
<%end%>
<%= set_focus_to_id 'search' %>
<% content_for :search_javascript do %>
function respondToChange() {
var pars = 'search=' + $('search').getValue()
new Ajax.Request("<%= homepages_path %>" ,{
method: 'get',
parameters: pars
});
};
document.observe("dom:loaded", function() {
new Form.Element.Observer(
'search',
2,
respondToChange
)
});
<% end %>
<br />
<%= link_to 'New Homepage', new_homepage_path %>
In my application layout file I now have:-
GardenR3
<%= stylesheet_link_tag :all %>
<%= javascript_include_tag :defaults %>
<%= csrf_meta_tag %>
<script>
<%= yield :search_javascript %>
</script>
</head>
<body>
<%= yield %>
</body>
</html>
Here is my full code if anyone is interested. This code observes the text_field_tag "search" every 2 seconds, and if there is a change in the value, it triggers a search automatically. The submit button can now be done away with, I think. I might add :autocomplete => "off", :onKeyPress=>"return disableEnterKey(event)") %> to the text_field_tag to disable the return key, not sure.
In my index.html.erb I have:
<h1>Listing homepages</h1>
<div id = "testsearch">
<%=render :partial => 'homepage'%>
</div>
<%= form_tag homepages_path, :method => 'get', :remote => true do %>
<%= label_tag(:search, "Search for:") %>
<%= text_field_tag :search, params[:search]%>
<%= submit_tag "search", :name => nil %>
<%end%>
<%= set_focus_to_id 'search' %> // I have a helper "set_focus_to_id"
<script>
document.observe("dom:loaded", function() { // ensures the page is loaded first
new Form.Element.Observer( // Observes the text_field_tag every 2 seconds
'search',
2,
respondToChange //refrences the function in the Layout <head>
) // on a change in search calls respondToChange
});
</script>
<br />
<%= link_to 'New Homepage', new_homepage_path %>
In my application Layout head I have:
<script>
function respondToChange() {
$('search').up('form').submit() // The ".up finds the form in the DOM"
};
</script
In my controller#index I have:
def index
#homepages = Homepage.search(params[:search]) //".search method is in the Model"
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #homepages }
format.js
end
end
In my Model I have:
def self.search(search_item)
if search_item
self.where('section LIKE ?', "%#{search_item}%") //Handles the ajax call.
else
self.all //Handles the html call on startup.
end
end
In the helper I have:
def set_focus_to_id(id)
javascript_tag("$('#{id}').focus()");
end
In the "_homepage" partial I have:
<table>
<tr>
<th>Id</th>
<th>Section</th>
<th>Link</th>
<th>Description</th>
<th></th>
<th></th>
<th></th>
</tr>
<% for homepage in #homepages %>
<tr>
<td><%= homepage.id %></td>
<td><%= homepage.section %></td>
<td><%= homepage.link %></td>
<td><%= homepage.description %></td>
<td><%= link_to 'Show', homepage %></td>
<td><%= link_to 'Edit', edit_homepage_path(homepage) %></td>
<td><%= link_to 'Destroy', homepage, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<%end%>
</table>
And in the index.js.erb I have:
$('testsearch').update("<%= escape_javascript(render :partial => 'homepage') %>");
If anyone has any comments on how I could improve this, please contact me or say so.
With thanks to "themiddleman" and "agnaki" somewhere out there in the ether, I have solved the problem:
Use respondToChange, not respondToChange()
As the parentheses () execute the function, whereas without () it references it.
$('search').observe('change', respondToChange);
// only triggers when the focus is moved away from the text_field.
new Form.Element.Observer(
'search',
1,
respondToChange
) });
//................................repeatedly checks the text_field,every 1 second, and call the function if there is a any change.