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.
Related
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.
I am running into issues trying to separate a form from a view into a partial. I want to use the same form for the new and edit views. These are both on the same page. The new model form is at the top of the page and uses a variable that I set in the controller.
<%= form_for #new_hire do |f| %>
<%= render :partial => 'new_hire_requests/form', :locals => {:f => f} %>
<% end %>
I then have a partial for the pending approvals that gets rendered by another partial
<%= render :partial => 'pending_approval', :collection => #pending_approval %>
And inside the pending approval partial I have this
<%= form_for pending_approval do |f| %>
<%= render :partial => 'new_hire_requests/form', :locals => {:f => f} %>
<% end %>
This is throwing an error
undefined method `new_hire_request_path' for #<#<Class:0x0000010488ac98>:0x0000010223ffc0>
Is there a way to re use the form code for both a new and edit form on the same page?
Controller Logic
#new_hire = NewHireRequest.new
#new_hire_requests = current_user.new_hire_requests
#pending_approval = #new_hire_requests.select{|p| p.status == 'pending_hr_approval' || p.status == 'pending_exec_approval'}
Partial code
<%= render 'shared/error_messages', object: f.object %>
<fieldset class="first">
<%= f.label :first_name, "First Name" %>
<%= f.text_field :first_name %>
</fieldset>
<fieldset>
<%= f.label :last_name, "Last Name" %>
<%= f.text_field :last_name %>
</fieldset>
<%= f.submit "Submit for Approval <i class='icon-share-alt icon-white'></i>",
class: "button_green" %>
add resources new_hire_requests in the routes and get done with it .
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.
Update: I updated this after doing some digging and realizing that this might be twitter-bootstrap causing the problem.
Here is a rough version of my nested form:
<%= simple_nested_form_for #user, :html => { :class => 'form-horizontal' } do |f| %>
<fieldset>
<%= f.input :email %>
<%= f.input :name_first %>
<%= f.input :name_last %>
<table class="table table-striped">
<thead>
<tr>
<th>Active</th>
<th>Company</th>
<th>Role</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<%= f.simple_fields_for :roles, :wrapper_tag => :tr do |role_form| %>
<td><%= role_form.hidden_field :id %><%= role_form.input :active, :label => false, :wrapper => false %></td>
<td><%= role_form.association :company, :label => false, :wrapper => false %></td>
<td><%= role_form.input :role, :label => false, :collection => [ "Guest", "User", "Inspector", "Owner"], :wrapper => false %></td>
<td><%= role_form.link_to_remove "Delete", :class => 'btn btn-mini btn-danger' %>
</td>
<% end %>
</tbody>
</table>
<p><%= f.link_to_add "Add a Role", :roles %></p>
</div>
<div class="form-actions">
<%= f.submit nil, :class => 'btn btn-primary' %>
<%= link_to 'Cancel', users_path, :class => 'btn' %>
</div>
</fieldset>
<% end %>
When it's rendered the fields in the table rows are indented the same as the parent form via the { :class => 'form-horizontal' }. I just want the fields with no wrapper divs etc. and can't seem to figure it out. I thought the :wrapper => false was the ticket but no luck so far.
Dan
I ended up figuring it out on my own. You have to move the form style (form-horizontal) into a div just around the non-nested fields:
<%= simple_nested_form_for #user do |f| %>
<fieldset>
<div class="form-horizontal">
<%= f.input :email %>
<%= f.input :name_first %>
<%= f.input :name_last %>
<%= f.input :phone %>
<%= f.input :mobile %>
<%= f.input :password %>
<%= f.input :password_confirmation %>
</div>
<div class="tubbable">...
If you want to use a table (as in your initial example) to do the layout, I've patched the nested_form gem here https://github.com/ritchiey/nested_form to allow that.
To specify that you want the new fields appended at the bottom of the tbody and wrapped in a tr, replace your current link_to_add call with:
<%= f.link_to_add "Add a Role", :roles, :container =>'tbody', :fields_element=>'tr'%>
Note: the :container param is a CSS selector.
Not sure if this is what you want, but if you want to remove the div wrapper from an input field, use f.input_field instead of f.input:
= f.input_field :email, label: false, placeholder: 'email'
Add :wrapper => false to the simple_nested_form_for call.
The problem is, that :wrapper => false in simple_fields_for gets overwritten by the default :wrapper => nil in the simple_form_for configuration.
See this link for a setup:
How To: Render nested fields inside a table
In my app use tinymce editor and the problem is that the form send empty textarea. When I remove Tinymce from this form, so everything's working well.
<%= form_tag({ :controller => 'home', :action => 'process_note' }) do %>
<%= hidden_field_tag 'user_id', #user_note.id%>
<div style="width: 800px;">
<div>Your note:</div>
<div>
<%= text_area_tag 'new_note', #user_note.note, :class => 'mceEditor text', :style => 'width: 700px;height: 250px;' %></td>
</div>
<div>
<%= submit_tag "Save" %>
</div>
</div>
<% end %>
Have anyone a similar experience with this behavior? I have already no idea, where could be a problem