I want to render my form partial in javascript erb file. When I place it in there it gives me a no method error. Any ideas?
script.js.erb
$(document).ready(function() {
$(".enquiry-button").click(function(e) {
e.preventDefault();
e.stopPropagation();
if ($(this).parents('.cell').find('form').length == 0) {
$(this).closest('.cell').append(
"<div class='enquiry-form'>" +
"<%= escape_javascript( render '/static/form' ) %>" +
"</div>");
$(this).closest('.cell').find(".enquiry-form:last").slideDown("slow");
} else {
$(this).closest('.cell').find(".enquiry-form:last").slideToggle("fast");
}
});
});
_form.html.erb
<%= simple_form_for #user do |f| %>
<%= f.error_messages %>
<%= f.input :email %>
<%= f.button :submit %>
<% end %>
error
NoMethodError in Static#home
Showing /Users/colton/kitchen_ninja/kitchen_ninja/app/views/layouts/application.html.erb where line #6 raised:
undefined method `render' for #<#<Class:0x007f90cc875c80>:0x007f90cd2017e0>
(in /Users/colton/kitchen_ninja/kitchen_ninja/app/assets/javascripts/script.js.erb)
Extracted source (around line #6):
You are mixing two separate things together. Your render needs to run on the server. JavaScript's job is just to make an AJAX request and get a resource.
So, supposed you were to to this:
$.ajax(url: "/test").done(function(html) {
$("#results").append(html);
});
AJAX's only role is to grab a remote resource and parse the results.
In Ruby, you can use render to emit the HTML:
<%= escape_javascript( render '/static/form' ) %>
Just make sure you point the AJAX request to the right resource so Ruby can do the rest of the magic.
Since you are pre-processing the script with .erb, you could use Ruby's string interpolation to return the partial as a string literal in the JavaScript file.
html = "<div class='enquiry-form'>" +
"#{j render partial: 'static/form'}}" +
"</div>"
$(this).closest('.cell').append( html );
Related
I am hoping someone can help me here. Been at this for a few hours, but can't seem to figure out why my Javascript is not working on my simple form. I'm simply trying to display comments using the ajax call. I have gem 'jquery-rails', and required jquery, and jquery_ujs in my application.js file. Here's the code I have so far:
I have a Joy model that has_many comments.
<% #joys.each do |joy| %>
<ul id="comments-<%= joy.id %>">
<% joy.comments.where(void:'f').each do |comment| %>
<li><%= comment.body %></li>
<% end %>
</ul>
<%= form_with(model: [ joy.user, joy, joy.comments.build ], data:{ "js-comments-#{joy.id}" => true}) do |f| %>
<%= f.text_area :body, :class=>'form-control', :required=>'true' %>
<%= f.submit "Post Comment" %>
<% end %>
<script>
$(document).ready(function() {
$('[data-js-comments-<%= joy.id %>]').on("ajax:success", function(event, data, status, xhr){
$('#comments-<%=joy.id%>').append(xhr.responseText);
});
});
</script>
<% end %>
In my Comment controller, in my 'create' action, I have:
if #comment.save
render partial: "comment", locals: {comment: #comment}
end
In my Comment views, I created a partial, called _comment.html.erb:
<li>
<%= comment.body %>
</li>
So, now when I enter a comment, and click 'Post Comment', it correctly saves my Comment, but it does not ajax load the comment into list. Furthermore, the form does not refresh either. The text remains in the text box. It is not only until after I refresh the page when my comment shows up in the list. Anyone with any thoughts on what I'm missing or doing wrong???
Your help is greatly appreciated in advance.
form_with it's a remote form, you dont need that block <script>..</script>.
Just use create.js.erb then use jquery to append new comment.
And if you want to check if your message was created successfully, you can add a #status value in your controller.
//comments_controller.rb
def create
...
if #comment.save
#status = "success"
else
#status = "failed"
end
...
end
//create.js.erb - for example
$("#yourCommentList").append('<%= j( render partial: 'comments/comment', locals: #comment ) %>');
<% if #status == "success" %>
$("body").append(...your notification...)
...
<% else %>
...
<% end %>
I'm trying to set up my form so that when the user changes the "position" drop down box selection it will update a partials with records that are related to that position. I will do my best to include all relevant code below with the error shown first. If I've forgotten to include anything please let me know, thanks.
Error (from the... jqXHR.responseText)
AJAX Error: NameError in Players::Reports#update_position_specifics
Showing ../app/views/players/reports/update_position_specifics.js.erb where line #2 raised:
undefined local variable or method `f' for #<#<Class:0x007f9b82ebdcf8>:0x007f9b82fc8030>
reports.coffee
$(document).on 'change', '#report_position_id', (evt) ->
$.ajax 'update_position_specifics',
type: 'GET'
dataType: 'script'
data: {
position_graded_id: $("#report_position_id option:selected").val()
}
error: (jqXHR, textStatus, errorThrown) ->
console.log("AJAX Error: #{jqXHR.responseText}")
success: (data, textStatus, jqXHR) ->
console.log("Dynamic position select OK!")
_form.html.erb
<%= simple_form_for([#player, #report], html: {id: 'report-form'}) do |f| %>
<%= f.association :position, selected: #position_graded.id %>
<div id="position_specifics">
<%= render 'form_position_specifics', f: f %>
</div>
<% end %>
_form_position_specifics.html.erb
<%= f.nested_fields_for :evaluations,
f.object.evaluations.target.sort_by! { |a| a.skill.order_by },
wrapper_tag: :tr, wrapper_options: { class: 'fields' } do |fn| %>
<% # Form fields here... %>
<% end %>
update_position_specifics.js.erb
$("#position_specifics").empty().append("<%= escape_javascript(render partial: 'form_position_specifcs', f: f") %>")
reports_controller.rb
def update_position_specifics
# remove previous/existing position specific skill from evaluations
#report.evaluations.joins(:skill).where(skills: { type: 'position specifcs'}).delete_all
# add new position specifics from specified position
#skills = Skill.joins(:positions).where(position_id: #position_graded.id)
# Add new evaluations to report
#skills.joins(:positions).where(positions: {id: #position_graded_id}, disabled: false).each do |skill|
#report.evaluations << Evaluation.new(skill_id: skill.id
end
end
Updated Answer
views/posts/new.html.erb
<%= form_for(#post, id: 'myform') do |f| %>
<%= f.association :pictures do |ff| %>
<% target = "picture-#{ff.object.id}-div-that-will-updated" %>
<%= ff.select :category, 'data-target': target %>
<%= ff.file_field :file %>
<!-- This is the element that will be updated when <select> above is changed -->
<div id='<%= target %>'></div>
<% end %>
<% end %>
javascripts/posts/new.js
$('#myform').find('select').change(function() {
// get the data-target of the <select>, then load that target element with the new partially loaded (current url) target element
$( '#' + $(this).attr('data-target') )
.load( window.location.href + ' #' + $(this).attr('data-target') );
// Take note of the space in ' #' above
}
In summary, what this all will do is when a user selects from a dropdown, the page is just reloaded. But instead of reloading the whole page, only the data-target element is updated. This also works for multiple nested associated records on the page.
I have the ff:
app/views/reports/index.html.erb
<h1>Reports</h1>
<br>
<legend>Categories</legend>
<div class="row">
<div class="span5">
<ol>
<li><%= link_to 'COMMENDATION', commendations_path(format: 'pdf'), { id: 'commendations_click' } %></li>
<%= collection_select(nil,
:employee_id,
#employees,
:id,
:last_name,
{:prompt => "Select an Employee"},
{:id => 'employees_select'}) %>
<br>
<%= collection_select(nil,
:employee_movement_id,
#employeemovements,
:id,
:position,
{:prompt => "-"},
{:id => 'employee_movements_select'}) %>
<li><%= link_to 'REPORT2', '#' %></li>
<li><%= link_to 'REPORT3', '#' %></li>
</ol>
</div>
</div>
<script type="text/javascript">
$(document).ready(function() {
$('#employees_select').change(function() {
$.ajax({
url: "<%= update_employee_movements_path %>",
data: { employee_id : $('#employees_select').val() },
dataType: "script"
});
});
$('#commendations_click').click(function() {
$.ajax({
url: "<%= commendations_path %>",
data: {
employee_id : $('#employees_select').val(),
employee_movement_id : $('#employee_movements_select').val()
},
dataType: "script"
});
});
});
</script>
app/controllers/reports_controller
class ReportsController < ApplicationController
before_filter :authenticate_user!
# GET /reports
def index
#employees = Employee.all
#employeemovements = EmployeeMovement.distinct_positions
end
def update_employee_movements
if params[:employee_id]
#employeemovements = [].insert(0, "Select Employee Movement")
else
employee = Employee.find(params[:employee_id])
#employeemovements = employee.employee_movements.map{ |a| [a.position, a.id] }.insert(0, "Select Employee Movement")
end
end
def commendations
emdates = EmployeeMovement.last_2_dates_obtained(params[:employee_movement_id])
date_from = emdates[0].date_obtained
date_to = emdates.length == 1 ? nil : emdates[1].date_obtained
emp = Employee.find(params[:employee_id])
#commendations = case date_to.nil?
when true then emp.commendations.this_day_onwards(date_from)
else emp.commendations.within(date_from, date_to)
end
end
end
What I'm trying to do here is, I'm creating a page filled with links and drop down lists that will serve as a Reports center. The idea is, each link will be catered by a controller. Each controller will be responsible in showing my PDF in the browser (through ThinReports, if you're curious).
The #employees_select change event is used for changing the value of the #employee_movements_select collection_select.
Now my problem is, how can i capture the value of both #employees_select and #employee_movements_select and pass them to my commendations action?
I tested link_to by hardcoding values, and it works (code below)
<%= link_to 'COMMENDATION', commendations_path(employee_id: 1, employee_movement_id: 12, format: 'pdf') %>
However, If I use javascript to push the values to my commendations action through the 'click' event, my commendations action will be called twice, thus an error occurs because the params[:employee_id] in the action is now blank.
By the way, I need those values because my commendations action needs it so I can populate my PDF report template.
Please help. Thanks a lot in advance!
UPDATE 1
-> Updated link_to:
<%= link_to 'COMMENDATION', '#', { id: 'commendations_click' } %>
-> Removed dataType: "script" in #commendations_click event handler
-> Updated url: in #commendations_click event handler
url: <%= commendations_path(format: 'pdf') %>
UPDATE 2 (RESOLUTION)
I tweaked my javascript to look something like this:
$('#commendations_click').click(function() {
event.preventdefault();
window.location = "<%=j commendations_path(format: 'pdf') %>" + "?employee_id=" + $('#employees_select').val() + "&employee_movement_id=" + $('#employee_movements_select').val();
});
Works perfect now.
Two things come to mind. You can wrap the two select lists within a form element and just do a submit. Everything inside the form will be submitted to your server and you can process the request and handle the redirect on the server side. The other thing you can do is to handle the commendations click event on the client side using jquery or something. Just bind to the click event of that link, grab the values of the two select lists and do whatever you want with it. Remember, link_to just gets rendered as plain old html links on the view. For e.g.
link_to "Profile", profile_path(#profile) gets rendered as Profile
The app in question utilizes jQuery to do ajax requests in order to populate dependent select boxes. My controller action responds_to :js, and in the .js.erb file I have:
str += '<%= f.select field.name, list, {}, { :class => "list", :multiple => "multiple", :style => "size:8; width:100px;" } %>';
"list" is populated like so:
str += '<% list = #validation_model.lookup([field], #lookup) %>';
I am .append()'ing this to a div. at the end of the .js.erb template file. However, when "list" contains more than one value, the parsing of the template fails. If it is empty, or contains only one value, parsing is successful.
Is this a bug I am running into, or am I doing something wrong? Please note this is appearing as a parse error rather than a runtime error, so I have been unable to determine exactly what the problem is in either Firebug or Safari Dev.
UPDATE: Here is the full code of the .js.erb file. I have replaced the "list" variable with inline logic to retrieve an array.
str = '<% fields_for :mapapps do |f| %>';
<% for tf in #tag.tag_fields.find(:all, :order => :sequence) %>
<% field = tf.parentfield %>
<% if !#lookup.include?(field) %>
$("#<%= field.name %>").remove();
<% else %>
<% next %>
<% end %>
str += '<div id="<%= field.name %>" class="floater">';
str += '<label for="mapapps_<%= field.name %>"><%= field.label %></label>';
str += '<%= f.select field.name, #validation_model.lookup([field], #lookup), {}, { :class => "list", :multiple => "multiple", :style => "size:8; width:100px;" } %>';
str += '</div>';
<% end %>
str += '<% end %>'
$("#mfrsdiv").append(str);
I think you are under the impression that eruby items can be appended to the string and will be calculated in the view. Actually the eruby items are calculated in .js.erb file itself and then appended to the string. In your code, f must be the form variable from the view..it will not have value in the .js.erb file. If you really want to add this select to the form, you should be thinking of a partial and using Ajax.
I got the code working. All I needed to do was to put "escape_javascript" around the call to f.select.
str += '<%= escape_javascript(f.select field.name, #validation_model.lookup([field], #lookup), {}, { :class => "list", :multiple => "multiple", :style => "size:8; width:100px;" }) %>';
It should be noted that the code in my question above will still fail for the reasons mentioned rubyprince, but the rendering issue itself is solved by the escape_javascript.
Tried doing http://davidwparker.com/2008/09/17/site-wide-announcements-in-rails-using-jquery-jgrowl/
Am really bad with JS. Think I am messing up on the last part where it says "This code goes in your application.js file (somewhere in $(function){ //here })"
Am I not suppose to do a link_to_function and create a function with this code that references that link?
Really lost on this one.
Updated -
application.js looks like
$(document).ready(function() {
$.jGrowl.defaults.closer = true;
$("#announcements_box").css("display", "none");
$("#announcements_box .announcement").each(function(){
$jQuery.jGrowl(this.textContent,{ sticky:true, close:function(e,m,o){hide_announcements();} });
});
});
function hide_announcements(){
$.get(
'/hide_announcements'
);
$("#announcements_box").fadeOut();
return false;
}
And my application.html.erb has
<% unless current_announcements.empty? %>
<div id="announcements_box">
<% for announcement in current_announcements %>
<div id="announcement_<%= announcement.id.to_s %>" class="jGrowl">
<%= announcement.message %>
<%= link_to "Hide Annoucements", hide_announcements_path, :id => 'hideAnn'%>
</div>
<% end %>
</div>
<% end %>
I'm not sure what $(function){ //here } notation means, that should give you error in the browser, but I think he just wants to execute code after page is loaded:
$(document).ready(function() {
// here
}
And the culprit was I only entered a div ID when I needed to have a div ID and class.